@@ -41,9 +41,11 @@ export function setListenToResponderEventTypes(
41
41
listenToResponderEventTypesImpl = _listenToResponderEventTypesImpl ;
42
42
}
43
43
44
+ type EventObjectTypes = { | stopPropagation : true | } | $Shape < PartialEventObject > ;
45
+
44
46
type EventQueue = {
45
- bubble : null | Array < $Shape < PartialEventObject > >,
46
- capture : null | Array < $Shape < PartialEventObject > >,
47
+ bubble : null | Array < EventObjectTypes > ,
48
+ capture : null | Array < EventObjectTypes > ,
47
49
discrete : boolean ,
48
50
} ;
49
51
@@ -53,16 +55,38 @@ type PartialEventObject = {
53
55
type : string ,
54
56
} ;
55
57
58
+ type ResponderTimeout = { |
59
+ id : TimeoutID ,
60
+ timers : Map < Symbol , ResponderTimer> ,
61
+ | } ;
62
+
63
+ type ResponderTimer = { |
64
+ instance : ReactEventComponentInstance ,
65
+ func : ( ) => void ,
66
+ id : Symbol ,
67
+ | } ;
68
+
69
+ const activeTimeouts : Map < Symbol , ResponderTimeout > = new Map ( ) ;
70
+ const rootEventTypesToEventComponentInstances : Map <
71
+ DOMTopLevelEventType | string ,
72
+ Set < ReactEventComponentInstance > ,
73
+ > = new Map ( ) ;
74
+ const targetEventTypeCached : Map <
75
+ Array < ReactEventResponderEventType > ,
76
+ Set< DOMTopLevelEventType > ,
77
+ > = new Map ( ) ;
78
+ const ownershipChangeListeners : Set < ReactEventComponentInstance > = new Set();
79
+
80
+ let currentTimers = new Map();
56
81
let currentOwner = null;
57
82
let currentInstance: ReactEventComponentInstance;
58
83
let currentEventQueue: EventQueue;
59
84
60
85
const eventResponderContext: ReactResponderContext = {
61
86
dispatchEvent (
62
87
possibleEventObject : Object ,
63
- { capture, discrete, stopPropagation } : ReactResponderDispatchEventOptions ,
88
+ { capture, discrete} : ReactResponderDispatchEventOptions ,
64
89
) : void {
65
- const eventQueue = currentEventQueue ;
66
90
const { listener, target, type} = possibleEventObject ;
67
91
68
92
if ( listener == null || target == null || type == null ) {
@@ -89,27 +113,15 @@ const eventResponderContext: ReactResponderContext = {
89
113
const eventObject = ( ( possibleEventObject : any ) : $Shape <
90
114
PartialEventObject ,
91
115
> ) ;
92
- let events ;
93
-
94
- if ( capture ) {
95
- events = eventQueue . capture ;
96
- if ( events === null ) {
97
- events = eventQueue . capture = [ ] ;
98
- }
99
- } else {
100
- events = eventQueue . bubble ;
101
- if ( events === null ) {
102
- events = eventQueue . bubble = [ ] ;
103
- }
104
- }
116
+ const events = getEventsFromEventQueue ( capture ) ;
105
117
if ( discrete ) {
106
- eventQueue . discrete = true ;
118
+ currentEventQueue . discrete = true ;
107
119
}
108
120
events.push(eventObject);
109
-
110
- if ( stopPropagation ) {
111
- eventsWithStopPropagation . add ( eventObject ) ;
112
- }
121
+ } ,
122
+ dispatchStopPropagation ( capture ?: boolean ) {
123
+ const events = getEventsFromEventQueue ( ) ;
124
+ events . push ( { stopPropagation : true } ) ;
113
125
} ,
114
126
isPositionWithinTouchHitTarget(doc: Document, x: number, y: number): boolean {
115
127
// This isn't available in some environments (JSDOM)
@@ -222,21 +234,42 @@ const eventResponderContext: ReactResponderContext = {
222
234
triggerOwnershipListeners();
223
235
return false;
224
236
} ,
225
- setTimeout ( func : ( ) = > void , delay ) : TimeoutID {
226
- const contextInstance = currentInstance ;
227
- return setTimeout ( ( ) => {
228
- const previousEventQueue = currentEventQueue ;
229
- const previousInstance = currentInstance ;
230
- currentEventQueue = createEventQueue ( ) ;
231
- currentInstance = contextInstance ;
232
- try {
233
- func ( ) ;
234
- batchedUpdates ( processEventQueue , currentEventQueue ) ;
235
- } finally {
236
- currentInstance = previousInstance ;
237
- currentEventQueue = previousEventQueue ;
237
+ setTimeout ( func : ( ) => void , delay ) : Symbol {
238
+ if ( currentTimers === null ) {
239
+ currentTimers = new Map ( ) ;
240
+ }
241
+ let timeout = currentTimers.get(delay);
242
+
243
+ const timerId = Symbol();
244
+ if (timeout === undefined) {
245
+ const timers = new Map ( ) ;
246
+ const id = setTimeout ( ( ) => {
247
+ processTimers ( timers ) ;
248
+ } , delay ) ;
249
+ timeout = {
250
+ id,
251
+ timers,
252
+ } ;
253
+ currentTimers . set ( delay , timeout ) ;
254
+ }
255
+ timeout.timers.set(timerId, {
256
+ instance : currentInstance ,
257
+ func ,
258
+ id : timerId ,
259
+ } );
260
+ activeTimeouts.set(timerId, timeout);
261
+ return timerId;
262
+ } ,
263
+ clearTimeout ( timerId : Symbol ) : void {
264
+ const timeout = activeTimeouts . get ( timerId ) ;
265
+
266
+ if ( timeout !== undefined ) {
267
+ const timers = timeout . timers ;
268
+ timers . delete ( timerId ) ;
269
+ if ( timers . size === 0 ) {
270
+ clearTimeout ( timeout . id ) ;
238
271
}
239
- } , delay ) ;
272
+ }
240
273
} ,
241
274
getEventTargetsFromTarget(
242
275
target: Element | Document,
@@ -292,6 +325,46 @@ const eventResponderContext: ReactResponderContext = {
292
325
} ,
293
326
} ;
294
327
328
+ function getEventsFromEventQueue ( capture ?: boolean ) : Array < EventObjectTypes > {
329
+ let events ;
330
+ if ( capture ) {
331
+ events = currentEventQueue . capture ;
332
+ if ( events === null ) {
333
+ events = currentEventQueue . capture = [ ] ;
334
+ }
335
+ } else {
336
+ events = currentEventQueue . bubble ;
337
+ if ( events === null ) {
338
+ events = currentEventQueue . bubble = [ ] ;
339
+ }
340
+ }
341
+ return events ;
342
+ }
343
+
344
+ function processTimers ( timers : Map < Symbol , ResponderTimer > ): void {
345
+ const previousEventQueue = currentEventQueue ;
346
+ const previousInstance = currentInstance ;
347
+ currentEventQueue = createEventQueue ( ) ;
348
+
349
+ try {
350
+ const timersArr = Array . from ( timers . values ( ) ) ;
351
+ for ( let i = 0 ; i < timersArr . length ; i ++ ) {
352
+ const { instance, func, id} = timersArr [ i ] ;
353
+ currentInstance = instance ;
354
+ try {
355
+ func ( ) ;
356
+ } finally {
357
+ activeTimeouts . delete ( id ) ;
358
+ }
359
+ }
360
+ batchedUpdates ( processEventQueue , currentEventQueue ) ;
361
+ } finally {
362
+ currentInstance = previousInstance ;
363
+ currentEventQueue = previousEventQueue ;
364
+ currentTimers = null ;
365
+ }
366
+ }
367
+
295
368
function queryEventTarget (
296
369
child : Fiber ,
297
370
queryType : void | Symbol | number ,
@@ -306,20 +379,6 @@ function queryEventTarget(
306
379
return true ;
307
380
}
308
381
309
- const rootEventTypesToEventComponentInstances : Map <
310
- DOMTopLevelEventType | string ,
311
- Set < ReactEventComponentInstance > ,
312
- > = new Map ( ) ;
313
- const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set ;
314
- const eventsWithStopPropagation :
315
- | WeakSet
316
- | Set < $Shape < PartialEventObject >> = new PossiblyWeakSet ( ) ;
317
- const targetEventTypeCached : Map <
318
- Array < ReactEventResponderEventType > ,
319
- Set < DOMTopLevelEventType > ,
320
- > = new Map ( ) ;
321
- const ownershipChangeListeners : Set < ReactEventComponentInstance > = new Set ( ) ;
322
-
323
382
function createResponderEvent (
324
383
topLevelType : string ,
325
384
nativeEvent : AnyNativeEvent ,
@@ -350,27 +409,27 @@ function processEvent(event: $Shape<PartialEventObject>): void {
350
409
}
351
410
352
411
function processEvents (
353
- bubble : null | Array < $Shape < PartialEventObject > >,
354
- capture : null | Array < $Shape < PartialEventObject > >,
412
+ bubble : null | Array < EventObjectTypes > ,
413
+ capture : null | Array < EventObjectTypes > ,
355
414
) : void {
356
415
let i , length ;
357
416
358
417
if ( capture !== null ) {
359
418
for ( i = capture . length ; i -- > 0 ; ) {
360
419
const event = capture [ i ] ;
361
- processEvent ( capture [ i ] ) ;
362
- if ( eventsWithStopPropagation . has ( event ) ) {
420
+ if ( event . stopPropagation === true ) {
363
421
return ;
364
422
}
423
+ processEvent ( ( ( event : any ) : $Shape < PartialEventObject > ) ) ;
365
424
}
366
425
}
367
426
if ( bubble !== null ) {
368
427
for ( i = 0 , length = bubble . length ; i < length ; ++ i ) {
369
428
const event = bubble [ i ] ;
370
- processEvent ( event ) ;
371
- if ( eventsWithStopPropagation . has ( event ) ) {
429
+ if ( event . stopPropagation === true ) {
372
430
return ;
373
431
}
432
+ processEvent ( ( ( event : any ) : $Shape < PartialEventObject > ) ) ;
374
433
}
375
434
}
376
435
}
@@ -475,6 +534,7 @@ export function runResponderEventsInBatch(
475
534
}
476
535
}
477
536
processEventQueue ( ) ;
537
+ currentTimers = null ;
478
538
}
479
539
}
480
540
@@ -518,6 +578,7 @@ export function unmountEventResponder(
518
578
} finally {
519
579
currentEventQueue = previousEventQueue ;
520
580
currentInstance = previousInstance ;
581
+ currentTimers = null ;
521
582
}
522
583
}
523
584
if ( currentOwner === eventComponentInstance ) {
0 commit comments