@@ -18,6 +18,7 @@ import {
18
18
HostComponent ,
19
19
} from 'shared/ReactWorkTags' ;
20
20
import type {
21
+ ReactEventResponder ,
21
22
ReactEventResponderEventType ,
22
23
ReactEventComponentInstance ,
23
24
ReactResponderContext ,
@@ -61,13 +62,10 @@ type ResponderTimeout = {|
61
62
62
63
type ResponderTimer = { |
63
64
instance : ReactEventComponentInstance ,
64
- func : ( ) => boolean ,
65
+ func : ( ) => void ,
65
66
id : Symbol ,
66
67
| } ;
67
68
68
- const ROOT_PHASE = 0 ;
69
- const BUBBLE_PHASE = 1 ;
70
- const CAPTURE_PHASE = 2 ;
71
69
const activeTimeouts : Map < Symbol , ResponderTimeout > = new Map ( ) ;
72
70
const rootEventTypesToEventComponentInstances : Map <
73
71
DOMTopLevelEventType | string ,
@@ -253,7 +251,7 @@ const eventResponderContext: ReactResponderContext = {
253
251
triggerOwnershipListeners ( ) ;
254
252
return false ;
255
253
} ,
256
- setTimeout ( func : ( ) = > boolean , delay ) : Symbol {
254
+ setTimeout ( func : ( ) = > void , delay ) : Symbol {
257
255
validateResponderContext ( ) ;
258
256
if ( currentTimers === null ) {
259
257
currentTimers = new Map ( ) ;
@@ -349,16 +347,13 @@ const eventResponderContext: ReactResponderContext = {
349
347
350
348
function processTimers ( timers : Map < Symbol , ResponderTimer > ) : void {
351
349
const timersArr = Array . from ( timers . values ( ) ) ;
352
- let shouldStopPropagation = false ;
353
350
currentEventQueue = createEventQueue ( ) ;
354
351
try {
355
352
for ( let i = 0 ; i < timersArr . length ; i ++ ) {
356
353
const { instance, func, id} = timersArr [ i ] ;
357
354
currentInstance = instance ;
358
355
try {
359
- if ( ! shouldStopPropagation ) {
360
- shouldStopPropagation = func ( ) ;
361
- }
356
+ func ( ) ;
362
357
} finally {
363
358
activeTimeouts . delete ( id ) ;
364
359
}
@@ -390,15 +385,13 @@ function createResponderEvent(
390
385
nativeEvent : AnyNativeEvent ,
391
386
nativeEventTarget : Element | Document ,
392
387
eventSystemFlags : EventSystemFlags ,
393
- phase : 0 | 1 | 2 ,
394
388
) : ReactResponderEvent {
395
389
const responderEvent = {
396
390
nativeEvent : nativeEvent ,
397
391
target : nativeEventTarget ,
398
392
type : topLevelType ,
399
393
passive : ( eventSystemFlags & IS_PASSIVE ) !== 0 ,
400
394
passiveSupported : ( eventSystemFlags & PASSIVE_NOT_SUPPORTED ) === 0 ,
401
- phase ,
402
395
} ;
403
396
if ( __DEV__ ) {
404
397
Object . freeze ( responderEvent ) ;
@@ -510,16 +503,7 @@ function getRootEventResponderInstances(
510
503
return eventResponderInstances ;
511
504
}
512
505
513
- function triggerEventResponderEventListener (
514
- responderEvent : ReactResponderEvent ,
515
- eventComponentInstance : ReactEventComponentInstance ,
516
- ) : boolean {
517
- const { responder , props , state } = eventComponentInstance ;
518
- currentInstance = eventComponentInstance ;
519
- return responder . onEvent ( responderEvent , eventResponderContext , props , state ) ;
520
- }
521
-
522
- function traverseAndTriggerEventResponderInstances (
506
+ function traverseAndHandleEventResponderInstances (
523
507
topLevelType : DOMTopLevelEventType ,
524
508
targetFiber : null | Fiber ,
525
509
nativeEvent : AnyNativeEvent ,
@@ -535,46 +519,54 @@ function traverseAndTriggerEventResponderInstances(
535
519
topLevelType ,
536
520
targetFiber ,
537
521
) ;
522
+ const responderEvent = createResponderEvent (
523
+ ( ( topLevelType : any ) : string ) ,
524
+ nativeEvent ,
525
+ ( ( nativeEventTarget : any ) : Element | Document ) ,
526
+ eventSystemFlags ,
527
+ ) ;
528
+ const propagatedEventResponders : Set < ReactEventResponder > = new Set ( ) ;
538
529
let length = targetEventResponderInstances . length ;
539
530
let i ;
540
- let shouldStopPropagation = false ;
541
- let responderEvent ;
542
531
532
+ // Captured and bubbled event phases have the notion of local propagation.
533
+ // This means that the propgation chain can be stopped part of the the way
534
+ // through processing event component instances. The major difference to other
535
+ // events systems is that the stopping of propgation is localized to a single
536
+ // phase, rather than both phases.
543
537
if ( length > 0 ) {
544
538
// Capture target phase
545
- responderEvent = createResponderEvent (
546
- ( ( topLevelType : any ) : string ) ,
547
- nativeEvent ,
548
- ( ( nativeEventTarget : any ) : Element | Document ) ,
549
- eventSystemFlags ,
550
- CAPTURE_PHASE ,
551
- ) ;
552
539
for ( i = length ; i -- > 0 ; ) {
553
540
const targetEventResponderInstance = targetEventResponderInstances [ i ] ;
554
- shouldStopPropagation = triggerEventResponderEventListener (
555
- responderEvent ,
556
- targetEventResponderInstance ,
557
- ) ;
558
- if ( shouldStopPropagation ) {
559
- return ;
541
+ const { responder , props , state } = targetEventResponderInstance ;
542
+ if ( responder . stopLocalPropagation ) {
543
+ if ( propagatedEventResponders . has ( responder ) ) {
544
+ continue ;
545
+ }
546
+ propagatedEventResponders . add ( responder ) ;
547
+ }
548
+ const eventListener = responder . onEventCapture ;
549
+ if ( eventListener !== undefined ) {
550
+ currentInstance = targetEventResponderInstance ;
551
+ eventListener ( responderEvent , eventResponderContext , props , state ) ;
560
552
}
561
553
}
554
+ // We clean propagated event responders between phases.
555
+ propagatedEventResponders . clear ( ) ;
562
556
// Bubble target phase
563
- responderEvent = createResponderEvent (
564
- ( ( topLevelType : any ) : string ) ,
565
- nativeEvent ,
566
- ( ( nativeEventTarget : any ) : Element | Document ) ,
567
- eventSystemFlags ,
568
- BUBBLE_PHASE ,
569
- ) ;
570
557
for ( i = 0 ; i < length ; i ++ ) {
571
558
const targetEventResponderInstance = targetEventResponderInstances [ i ] ;
572
- shouldStopPropagation = triggerEventResponderEventListener (
573
- responderEvent ,
574
- targetEventResponderInstance ,
575
- ) ;
576
- if ( shouldStopPropagation ) {
577
- return ;
559
+ const { responder , props , state } = targetEventResponderInstance ;
560
+ if ( responder . stopLocalPropagation ) {
561
+ if ( propagatedEventResponders . has ( responder ) ) {
562
+ continue ;
563
+ }
564
+ propagatedEventResponders . add ( responder ) ;
565
+ }
566
+ const eventListener = responder . onEvent ;
567
+ if ( eventListener !== undefined ) {
568
+ currentInstance = targetEventResponderInstance ;
569
+ eventListener ( responderEvent , eventResponderContext , props , state ) ;
578
570
}
579
571
}
580
572
}
@@ -584,21 +576,13 @@ function traverseAndTriggerEventResponderInstances(
584
576
) ;
585
577
length = rootEventResponderInstances . length ;
586
578
if ( length > 0 ) {
587
- responderEvent = createResponderEvent (
588
- ( ( topLevelType : any ) : string ) ,
589
- nativeEvent ,
590
- ( ( nativeEventTarget : any ) : Element | Document ) ,
591
- eventSystemFlags ,
592
- ROOT_PHASE ,
593
- ) ;
594
579
for ( i = 0 ; i < length ; i ++ ) {
595
- const targetEventResponderInstance = rootEventResponderInstances [ i ] ;
596
- shouldStopPropagation = triggerEventResponderEventListener (
597
- responderEvent ,
598
- targetEventResponderInstance ,
599
- ) ;
600
- if ( shouldStopPropagation ) {
601
- return ;
580
+ const rootEventResponderInstance = rootEventResponderInstances [ i ] ;
581
+ const { responder , props , state } = rootEventResponderInstance ;
582
+ const eventListener = responder . onRootEvent ;
583
+ if ( eventListener !== undefined ) {
584
+ currentInstance = rootEventResponderInstance ;
585
+ eventListener ( responderEvent , eventResponderContext , props , state ) ;
602
586
}
603
587
}
604
588
}
@@ -672,7 +656,7 @@ export function dispatchEventForResponderEventSystem(
672
656
if ( enableEventAPI ) {
673
657
currentEventQueue = createEventQueue ( ) ;
674
658
try {
675
- traverseAndTriggerEventResponderInstances (
659
+ traverseAndHandleEventResponderInstances (
676
660
topLevelType ,
677
661
targetFiber ,
678
662
nativeEvent ,
0 commit comments