How to use addTrappedEventListener method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

DOMPluginEventSystem.js

Source: DOMPluginEventSystem.js Github

copy
1import { DOCUMENT_NODE } from '../../../HTMLNodeType';
2import { IS_NON_DELEGATED, IS_CAPTURE_PHASE } from './EventSystemFlags';
3
4import { getEventListenerSet } from '../client/ReactDOMComponentTree';
5import { allNativeEvents } from './EventRegistry';
6import { createEventListenerWrapperWithPriority } from './ReactDOMEventListener';
7import {
8  addEventCaptureListener,
9  addEventBubbleListener,
10  addEventBubbleListenerWithPassiveFlag,
11  addEventCaptureListenerWithPassiveFlag,
12} from './EventListener';
13
14const listeningMarker = '_reactListening' + Math.random().toString(36).slice(2);
15
16const mediaEventTypes = [
17  'abort',
18  'canplay',
19  'canplaythrough',
20  'durationchange',
21  'emptied',
22  'encrypted',
23  'ended',
24  'error',
25  'loadeddata',
26  'loadedmetadata',
27  'loadstart',
28  'pause',
29  'play',
30  'playing',
31  'progress',
32  'ratechange',
33  'seeked',
34  'seeking',
35  'stalled',
36  'suspend',
37  'timeupdate',
38  'volumechange',
39  'waiting',
40];
41
42const nonDelegatedEvents = new Set([
43  'cancel',
44  'close',
45  'invalid',
46  'load',
47  'scroll',
48  'toggle',
49  ...mediaEventTypes,
50]);
51
52const getListenerSetKey = (domEventName, capture) =>
53  `${domEventName}__${capture ? 'capture' : 'bubble'}`;
54
55const addTrappedEventListener = (
56  targetContainer,
57  domEventName,
58  eventSystemFlags,
59  isCapturePhaseListener
60) => {
61  const listener = createEventListenerWrapperWithPriority(
62    targetContainer,
63    domEventName,
64    eventSystemFlags
65  );
66  let isPassiveListener;
67
68  if (
69    domEventName === 'touchstart' ||
70    domEventName === 'touchmove' ||
71    domEventName === 'wheel'
72  ) {
73    isPassiveListener = true;
74  }
75
76  if (isCapturePhaseListener) {
77    if (isPassiveListener !== undefined) {
78      addEventCaptureListenerWithPassiveFlag(
79        targetContainer,
80        domEventName,
81        listener,
82        isPassiveListener
83      );
84    } else {
85      addEventCaptureListener(targetContainer, domEventName, listener);
86    }
87  } else {
88    if (isPassiveListener !== undefined) {
89      addEventBubbleListenerWithPassiveFlag(
90        targetContainer,
91        domEventName,
92        listener,
93        isPassiveListener
94      );
95    } else {
96      unsubscribeListener = addEventBubbleListener(
97        targetContainer,
98        domEventName,
99        listener
100      );
101    }
102  }
103};
104
105const listenToNativeEvent = (
106  domEventName,
107  isCapturePhaseListener,
108  rootContainerElement,
109  targetElement,
110  eventSystemFlags = 0
111) => {
112  let target = rootContainerElement;
113
114  if (
115    domEventName === 'selectionchange' &&
116    rootContainerElement.nodeType !== DOCUMENT_NODE
117  ) {
118    target = rootContainerElement.ownerDocument;
119  }
120
121  if (
122    targetElement !== null &&
123    !isCapturePhaseListener &&
124    nonDelegatedEvents.has(domEventName)
125  ) {
126    if (domEventName !== 'scroll') {
127      return;
128    }
129    eventSystemFlags |= IS_NON_DELEGATED;
130    target = targetElement;
131  }
132
133  const listenerSet = getEventListenerSet(target);
134  const listenerSetKey = getListenerSetKey(
135    domEventName,
136    isCapturePhaseListener
137  );
138
139  if (!listenerSet.has(listenerSetKey)) {
140    if (isCapturePhaseListener) {
141      eventSystemFlags |= IS_CAPTURE_PHASE;
142    }
143    addTrappedEventListener(
144      target,
145      domEventName,
146      eventSystemFlags,
147      isCapturePhaseListener
148    );
149    listenerSet.add(listenerSetKey);
150  }
151};
152
153const listenToAllSupportedEvents = (rootContainerElement) => {
154  if (rootContainerElement[listeningMarker]) return;
155
156  rootContainerElement[listeningMarker] = true;
157
158  allNativeEvents.forEach((domEventName) => {
159    if (!nonDelegatedEvents.has(domEventName)) {
160      listenToNativeEvent(domEventName, false, rootContainerElement, null);
161    }
162
163    listenToNativeEvent(domEventName, true, rootContainerElement, null);
164  });
165};
166
167const listenToNonDelegatedEvent = (domEventName, targetElement) => {
168  const isCapturePhaseListener = false;
169  const listenerSet = getEventListenerSet(targetElement);
170  const listenerSetKey = getListenerSetKey(
171    domEventName,
172    isCapturePhaseListener
173  );
174  if (!listenerSet.has(listenerSetKey)) {
175    addTrappedEventListener(
176      targetElement,
177      domEventName,
178      IS_NON_DELEGATED,
179      isCapturePhaseListener
180    );
181    listenerSet.add(listenerSetKey);
182  }
183};
184
185export {
186  mediaEventTypes,
187  nonDelegatedEvents,
188  getListenerSetKey,
189  listenToNativeEvent,
190  listenToAllSupportedEvents,
191  listenToNonDelegatedEvent,
192};
193
Full Screen

