ReactDOM.useEvent: Add DOM host event listener logic (#18292)
Dominic Gannaway committed
Mar 12, 2020 at 22:41 UTC
2a7cd589567b6a6fdb38664565bfad7ba3f14b6b
7 files changed
+228
-84
packages/legacy-events/PluginModuleType.js
+1
-1
@@ -29,7 +29,7 @@ export type PluginModule<NativeEvent> = {
29
nativeTarget: NativeEvent,
30
nativeEventTarget: null | EventTarget,
31
eventSystemFlags: EventSystemFlags,
32
- container?: EventTarget,
32
+ container?: null | EventTarget,
33
) => ?ReactSyntheticEvent,
34
tapMoveThreshold?: number,
35
};
packages/react-dom/src/client/ReactDOMComponentTree.js
+17
@@ -15,6 +15,7 @@ import type {
15
SuspenseInstance,
16
Props,
17
} from './ReactDOMHostConfig';
18
+import type {ReactDOMListener} from 'shared/ReactDOMTypes';
19
20
import {
21
HostComponent,
@@ -32,6 +33,7 @@ const randomKey = Math.random()
33
const internalInstanceKey = '__reactInternalInstance$' + randomKey;
34
const internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
35
const internalContainerInstanceKey = '__reactContainere$' + randomKey;
36
+const internalEventListenersKey = '__reactEventListeners$' + randomKey;
37
38
export function precacheFiberNode(
39
hostInst: Fiber,
@@ -185,3 +187,18 @@ export function updateFiberProps(
187
): void {
188
(node: any)[internalEventHandlersKey] = props;
189
}
190
+
191
+// This is used for useEvent listeners
192
+export function getListenersFromTarget(
193
+ target: EventTarget,
194
+): null | Set<ReactDOMListener> {
195
+ return (target: any)[internalEventListenersKey] || null;
196
+}
197
+
198
+// This is used for useEvent listeners
199
+export function initListenersSet(
200
+ target: EventTarget,
201
+ value: Set<ReactDOMListener>,
202
+): void {
203
+ (target: any)[internalEventListenersKey] = value;
204
+}
packages/react-dom/src/client/ReactDOMHostConfig.js
+20
-17
@@ -76,6 +76,8 @@ import {
76
import {
77
attachElementListener,
78
detachElementListener,
79
+ isDOMDocument,
80
+ isDOMElement,
81
} from '../events/DOMModernPluginEventSystem';
82
83
export type ReactListenerEvent = ReactDOMListenerEvent;
@@ -1086,7 +1088,9 @@ export function mountEventListener(listener: ReactDOMListener): void {
1088
const {target} = listener;
1089
if (target === window) {
1090
// TODO (useEvent)
1089
- } else {
1091
+ } else if (isDOMDocument(target)) {
1092
+ // TODO (useEvent)
1093
+ } else if (isDOMElement(target)) {
1094
attachElementListener(listener);
1095
}
1096
}
@@ -1097,7 +1101,9 @@ export function unmountEventListener(listener: ReactDOMListener): void {
1101
const {target} = listener;
1102
if (target === window) {
1103
// TODO (useEvent)
1100
- } else {
1104
+ } else if (isDOMDocument(target)) {
1105
+ // TODO (useEvent)
1106
+ } else if (isDOMElement(target)) {
1107
detachElementListener(listener);
1108
}
1109
}
@@ -1109,8 +1115,11 @@ export function validateEventListenerTarget(
1115
): boolean {
1116
if (enableUseEventAPI) {
1117
if (
1112
- target &&
1113
- (target === window || getClosestInstanceFromNode(((target: any): Node)))
1118
+ target != null &&
1119
+ (target === window ||
1120
+ isDOMDocument(target) ||
1121
+ (isDOMElement(target) &&
1122
+ getClosestInstanceFromNode(((target: any): Element))))
1123
) {
1124
if (listener == null || typeof listener === 'function') {
1125
return true;
@@ -1123,19 +1132,13 @@ export function validateEventListenerTarget(
1132
}
1133
}
1134
if (__DEV__) {
1126
- if (target && (target: any).nodeType === DOCUMENT_NODE) {
1127
- console.warn(
1128
- 'Event listener method setListener() from useEvent() hook requires the first argument to be a valid' +
1129
- ' DOM node that was rendered and managed by React or a "window" object. It looks like' +
1130
- ' you supplied a "document" node, instead use the "window" object.',
1131
- );
1132
- } else {
1133
- console.warn(
1134
- 'Event listener method setListener() from useEvent() hook requires the first argument to be a valid' +
1135
- ' DOM node that was rendered and managed by React or a "window" object. If this is' +
1136
- ' from a ref, ensure the ref value has been set before attaching.',
1137
- );
1138
- }
1135
+ console.warn(
1136
+ 'Event listener method setListener() from useEvent() hook requires the first argument to be either:' +
1137
+ '\n\n' +
1138
+ '1. A valid DOM node that was rendered and managed by React' +
1139
+ '2. The "window" object' +
1140
+ '3. The "document" object',
1141
+ );
1142
}
1143
}
1144
return false;
packages/react-dom/src/events/DOMModernPluginEventSystem.js
+111
-28
@@ -59,8 +59,16 @@ import {
59
TOP_PROGRESS,
60
TOP_PLAYING,
61
} from './DOMTopLevelEventTypes';
62
-import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
63
-import {DOCUMENT_NODE, COMMENT_NODE} from '../shared/HTMLNodeType';
62
+import {
63
+ getClosestInstanceFromNode,
64
+ getListenersFromTarget,
65
+ initListenersSet,
66
+} from '../client/ReactDOMComponentTree';
67
+import {
68
+ DOCUMENT_NODE,
69
+ COMMENT_NODE,
70
+ ELEMENT_NODE,
71
+} from '../shared/HTMLNodeType';
72
73
import {enableLegacyFBPrimerSupport} from 'shared/ReactFeatureFlags';
74
@@ -107,7 +115,7 @@ function dispatchEventsForPlugins(
115
eventSystemFlags: EventSystemFlags,
116
nativeEvent: AnyNativeEvent,
117
targetInst: null | Fiber,
110
- rootContainer: EventTarget,
118
+ targetContainer: null | EventTarget,
119
): void {
120
const nativeEventTarget = getEventTarget(nativeEvent);
121
const syntheticEvents: Array<ReactSyntheticEvent> = [];
@@ -121,7 +129,7 @@ function dispatchEventsForPlugins(
129
nativeEvent,
130
nativeEventTarget,
131
eventSystemFlags,
124
- rootContainer,
132
+ targetContainer,
133
);
134
if (isArray(extractedEvents)) {
135
// Flow complains about @@iterator being missing in ReactSyntheticEvent,
@@ -145,13 +153,20 @@ function dispatchEventsForPlugins(
153
154
export function listenToTopLevelEvent(
155
topLevelType: DOMTopLevelEventType,
148
- rootContainerElement: Element,
156
+ targetContainer: EventTarget,
157
listenerMap: Map<DOMTopLevelEventType | string, null | (any => void)>,
158
+ passive?: boolean,
159
): void {
160
if (!listenerMap.has(topLevelType)) {
161
const isCapturePhase = capturePhaseEvents.has(topLevelType);
153
- addTrappedEventListener(rootContainerElement, topLevelType, isCapturePhase);
154
- listenerMap.set(topLevelType, null);
162
+ const listener = addTrappedEventListener(
163
+ targetContainer,
164
+ topLevelType,
165
+ isCapturePhase,
166
+ false,
167
+ passive,
168
+ );
169
+ listenerMap.set(topLevelType, listener);
170
}
171
}
172
@@ -194,7 +209,7 @@ function willDeferLaterForFBLegacyPrimer(nativeEvent: any): boolean {
209
const legacyFBSupport = true;
210
const isCapture = nativeEvent.eventPhase === 1;
211
addTrappedEventListener(
197
- document,
212
+ null,
213
((type: any): DOMTopLevelEventType),
214
isCapture,
215
legacyFBSupport,
@@ -208,35 +223,46 @@ function willDeferLaterForFBLegacyPrimer(nativeEvent: any): boolean {
223
224
function isMatchingRootContainer(
225
grandContainer: Element,
211
- rootContainer: EventTarget,
226
+ targetContainer: EventTarget,
227
): boolean {
228
return (
214
- grandContainer === rootContainer ||
229
+ grandContainer === targetContainer ||
230
(grandContainer.nodeType === COMMENT_NODE &&
216
- grandContainer.parentNode === rootContainer)
231
+ grandContainer.parentNode === targetContainer)
232
);
233
}
234
235
+export function isDOMElement(target: EventTarget): boolean {
236
+ const nodeType = ((target: any): Node).nodeType;
237
+ return (nodeType: any) && nodeType === ELEMENT_NODE;
238
+}
239
+
240
+export function isDOMDocument(target: EventTarget): boolean {
241
+ const nodeType = ((target: any): Node).nodeType;
242
+ return nodeType === DOCUMENT_NODE;
243
+}
244
+
245
export function dispatchEventForPluginEventSystem(
246
topLevelType: DOMTopLevelEventType,
247
eventSystemFlags: EventSystemFlags,
248
nativeEvent: AnyNativeEvent,
249
targetInst: null | Fiber,
225
- rootContainer: EventTarget,
250
+ targetContainer: null | EventTarget,
251
): void {
252
let ancestorInst = targetInst;
228
- // Given the rootContainer can be any EventTarget, if the
229
- // target is that of a DOM node (other than the document)
230
- // then we'll attempt to find the correct ancestor root.
231
- // Note: the rootContainer can be other things like
232
- // "window" or other valid EventTarget objects.
233
- const possibleContainerNodeType = ((rootContainer: any): Node).nodeType;
234
- if (
235
- possibleContainerNodeType !== undefined &&
236
- possibleContainerNodeType !== DOCUMENT_NODE
237
- ) {
253
+ if (targetContainer !== null) {
254
+ const possibleTargetContainerNode = ((targetContainer: any): Node);
255
+ // Given the rootContainer can be any EventTarget, if the
256
+ // target is not a valid DOM element then we'll skip this part.
257
+ if (
258
+ possibleTargetContainerNode === window ||
259
+ !isDOMElement(possibleTargetContainerNode)
260
+ ) {
261
+ // TODO: useEvent for document and window
262
+ return;
263
+ }
264
// If we detect the FB legacy primer system, we
239
- // defer the event to the "document" with a one
265
+ // defer the event to the null with a one
266
// time event listener so we can defer the event.
267
if (
268
enableLegacyFBPrimerSupport &&
@@ -263,7 +289,7 @@ export function dispatchEventForPluginEventSystem(
289
}
290
if (node.tag === HostRoot || node.tag === HostPortal) {
291
const container = node.stateNode.containerInfo;
266
- if (isMatchingRootContainer(container, rootContainer)) {
292
+ if (isMatchingRootContainer(container, possibleTargetContainerNode)) {
293
break;
294
}
295
if (node.tag === HostPortal) {
@@ -275,7 +301,12 @@ export function dispatchEventForPluginEventSystem(
301
while (grandNode !== null) {
302
if (grandNode.tag === HostRoot || grandNode.tag === HostPortal) {
303
const grandContainer = grandNode.stateNode.containerInfo;
278
- if (isMatchingRootContainer(grandContainer, rootContainer)) {
304
+ if (
305
+ isMatchingRootContainer(
306
+ grandContainer,
307
+ possibleTargetContainerNode,
308
+ )
309
+ ) {
310
// This is the rootContainer we're looking for and we found it as
311
// a parent of the Portal. That means we can ignore it because the
312
// Portal will bubble through to us.
@@ -302,15 +333,67 @@ export function dispatchEventForPluginEventSystem(
333
eventSystemFlags,
334
nativeEvent,
335
ancestorInst,
305
- rootContainer,
336
+ targetContainer,
337
),
338
);
339
}
340
341
+function getNearestRootOrPortalContainer(instance: Element): Element {
342
+ let node = getClosestInstanceFromNode(instance);
343
+ while (node !== null) {
344
+ const tag = node.tag;
345
+ // Once we encounter a host container or root container
346
+ // we can return their DOM instance.
347
+ if (tag === HostRoot || tag === HostPortal) {
348
+ return node.stateNode.containerInfo;
349
+ }
350
+ node = node.return;
351
+ }
352
+ return instance;
353
+}
354
+
355
export function attachElementListener(listener: ReactDOMListener): void {
311
- // TODO
356
+ const {event, target} = listener;
357
+ const {passive, type} = event;
358
+ let containerEventTarget = target;
359
+ // If we the target is a managed React element, then we need to
360
+ // find the nearest root/portal contained to attach the event listener
361
+ // to. If it's not managed, i.e. the window, then we just attach
362
+ // the listener to the target.
363
+ if (isDOMElement(target)) {
364
+ const possibleManagedTarget = ((target: any): Element);
365
+ if (getClosestInstanceFromNode(possibleManagedTarget)) {
366
+ containerEventTarget = getNearestRootOrPortalContainer(
367
+ possibleManagedTarget,
368
+ );
369
+ }
370
+ }
371
+ const listenerMap = getListenerMapForElement(containerEventTarget);
372
+ // Add the event listener to the target container (falling back to
373
+ // the target if we didn't find one).
374
+ listenToTopLevelEvent(
375
+ ((type: any): DOMTopLevelEventType),
376
+ containerEventTarget,
377
+ listenerMap,
378
+ passive,
379
+ );
380
+ // Get the internal listeners Set from the target instance.
381
+ let listeners = getListenersFromTarget(target);
382
+ // If we don't have any listeners, then we need to init them.
383
+ if (listeners === null) {
384
+ listeners = new Set();
385
+ initListenersSet(target, listeners);
386
+ }
387
+ // Finally, add our listener to the listeners Set.
388
+ listeners.add(listener);
389
}
390
391
export function detachElementListener(listener: ReactDOMListener): void {
315
- // TODO
392
+ const {target} = listener;
393
+ // Get the internal listeners Set from the target instance.
394
+ const listeners = getListenersFromTarget(target);
395
+ if (listeners !== null) {
396
+ // Remove out listener from the listeners Set.
397
+ listeners.delete(listener);
398
+ }
399
}
packages/react-dom/src/events/ReactDOMEventListener.js
+63
-22
@@ -47,6 +47,7 @@ import {
47
addEventBubbleListener,
48
addEventCaptureListener,
49
addEventCaptureListenerWithPassiveFlag,
50
+ addEventBubbleListenerWithPassiveFlag,
51
} from './EventListener';
52
import getEventTarget from './getEventTarget';
53
import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
@@ -57,6 +58,7 @@ import {
58
enableDeprecatedFlareAPI,
59
enableModernEventSystem,
60
enableLegacyFBPrimerSupport,
61
+ enableUseEventAPI,
62
} from 'shared/ReactFeatureFlags';
63
import {
64
UserBlockingEvent,
@@ -130,10 +132,11 @@ export function addResponderEventSystemEvent(
132
}
133
134
export function addTrappedEventListener(
133
- targetContainer: EventTarget,
135
+ targetContainer: null | EventTarget,
136
topLevelType: DOMTopLevelEventType,
137
capture: boolean,
138
legacyFBSupport?: boolean,
139
+ passive?: boolean,
140
): any => void {
141
let listener;
142
let listenerWrapper;
@@ -149,6 +152,12 @@ export function addTrappedEventListener(
152
listenerWrapper = dispatchEvent;
153
break;
154
}
155
+ // If passive option is not supported, then the event will be
156
+ // active and not passive.
157
+ if (passive === true && !passiveBrowserEventsSupported) {
158
+ passive = false;
159
+ }
160
+
161
listener = listenerWrapper.bind(
162
null,
163
topLevelType,
@@ -156,6 +165,18 @@ export function addTrappedEventListener(
165
targetContainer,
166
);
167
168
+ // When the targetContainer is null, it means that the container
169
+ // target is null, but really we need a real DOM node to attach to.
170
+ // In this case, we fallback to the "document" node, but leave the
171
+ // targetContainer (which is bound in the above function) to null.
172
+ // Really, this only happens for TestUtils.Simulate, so when we
173
+ // remove that support, we can remove this block of code.
174
+ if (targetContainer === null) {
175
+ targetContainer = document;
176
+ }
177
+
178
+ const validTargetContainer = ((targetContainer: any): EventTarget);
179
+
180
const rawEventName = getRawEventName(topLevelType);
181
let fbListener;
182
@@ -179,7 +200,7 @@ export function addTrappedEventListener(
200
if (fbListener) {
201
fbListener.remove();
202
} else {
182
- targetContainer.removeEventListener(
203
+ validTargetContainer.removeEventListener(
204
((rawEventName: any): string),
205
(listener: any),
206
);
@@ -188,17 +209,37 @@ export function addTrappedEventListener(
209
};
210
}
211
if (capture) {
191
- fbListener = addEventCaptureListener(
192
- targetContainer,
193
- rawEventName,
194
- listener,
195
- );
212
+ if (enableUseEventAPI && passive !== undefined) {
213
+ // This is only used with passive is either true or false.
214
+ fbListener = addEventCaptureListenerWithPassiveFlag(
215
+ validTargetContainer,
216
+ rawEventName,
217
+ listener,
218
+ passive,
219
+ );
220
+ } else {
221
+ fbListener = addEventCaptureListener(
222
+ validTargetContainer,
223
+ rawEventName,
224
+ listener,
225
+ );
226
+ }
227
} else {
197
- fbListener = addEventBubbleListener(
198
- targetContainer,
199
- rawEventName,
200
- listener,
201
- );
228
+ if (enableUseEventAPI && passive !== undefined) {
229
+ // This is only used with passive is either true or false.
230
+ fbListener = addEventBubbleListenerWithPassiveFlag(
231
+ validTargetContainer,
232
+ rawEventName,
233
+ listener,
234
+ passive,
235
+ );
236
+ } else {
237
+ fbListener = addEventBubbleListener(
238
+ validTargetContainer,
239
+ rawEventName,
240
+ listener,
241
+ );
242
+ }
243
}
244
// If we have an fbListener, then use that.
245
// We'll only have one if we use the forked
@@ -262,7 +303,7 @@ function dispatchUserBlockingUpdate(
303
export function dispatchEvent(
304
topLevelType: DOMTopLevelEventType,
305
eventSystemFlags: EventSystemFlags,
265
- container: EventTarget,
306
+ targetContainer: null | EventTarget,
307
nativeEvent: AnyNativeEvent,
308
): void {
309
if (!_enabled) {
@@ -276,7 +317,7 @@ export function dispatchEvent(
317
null, // Flags that we're not actually blocked on anything as far as we know.
318
topLevelType,
319
eventSystemFlags,
279
- container,
320
+ targetContainer,
321
nativeEvent,
322
);
323
return;
@@ -285,7 +326,7 @@ export function dispatchEvent(
326
const blockedOn = attemptToDispatchEvent(
327
topLevelType,
328
eventSystemFlags,
288
- container,
329
+ targetContainer,
330
nativeEvent,
331
);
332
@@ -301,7 +342,7 @@ export function dispatchEvent(
342
blockedOn,
343
topLevelType,
344
eventSystemFlags,
304
- container,
345
+ targetContainer,
346
nativeEvent,
347
);
348
return;
@@ -312,7 +353,7 @@ export function dispatchEvent(
353
blockedOn,
354
topLevelType,
355
eventSystemFlags,
315
- container,
356
+ targetContainer,
357
nativeEvent,
358
)
359
) {
@@ -333,7 +374,7 @@ export function dispatchEvent(
374
eventSystemFlags,
375
nativeEvent,
376
null,
336
- container,
377
+ targetContainer,
378
);
379
} else {
380
dispatchEventForLegacyPluginEventSystem(
@@ -361,7 +402,7 @@ export function dispatchEvent(
402
eventSystemFlags,
403
nativeEvent,
404
null,
364
- container,
405
+ targetContainer,
406
);
407
} else {
408
dispatchEventForLegacyPluginEventSystem(
@@ -378,7 +419,7 @@ export function dispatchEvent(
419
export function attemptToDispatchEvent(
420
topLevelType: DOMTopLevelEventType,
421
eventSystemFlags: EventSystemFlags,
381
- container: EventTarget,
422
+ targetContainer: EventTarget | null,
423
nativeEvent: AnyNativeEvent,
424
): null | Container | SuspenseInstance {
425
// TODO: Warn if _enabled is false.
@@ -432,7 +473,7 @@ export function attemptToDispatchEvent(
473
eventSystemFlags,
474
nativeEvent,
475
targetInst,
435
- container,
476
+ targetContainer,
477
);
478
} else {
479
dispatchEventForLegacyPluginEventSystem(
@@ -460,7 +501,7 @@ export function attemptToDispatchEvent(
501
eventSystemFlags,
502
nativeEvent,
503
targetInst,
463
- container,
504
+ targetContainer,
505
);
506
} else {
507
dispatchEventForLegacyPluginEventSystem(
packages/react-dom/src/events/ReactDOMEventReplaying.js
+15
-15
@@ -126,7 +126,7 @@ type QueuedReplayableEvent = {|
126
topLevelType: DOMTopLevelEventType,
127
eventSystemFlags: EventSystemFlags,
128
nativeEvent: AnyNativeEvent,
129
- container: EventTarget,
129
+ targetContainer: EventTarget | null,
130
|};
131
132
let hasScheduledReplayAttempt = false;
@@ -285,7 +285,7 @@ function createQueuedReplayableEvent(
285
blockedOn: null | Container | SuspenseInstance,
286
topLevelType: DOMTopLevelEventType,
287
eventSystemFlags: EventSystemFlags,
288
- container: EventTarget,
288
+ targetContainer: EventTarget | null,
289
nativeEvent: AnyNativeEvent,
290
): QueuedReplayableEvent {
291
return {
@@ -293,7 +293,7 @@ function createQueuedReplayableEvent(
293
topLevelType,
294
eventSystemFlags: eventSystemFlags | IS_REPLAYED,
295
nativeEvent,
296
- container,
296
+ targetContainer,
297
};
298
}
299
@@ -301,14 +301,14 @@ export function queueDiscreteEvent(
301
blockedOn: null | Container | SuspenseInstance,
302
topLevelType: DOMTopLevelEventType,
303
eventSystemFlags: EventSystemFlags,
304
- container: EventTarget,
304
+ targetContainer: EventTarget | null,
305
nativeEvent: AnyNativeEvent,
306
): void {
307
const queuedEvent = createQueuedReplayableEvent(
308
blockedOn,
309
topLevelType,
310
eventSystemFlags,
311
- container,
311
+ targetContainer,
312
nativeEvent,
313
);
314
queuedDiscreteEvents.push(queuedEvent);
@@ -376,7 +376,7 @@ function accumulateOrCreateContinuousQueuedReplayableEvent(
376
blockedOn: null | Container | SuspenseInstance,
377
topLevelType: DOMTopLevelEventType,
378
eventSystemFlags: EventSystemFlags,
379
- container: EventTarget,
379
+ targetContainer: EventTarget | null,
380
nativeEvent: AnyNativeEvent,
381
): QueuedReplayableEvent {
382
if (
@@ -387,7 +387,7 @@ function accumulateOrCreateContinuousQueuedReplayableEvent(
387
blockedOn,
388
topLevelType,
389
eventSystemFlags,
390
- container,
390
+ targetContainer,
391
nativeEvent,
392
);
393
if (blockedOn !== null) {
@@ -411,7 +411,7 @@ export function queueIfContinuousEvent(
411
blockedOn: null | Container | SuspenseInstance,
412
topLevelType: DOMTopLevelEventType,
413
eventSystemFlags: EventSystemFlags,
414
- container: EventTarget,
414
+ targetContainer: EventTarget | null,
415
nativeEvent: AnyNativeEvent,
416
): boolean {
417
// These set relatedTarget to null because the replayed event will be treated as if we
@@ -425,7 +425,7 @@ export function queueIfContinuousEvent(
425
blockedOn,
426
topLevelType,
427
eventSystemFlags,
428
- container,
428
+ targetContainer,
429
focusEvent,
430
);
431
return true;
@@ -437,7 +437,7 @@ export function queueIfContinuousEvent(
437
blockedOn,
438
topLevelType,
439
eventSystemFlags,
440
- container,
440
+ targetContainer,
441
dragEvent,
442
);
443
return true;
@@ -449,7 +449,7 @@ export function queueIfContinuousEvent(
449
blockedOn,
450
topLevelType,
451
eventSystemFlags,
452
- container,
452
+ targetContainer,
453
mouseEvent,
454
);
455
return true;
@@ -464,7 +464,7 @@ export function queueIfContinuousEvent(
464
blockedOn,
465
topLevelType,
466
eventSystemFlags,
467
- container,
467
+ targetContainer,
468
pointerEvent,
469
),
470
);
@@ -480,7 +480,7 @@ export function queueIfContinuousEvent(
480
blockedOn,
481
topLevelType,
482
eventSystemFlags,
483
- container,
483
+ targetContainer,
484
pointerEvent,
485
),
486
);
@@ -557,7 +557,7 @@ function attemptReplayContinuousQueuedEvent(
557
let nextBlockedOn = attemptToDispatchEvent(
558
queuedEvent.topLevelType,
559
queuedEvent.eventSystemFlags,
560
- queuedEvent.container,
560
+ queuedEvent.targetContainer,
561
queuedEvent.nativeEvent,
562
);
563
if (nextBlockedOn !== null) {
@@ -600,7 +600,7 @@ function replayUnblockedEvents() {
600
let nextBlockedOn = attemptToDispatchEvent(
601
nextDiscreteEvent.topLevelType,
602
nextDiscreteEvent.eventSystemFlags,
603
- nextDiscreteEvent.container,
603
+ nextDiscreteEvent.targetContainer,
604
nextDiscreteEvent.nativeEvent,
605
);
606
if (nextBlockedOn !== null) {
packages/react-dom/src/test-utils/ReactTestUtils.js
+1
-1
@@ -63,7 +63,7 @@ let hasWarnedAboutDeprecatedMockComponent = false;
63
*/
64
function simulateNativeEventOnNode(topLevelType, node, fakeNativeEvent) {
65
fakeNativeEvent.target = node;
66
- dispatchEvent(topLevelType, PLUGIN_EVENT_SYSTEM, document, fakeNativeEvent);
66
+ dispatchEvent(topLevelType, PLUGIN_EVENT_SYSTEM, null, fakeNativeEvent);
67
}
68
69
/**