How to use isMatchingRootContainer 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.

DOMModernPluginEventSystem.js

Source: DOMModernPluginEventSystem.js Github

copy
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10import type {AnyNativeEvent} from 'legacy-events/PluginModuleType';
11import type {DOMTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
12import type {EventSystemFlags} from 'legacy-events/EventSystemFlags';
13import type {Fiber} from 'react-reconciler/src/ReactFiber';
14import type {PluginModule} from 'legacy-events/PluginModuleType';
15import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType';
16
17import {registrationNameDependencies} from 'legacy-events/EventPluginRegistry';
18import {batchedEventUpdates} from 'legacy-events/ReactGenericBatching';
19import {executeDispatchesInOrder} from 'legacy-events/EventPluginUtils';
20import {plugins} from 'legacy-events/EventPluginRegistry';
21
22import {HostRoot, HostPortal} from 'shared/ReactWorkTags';
23
24import {trapEventForPluginEventSystem} from './ReactDOMEventListener';
25import getEventTarget from './getEventTarget';
26import {getListenerMapForElement} from './DOMEventListenerMap';
27import {
28  TOP_FOCUS,
29  TOP_LOAD,
30  TOP_ABORT,
31  TOP_CANCEL,
32  TOP_INVALID,
33  TOP_BLUR,
34  TOP_SCROLL,
35  TOP_CLOSE,
36  TOP_RESET,
37  TOP_SUBMIT,
38  TOP_CAN_PLAY,
39  TOP_CAN_PLAY_THROUGH,
40  TOP_DURATION_CHANGE,
41  TOP_EMPTIED,
42  TOP_ENCRYPTED,
43  TOP_ENDED,
44  TOP_ERROR,
45  TOP_WAITING,
46  TOP_VOLUME_CHANGE,
47  TOP_TIME_UPDATE,
48  TOP_SUSPEND,
49  TOP_STALLED,
50  TOP_SEEKING,
51  TOP_SEEKED,
52  TOP_PLAY,
53  TOP_PAUSE,
54  TOP_LOAD_START,
55  TOP_LOADED_DATA,
56  TOP_LOADED_METADATA,
57  TOP_RATE_CHANGE,
58  TOP_PROGRESS,
59  TOP_PLAYING,
60} from './DOMTopLevelEventTypes';
61import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
62import {DOCUMENT_NODE, COMMENT_NODE} from '../shared/HTMLNodeType';
63
64import {enableLegacyFBPrimerSupport} from 'shared/ReactFeatureFlags';
65
66const capturePhaseEvents = new Set([
67  TOP_FOCUS,
68  TOP_BLUR,
69  TOP_SCROLL,
70  TOP_LOAD,
71  TOP_ABORT,
72  TOP_CANCEL,
73  TOP_CLOSE,
74  TOP_INVALID,
75  TOP_RESET,
76  TOP_SUBMIT,
77  TOP_ABORT,
78  TOP_CAN_PLAY,
79  TOP_CAN_PLAY_THROUGH,
80  TOP_DURATION_CHANGE,
81  TOP_EMPTIED,
82  TOP_ENCRYPTED,
83  TOP_ENDED,
84  TOP_ERROR,
85  TOP_LOADED_DATA,
86  TOP_LOADED_METADATA,
87  TOP_LOAD_START,
88  TOP_PAUSE,
89  TOP_PLAY,
90  TOP_PLAYING,
91  TOP_PROGRESS,
92  TOP_RATE_CHANGE,
93  TOP_SEEKED,
94  TOP_SEEKING,
95  TOP_STALLED,
96  TOP_SUSPEND,
97  TOP_TIME_UPDATE,
98  TOP_VOLUME_CHANGE,
99  TOP_WAITING,
100]);
101
102const isArray = Array.isArray;
103
104function dispatchEventsForPlugins(
105  topLevelType: DOMTopLevelEventType,
106  eventSystemFlags: EventSystemFlags,
107  nativeEvent: AnyNativeEvent,
108  targetInst: null | Fiber,
109  rootContainer: Element | Document,
110): void {
111  const nativeEventTarget = getEventTarget(nativeEvent);
112  const syntheticEvents: Array<ReactSyntheticEvent> = [];
113
114  for (let i = 0; i < plugins.length; i++) {
115    const possiblePlugin: PluginModule<AnyNativeEvent> = plugins[i];
116    if (possiblePlugin !== undefined) {
117      const extractedEvents = possiblePlugin.extractEvents(
118        topLevelType,
119        targetInst,
120        nativeEvent,
121        nativeEventTarget,
122        eventSystemFlags,
123        rootContainer,
124      );
125      if (isArray(extractedEvents)) {
126        // Flow complains about @@iterator being missing in ReactSyntheticEvent,
127        // so we cast to avoid the Flow error.
128        const arrOfExtractedEvents = ((extractedEvents: any): Array<ReactSyntheticEvent>);
129        syntheticEvents.push(...arrOfExtractedEvents);
130      } else if (extractedEvents != null) {
131        syntheticEvents.push(extractedEvents);
132      }
133    }
134  }
135  for (let i = 0; i < syntheticEvents.length; i++) {
136    const syntheticEvent = syntheticEvents[i];
137    executeDispatchesInOrder(syntheticEvent);
138    // Release the event from the pool if needed
139    if (!syntheticEvent.isPersistent()) {
140      syntheticEvent.constructor.release(syntheticEvent);
141    }
142  }
143}
144
145export function listenToTopLevelEvent(
146  topLevelType: DOMTopLevelEventType,
147  rootContainerElement: Element,
148  listenerMap: Map<DOMTopLevelEventType | string, null | (any => void)>,
149): void {
150  if (!listenerMap.has(topLevelType)) {
151    const isCapturePhase = capturePhaseEvents.has(topLevelType);
152    trapEventForPluginEventSystem(
153      rootContainerElement,
154      topLevelType,
155      isCapturePhase,
156    );
157    listenerMap.set(topLevelType, null);
158  }
159}
160
161export function listenToEvent(
162  registrationName: string,
163  rootContainerElement: Element,
164): void {
165  const listenerMap = getListenerMapForElement(rootContainerElement);
166  const dependencies = registrationNameDependencies[registrationName];
167
168  for (let i = 0; i < dependencies.length; i++) {
169    const dependency = dependencies[i];
170    listenToTopLevelEvent(dependency, rootContainerElement, listenerMap);
171  }
172}
173
174const validFBLegacyPrimerRels = new Set([
175  'dialog',
176  'dialog-post',
177  'async',
178  'async-post',
179  'theater',
180  'toggle',
181]);
182
183function willDeferLaterForFBLegacyPrimer(nativeEvent: any): boolean {
184  let node = nativeEvent.target;
185  const type = nativeEvent.type;
186  if (type !== 'click') {
187    return false;
188  }
189  while (node !== null) {
190    // Primer works by intercepting a click event on an <a> element
191    // that has a "rel" attribute that matches one of the valid ones
192    // in the Set above. If we intercept this before Primer does, we
193    // will need to defer the current event till later and discontinue
194    // execution of the current event. To do this we can add a document
195    // event listener and continue again later after propagation.
196    if (node.tagName === 'A' && validFBLegacyPrimerRels.has(node.rel)) {
197      const legacyFBSupport = true;
198      const isCapture = nativeEvent.eventPhase === 1;
199      trapEventForPluginEventSystem(
200        document,
201        ((type: any): DOMTopLevelEventType),
202        isCapture,
203        legacyFBSupport,
204      );
205      return true;
206    }
207    node = node.parentNode;
208  }
209  return false;
210}
211
212function isMatchingRootContainer(
213  grandContainer: Element,
214  rootContainer: Document | Element,
215): boolean {
216  return (
217    grandContainer === rootContainer ||
218    (grandContainer.nodeType === COMMENT_NODE &&
219      grandContainer.parentNode === rootContainer)
220  );
221}
222
223export function dispatchEventForPluginEventSystem(
224  topLevelType: DOMTopLevelEventType,
225  eventSystemFlags: EventSystemFlags,
226  nativeEvent: AnyNativeEvent,
227  targetInst: null | Fiber,
228  rootContainer: Document | Element,
229): void {
230  let ancestorInst = targetInst;
231  if (rootContainer.nodeType !== DOCUMENT_NODE) {
232    // If we detect the FB legacy primer system, we
233    // defer the event to the "document" with a one
234    // time event listener so we can defer the event.
235    if (
236      enableLegacyFBPrimerSupport &&
237      willDeferLaterForFBLegacyPrimer(nativeEvent)
238    ) {
239      return;
240    }
241    // The below logic attempts to work out if we need to change
242    // the target fiber to a different ancestor. We had similar logic
243    // in the legacy event system, except the big difference between
244    // systems is that the modern event system now has an event listener
245    // attached to each React Root and React Portal Root. Together,
246    // the DOM nodes representing these roots are the "rootContainer".
247    // To figure out which ancestor instance we should use, we traverse
248    // up the fiber tree from the target instance and attempt to find
249    // root boundaries that match that of our current "rootContainer".
250    // If we find that "rootContainer", we find the parent fiber
251    // sub-tree for that root and make that our ancestor instance.
252    let node = targetInst;
253
254    while (true) {
255      if (node === null) {
256        return;
257      }
258      if (node.tag === HostRoot || node.tag === HostPortal) {
259        const container = node.stateNode.containerInfo;
260        if (isMatchingRootContainer(container, rootContainer)) {
261          break;
262        }
263        if (node.tag === HostPortal) {
264          // The target is a portal, but it's not the rootContainer we're looking for.
265          // Normally portals handle their own events all the way down to the root.
266          // So we should be able to stop now. However, we don't know if this portal
267          // was part of *our* root.
268          let grandNode = node.return;
269          while (grandNode !== null) {
270            if (grandNode.tag === HostRoot || grandNode.tag === HostPortal) {
271              const grandContainer = grandNode.stateNode.containerInfo;
272              if (isMatchingRootContainer(grandContainer, rootContainer)) {
273                // This is the rootContainer we're looking for and we found it as
274                // a parent of the Portal. That means we can ignore it because the
275                // Portal will bubble through to us.
276                return;
277              }
278            }
279            grandNode = grandNode.return;
280          }
281        }
282        const parentSubtreeInst = getClosestInstanceFromNode(container);
283        if (parentSubtreeInst === null) {
284          return;
285        }
286        node = ancestorInst = parentSubtreeInst;
287        continue;
288      }
289      node = node.return;
290    }
291  }
292
293  batchedEventUpdates(() =>
294    dispatchEventsForPlugins(
295      topLevelType,
296      eventSystemFlags,
297      nativeEvent,
298      ancestorInst,
299      rootContainer,
300    ),
301  );
302}
303
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)