8
8
*/
9
9
10
10
import { registrationNameDependencies } from 'events/EventPluginRegistry' ;
11
+ import type { DOMTopLevelEventType } from 'events/TopLevelEventTypes' ;
11
12
import {
12
13
TOP_BLUR ,
13
14
TOP_CANCEL ,
@@ -84,22 +85,23 @@ import isEventSupported from './isEventSupported';
84
85
* React Core . General Purpose Event Plugin System
85
86
*/
86
87
87
- const alreadyListeningTo = { } ;
88
- let reactTopListenersCounter = 0 ;
88
+ const PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map ;
89
+ const elementListeningSets :
90
+ | WeakMap
91
+ | Map <
92
+ Document | Element | Node ,
93
+ Set < DOMTopLevelEventType > ,
94
+ > = new PossiblyWeakMap ( ) ;
89
95
90
- /**
91
- * To ensure no conflicts with other potential React instances on the page
92
- */
93
- const topListenersIDKey = '_reactListenersID' + ( '' + Math . random ( ) ) . slice ( 2 ) ;
94
-
95
- function getListeningForDocument ( mountAt : any ) {
96
- // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
97
- // directly.
98
- if ( ! Object . prototype . hasOwnProperty . call ( mountAt , topListenersIDKey ) ) {
99
- mountAt [ topListenersIDKey ] = reactTopListenersCounter ++ ;
100
- alreadyListeningTo [ mountAt [ topListenersIDKey ] ] = { } ;
96
+ function getListeningSetForElement (
97
+ element : Document | Element | Node ,
98
+ ) : Set < DOMTopLevelEventType > {
99
+ let listeningSet = elementListeningSets . get ( element ) ;
100
+ if ( listeningSet === undefined ) {
101
+ listeningSet = new Set ( ) ;
102
+ elementListeningSets . set ( element , listeningSet ) ;
101
103
}
102
- return alreadyListeningTo [ mountAt [ topListenersIDKey ] ] ;
104
+ return listeningSet ;
103
105
}
104
106
105
107
/**
@@ -125,14 +127,14 @@ function getListeningForDocument(mountAt: any) {
125
127
*/
126
128
export function listenTo (
127
129
registrationName : string ,
128
- mountAt : Document | Element ,
129
- ) {
130
- const isListening = getListeningForDocument ( mountAt ) ;
130
+ mountAt : Document | Element | Node ,
131
+ ) : void {
132
+ const listeningSet = getListeningSetForElement ( mountAt ) ;
131
133
const dependencies = registrationNameDependencies [ registrationName ] ;
132
134
133
135
for ( let i = 0 ; i < dependencies . length ; i ++ ) {
134
136
const dependency = dependencies [ i ] ;
135
- if ( ! ( isListening . hasOwnProperty ( dependency ) && isListening [ dependency ] ) ) {
137
+ if ( ! listeningSet . has ( dependency ) ) {
136
138
switch ( dependency ) {
137
139
case TOP_SCROLL :
138
140
trapCapturedEvent ( TOP_SCROLL , mountAt ) ;
@@ -143,8 +145,8 @@ export function listenTo(
143
145
trapCapturedEvent ( TOP_BLUR , mountAt ) ;
144
146
// We set the flag for a single dependency later in this function,
145
147
// but this ensures we mark both as attached rather than just one.
146
- isListening [ TOP_BLUR ] = true ;
147
- isListening [ TOP_FOCUS ] = true ;
148
+ listeningSet . add ( TOP_BLUR ) ;
149
+ listeningSet . add ( TOP_FOCUS ) ;
148
150
break ;
149
151
case TOP_CANCEL :
150
152
case TOP_CLOSE :
@@ -167,20 +169,21 @@ export function listenTo(
167
169
}
168
170
break ;
169
171
}
170
- isListening [ dependency ] = true ;
172
+ listeningSet . add ( dependency ) ;
171
173
}
172
174
}
173
175
}
174
176
175
177
export function isListeningToAllDependencies (
176
178
registrationName : string ,
177
179
mountAt : Document | Element ,
178
- ) {
179
- const isListening = getListeningForDocument ( mountAt ) ;
180
+ ) : boolean {
181
+ const listeningSet = getListeningSetForElement ( mountAt ) ;
180
182
const dependencies = registrationNameDependencies [ registrationName ] ;
183
+
181
184
for ( let i = 0 ; i < dependencies . length ; i ++ ) {
182
185
const dependency = dependencies [ i ] ;
183
- if ( ! ( isListening . hasOwnProperty ( dependency ) && isListening [ dependency ] ) ) {
186
+ if ( ! listeningSet . has ( dependency ) ) {
184
187
return false ;
185
188
}
186
189
}
0 commit comments