99import {
1010 type EventSystemFlags ,
1111 IS_PASSIVE ,
12+ IS_CAPTURE ,
1213 PASSIVE_NOT_SUPPORTED ,
1314} from 'events/EventSystemFlags' ;
1415import type { AnyNativeEvent } from 'events/PluginModuleType' ;
@@ -73,7 +74,7 @@ const rootEventTypesToEventComponentInstances: Map<
7374> = new Map ( ) ;
7475const targetEventTypeCached : Map <
7576 Array < ReactEventResponderEventType > ,
76- Set< DOMTopLevelEventType > ,
77+ Set< string > ,
7778> = new Map ( ) ;
7879const ownershipChangeListeners : Set < ReactEventComponentInstance > = new Set();
7980const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
@@ -235,32 +236,8 @@ const eventResponderContext: ReactResponderContext = {
235236 listenToResponderEventTypesImpl ( rootEventTypes , activeDocument ) ;
236237 for ( let i = 0 ; i < rootEventTypes . length ; i ++ ) {
237238 const rootEventType = rootEventTypes [ i ] ;
238- const topLevelEventType =
239- typeof rootEventType === 'string' ? rootEventType : rootEventType . name ;
240- let rootEventComponentInstances = rootEventTypesToEventComponentInstances . get (
241- topLevelEventType ,
242- ) ;
243- if ( rootEventComponentInstances === undefined ) {
244- rootEventComponentInstances = new Set ( ) ;
245- rootEventTypesToEventComponentInstances . set (
246- topLevelEventType ,
247- rootEventComponentInstances ,
248- ) ;
249- }
250- const componentInstance = ( ( currentInstance : any ) : ReactEventComponentInstance ) ;
251- let rootEventTypesSet = componentInstance . rootEventTypes ;
252- if ( rootEventTypesSet === null ) {
253- rootEventTypesSet = componentInstance . rootEventTypes = new Set ( ) ;
254- }
255- invariant (
256- ! rootEventTypesSet . has ( topLevelEventType ) ,
257- 'addRootEventTypes() found a duplicate root event ' +
258- 'type of "%s". This might be because the event type exists in the event responder "rootEventTypes" ' +
259- 'array or because of a previous addRootEventTypes() using this root event type.' ,
260- rootEventType ,
261- ) ;
262- rootEventTypesSet . add ( topLevelEventType ) ;
263- rootEventComponentInstances . add ( componentInstance ) ;
239+ const eventComponentInstance = ( ( currentInstance : any ) : ReactEventComponentInstance ) ;
240+ registerRootEventType ( rootEventType , eventComponentInstance ) ;
264241 }
265242 } ,
266243 removeRootEventTypes (
@@ -269,15 +246,37 @@ const eventResponderContext: ReactResponderContext = {
269246 validateResponderContext ( ) ;
270247 for ( let i = 0 ; i < rootEventTypes . length ; i ++ ) {
271248 const rootEventType = rootEventTypes [ i ] ;
272- const topLevelEventType =
273- typeof rootEventType === 'string' ? rootEventType : rootEventType . name ;
249+ let name = rootEventType ;
250+ let capture = false ;
251+ let passive = true ;
252+
253+ if ( typeof rootEventType !== 'string' ) {
254+ const targetEventConfigObject = ( ( rootEventType : any ) : {
255+ name : string ,
256+ passive ?: boolean ,
257+ capture ?: boolean ,
258+ } ) ;
259+ name = targetEventConfigObject . name ;
260+ if ( targetEventConfigObject . passive !== undefined ) {
261+ passive = targetEventConfigObject . passive ;
262+ }
263+ if ( targetEventConfigObject . capture !== undefined ) {
264+ capture = targetEventConfigObject . capture ;
265+ }
266+ }
267+
268+ const listeningName = generateListeningKey (
269+ ( ( name : any ) : string ) ,
270+ passive ,
271+ capture ,
272+ ) ;
274273 let rootEventComponents = rootEventTypesToEventComponentInstances . get (
275- topLevelEventType ,
274+ listeningName ,
276275 ) ;
277276 let rootEventTypesSet = ( ( currentInstance : any ) : ReactEventComponentInstance )
278277 . rootEventTypes ;
279278 if ( rootEventTypesSet !== null ) {
280- rootEventTypesSet . delete ( topLevelEventType ) ;
279+ rootEventTypesSet . delete ( listeningName ) ;
281280 }
282281 if ( rootEventComponents !== undefined ) {
283282 rootEventComponents . delete (
@@ -476,14 +475,15 @@ function createResponderEvent(
476475 topLevelType : string ,
477476 nativeEvent : AnyNativeEvent ,
478477 nativeEventTarget : Element | Document ,
479- eventSystemFlags : EventSystemFlags ,
478+ passive : boolean ,
479+ passiveSupported : boolean ,
480480) : ReactResponderEvent {
481481 const responderEvent = {
482482 nativeEvent : nativeEvent ,
483483 target : nativeEventTarget ,
484484 type : topLevelType ,
485- passive : ( eventSystemFlags & IS_PASSIVE ) !== 0 ,
486- passiveSupported : ( eventSystemFlags & PASSIVE_NOT_SUPPORTED ) === 0 ,
485+ passive,
486+ passiveSupported,
487487 } ;
488488 if ( __DEV__ ) {
489489 Object . freeze ( responderEvent ) ;
@@ -529,24 +529,45 @@ export function processEventQueue(): void {
529529
530530function getTargetEventTypesSet (
531531 eventTypes : Array < ReactEventResponderEventType > ,
532- ) : Set < DOMTopLevelEventType > {
532+ ) : Set < string > {
533533 let cachedSet = targetEventTypeCached . get ( eventTypes ) ;
534534
535535 if ( cachedSet === undefined ) {
536536 cachedSet = new Set ( ) ;
537537 for ( let i = 0 ; i < eventTypes . length ; i ++ ) {
538538 const eventType = eventTypes [ i ] ;
539- const topLevelEventType =
540- typeof eventType === 'string' ? eventType : eventType . name ;
541- cachedSet . add ( ( ( topLevelEventType : any ) : DOMTopLevelEventType ) ) ;
539+ let name = eventType ;
540+ let capture = false ;
541+ let passive = true ;
542+
543+ if ( typeof eventType !== 'string' ) {
544+ const targetEventConfigObject = ( ( eventType : any ) : {
545+ name : string ,
546+ passive ?: boolean ,
547+ capture ?: boolean ,
548+ } ) ;
549+ name = targetEventConfigObject . name ;
550+ if ( targetEventConfigObject . passive !== undefined ) {
551+ passive = targetEventConfigObject . passive ;
552+ }
553+ if ( targetEventConfigObject . capture !== undefined ) {
554+ capture = targetEventConfigObject . capture ;
555+ }
556+ }
557+ const listeningName = generateListeningKey (
558+ ( ( name : any ) : string ) ,
559+ passive ,
560+ capture ,
561+ ) ;
562+ cachedSet . add ( listeningName ) ;
542563 }
543564 targetEventTypeCached . set ( eventTypes , cachedSet ) ;
544565 }
545566 return cachedSet ;
546567}
547568
548569function getTargetEventResponderInstances (
549- topLevelType : DOMTopLevelEventType ,
570+ listeningName : string ,
550571 targetFiber : null | Fiber ,
551572) : Array < ReactEventComponentInstance > {
552573 const eventResponderInstances = [ ] ;
@@ -560,7 +581,7 @@ function getTargetEventResponderInstances(
560581 // Validate the target event type exists on the responder
561582 if ( targetEventTypes !== undefined ) {
562583 const targetEventTypesSet = getTargetEventTypesSet ( targetEventTypes ) ;
563- if ( targetEventTypesSet . has ( topLevelType ) ) {
584+ if ( targetEventTypesSet . has ( listeningName ) ) {
564585 eventResponderInstances . push ( eventComponentInstance ) ;
565586 }
566587 }
@@ -571,11 +592,11 @@ function getTargetEventResponderInstances(
571592}
572593
573594function getRootEventResponderInstances (
574- topLevelType : DOMTopLevelEventType ,
595+ listeningName : string ,
575596) : Array < ReactEventComponentInstance > {
576597 const eventResponderInstances = [ ] ;
577598 const rootEventInstances = rootEventTypesToEventComponentInstances . get (
578- topLevelType ,
599+ listeningName ,
579600 ) ;
580601 if ( rootEventInstances !== undefined ) {
581602 const rootEventComponentInstances = Array . from ( rootEventInstances ) ;
@@ -618,20 +639,30 @@ function traverseAndHandleEventResponderInstances(
618639 nativeEventTarget : EventTarget ,
619640 eventSystemFlags : EventSystemFlags ,
620641) : void {
642+ const isPassiveEvent = ( eventSystemFlags & IS_PASSIVE ) !== 0 ;
643+ const isCaptureEvent = ( eventSystemFlags & IS_CAPTURE ) !== 0 ;
644+ const isPassiveSupported = ( eventSystemFlags & PASSIVE_NOT_SUPPORTED ) === 0 ;
645+ const listeningName = generateListeningKey (
646+ ( ( topLevelType : any ) : string ) ,
647+ isPassiveEvent || ! isPassiveSupported ,
648+ isCaptureEvent ,
649+ ) ;
650+
621651 // Trigger event responders in this order:
622652 // - Capture target phase
623653 // - Bubble target phase
624654 // - Root phase
625655
626656 const targetEventResponderInstances = getTargetEventResponderInstances (
627- topLevelType ,
657+ listeningName ,
628658 targetFiber ,
629659 ) ;
630660 const responderEvent = createResponderEvent (
631661 ( ( topLevelType : any ) : string ) ,
632662 nativeEvent ,
633663 ( ( nativeEventTarget : any ) : Element | Document ) ,
634- eventSystemFlags ,
664+ isPassiveEvent ,
665+ isPassiveSupported ,
635666 ) ;
636667 const propagatedEventResponders : Set < ReactEventResponder > = new Set ( ) ;
637668 let length = targetEventResponderInstances . length ;
@@ -684,7 +715,7 @@ function traverseAndHandleEventResponderInstances(
684715 }
685716 // Root phase
686717 const rootEventResponderInstances = getRootEventResponderInstances (
687- topLevelType ,
718+ listeningName ,
688719 ) ;
689720 length = rootEventResponderInstances . length ;
690721 if ( length > 0 ) {
@@ -835,25 +866,74 @@ export function addRootEventTypesForComponentInstance(
835866) : void {
836867 for ( let i = 0 ; i < rootEventTypes . length ; i ++ ) {
837868 const rootEventType = rootEventTypes [ i ] ;
838- const topLevelEventType =
839- typeof rootEventType === 'string' ? rootEventType : rootEventType . name ;
840- let rootEventComponentInstances = rootEventTypesToEventComponentInstances . get (
841- topLevelEventType ,
842- ) ;
843- if ( rootEventComponentInstances === undefined ) {
844- rootEventComponentInstances = new Set ( ) ;
845- rootEventTypesToEventComponentInstances . set (
846- topLevelEventType ,
847- rootEventComponentInstances ,
848- ) ;
869+ registerRootEventType ( rootEventType , eventComponentInstance ) ;
870+ }
871+ }
872+
873+ function registerRootEventType (
874+ rootEventType : ReactEventResponderEventType ,
875+ eventComponentInstance : ReactEventComponentInstance ,
876+ ) : void {
877+ let name = rootEventType ;
878+ let capture = false ;
879+ let passive = true ;
880+
881+ if ( typeof rootEventType !== 'string' ) {
882+ const targetEventConfigObject = ( ( rootEventType : any ) : {
883+ name : string ,
884+ passive ?: boolean ,
885+ capture ?: boolean ,
886+ } ) ;
887+ name = targetEventConfigObject . name ;
888+ if ( targetEventConfigObject . passive !== undefined ) {
889+ passive = targetEventConfigObject . passive ;
849890 }
850- let rootEventTypesSet = eventComponentInstance . rootEventTypes ;
851- if ( rootEventTypesSet === null ) {
852- rootEventTypesSet = eventComponentInstance . rootEventTypes = new Set ( ) ;
891+ if ( targetEventConfigObject . capture !== undefined ) {
892+ capture = targetEventConfigObject . capture ;
853893 }
854- rootEventTypesSet . add ( topLevelEventType ) ;
855- rootEventComponentInstances . add (
856- ( ( eventComponentInstance : any ) : ReactEventComponentInstance ) ,
894+ }
895+
896+ const listeningName = generateListeningKey (
897+ ( ( name : any ) : string ) ,
898+ passive ,
899+ capture ,
900+ ) ;
901+ let rootEventComponentInstances = rootEventTypesToEventComponentInstances . get (
902+ listeningName ,
903+ ) ;
904+ if ( rootEventComponentInstances === undefined ) {
905+ rootEventComponentInstances = new Set ( ) ;
906+ rootEventTypesToEventComponentInstances . set (
907+ listeningName ,
908+ rootEventComponentInstances ,
857909 ) ;
858910 }
911+ let rootEventTypesSet = eventComponentInstance . rootEventTypes ;
912+ if ( rootEventTypesSet === null ) {
913+ rootEventTypesSet = eventComponentInstance . rootEventTypes = new Set ( ) ;
914+ }
915+ invariant (
916+ ! rootEventTypesSet . has ( listeningName ) ,
917+ 'addRootEventTypes() found a duplicate root event ' +
918+ 'type of "%s". This might be because the event type exists in the event responder "rootEventTypes" ' +
919+ 'array or because of a previous addRootEventTypes() using this root event type.' ,
920+ name ,
921+ ) ;
922+ rootEventTypesSet . add ( listeningName ) ;
923+ rootEventComponentInstances . add (
924+ ( ( eventComponentInstance : any ) : ReactEventComponentInstance ) ,
925+ ) ;
926+ }
927+
928+ export function generateListeningKey (
929+ topLevelType : string ,
930+ passive : boolean ,
931+ capture : boolean ,
932+ ) : string {
933+ // Create a unique name for this event, plus its properties. We'll
934+ // use this to ensure we don't listen to the same event with the same
935+ // properties again.
936+ const passiveKey = passive ? '_passive' : '_active' ;
937+ const captureKey = capture ? '_capture' : '' ;
938+ return `${ topLevelType } ${ passiveKey } ${ captureKey } ` ;
859939}
0 commit comments