DOMPluginEvnentSystem.js

Source: DOMPluginEvnentSystem.js Github

copy
1import { allNativeEvents } from "./EventRegistry"
2import * as SimpleEventPlugin from "./SimpleEventPlugin"
3import { getEventListenerSet } from "./ReactDOMComponentTree"
4import { IS_CAPTURE_PHASE } from "./EventSystemFlags"
5import {
6  addEventBubbleListener,
7  addEventCaptureListener,
8} from "./EventListener"
9import { dispatchEvent } from "./ReactDOMEventLIstener"
10import { HostComponent } from "./ReactWorkTags"
11import getListener from "./getListener"
12
13SimpleEventPlugin.registerEvents()
14// 有些事件只有捕获,没有冒泡
15export const noDelegateEvents = new Set(["scroll"]) // 不需要委托代理的
16
17export function listenToAllSupportedEvents(container) {
18  allNativeEvents.forEach((domEventName) => {
19    console.log(domEventName)
20    if (!noDelegateEvents.has(domEventName)) {
21      // 监听container的冒泡阶段domEventName(click)事件
22      listenToNativeEvent(domEventName, false, container)
23    }
24    // 监听捕获事件
25    listenToNativeEvent(domEventName, true, container)
26  })
27}
28
29function listenToNativeEvent(
30  domEventName,
31  isCapturePhaseListener,
32  rootContainerElement,
33  eventSystemFlags = 0 // 事件系统标识
34) {
35  // 同一个容器上的同一个阶段的同一个事件只绑定一次
36  let listenerSet = getEventListenerSet(rootContainerElement)
37  let listenerSetKey = getListenerSetKey(domEventName, isCapturePhaseListener)
38  if (!listenerSet.has(listenerSetKey)) {   
39    // 如果没有绑定过,就添加上这个key
40    if (isCapturePhaseListener) {
41      eventSystemFlags |= IS_CAPTURE_PHASE // let a = 1; a+=2
42    }
43    addTrappedEventListener(
44      rootContainerElement,
45      domEventName,
46      eventSystemFlags,
47      isCapturePhaseListener
48    )
49    listenerSet.add(listenerSetKey)
50  }
51}
52
53function addTrappedEventListener(
54  rootContainerElement,
55  domEventName,
56  eventSystemFlags,
57  isCapturePhaseListener
58) {
59  let listener = dispatchEvent.bind(
60    null,
61    domEventName,
62    eventSystemFlags,
63    rootContainerElement
64  )
65  if (isCapturePhaseListener) {
66    addEventCaptureListener(rootContainerElement, domEventName, listener)
67  } else {
68    addEventBubbleListener(rootContainerElement, domEventName, listener)
69  }
70}
71
72function getListenerSetKey(domEventName, isCapturePhaseListener) {
73  // click_capture   click_bubble
74  return `${domEventName}__${isCapturePhaseListener ? "capture" : "bubble"}`
75}
76
77export function dispatchEventForPluginEventSystem(
78  domEventName,
79  eventSystemFlags,
80  nativeEvent,
81  targetInst,
82  targetContainer
83) {
84  let nativeEventTarget = nativeEvent.target
85  const dispatchQueue = []
86  // 由插件来提取事件处理函数
87  // 由插件来填充这个dispatchQueue数组
88  SimpleEventPlugin.extractEvents(
89    dispatchQueue,
90    domEventName,
91    targetInst,
92    nativeEvent,
93    nativeEventTarget,
94    eventSystemFlags,
95    targetContainer
96  )
97  console.log("dispatchQueue", dispatchQueue)
98  processDispatchQueue(dispatchQueue, eventSystemFlags)
99}
100
101function processDispatchQueue(dispatchQueue, eventSystemFlags) {
102  let isCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0
103  for (let i = 0; i < dispatchQueue.length; i++) {
104    const { event, listeners } = dispatchQueue[i]
105    processDispatchQueueItemsInorder(event, listeners, isCapturePhase)
106  }
107}
108
109function processDispatchQueueItemsInorder(event, listeners, isCapturePhase) {
110  if (isCapturePhase) {
111    for (let i = listeners.length - 1; i >= 0; i--) {
112      const { currentTarget, listener } = listeners[i]
113      if (event.isPropagationStoped()) return
114      execDispatch(event, listener, currentTarget)
115    }
116  } else {
117    for (let i = 0; i < listeners.length; i++) {
118      const { currentTarget, listener } = listeners[i]
119      if (event.isPropagationStoped()) return
120      execDispatch(event, listener, currentTarget)
121    }
122  }
123}
124
125function execDispatch(event, listener, currentTarget) {
126  event.currentTarget = currentTarget
127  listener(event)
128  event.currentTarget = null
129}
130
131export function accumulateSinglePhaseListeners(
132  targetFiber,
133  reactName,
134  nativeType,
135  inCapturePhase
136) {
137  debugger
138  let captureName = reactName + "Capture"
139  let reactEventName = inCapturePhase ? captureName : reactName
140  const listeners = []
141  let instance = targetFiber
142  let lastHostComponent = null
143  while (instance) {
144    const { stateNode, tag } = instance
145    if (tag === HostComponent && stateNode !== null) {
146      lastHostComponent = stateNode
147      const listener = getListener(instance, reactEventName)
148      if (listener) {
149        listeners.push(
150          createDispatchListener(instance, listener, lastHostComponent)
151        )
152      }
153    }
154    instance = instance.return
155  }
156  return listeners
157}
158
159function createDispatchListener(instance, listener, currentTarget) {
160  return {
161    instance,
162    listener,
163    currentTarget,
164  }
165}
166
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)