@@ -22,8 +22,8 @@ import {
22
22
EventTarget as EventTargetWorkTag ,
23
23
} from 'shared/ReactWorkTags' ;
24
24
import type {
25
- ReactEventResponder ,
26
25
ReactEventResponderEventType ,
26
+ ReactEventComponentInstance ,
27
27
} from 'shared/ReactTypes' ;
28
28
import type { DOMTopLevelEventType } from 'events/TopLevelEventTypes' ;
29
29
import { batchedUpdates , interactiveUpdates } from 'events/ReactGenericBatching' ;
@@ -55,7 +55,7 @@ type PartialEventObject = {
55
55
} ;
56
56
57
57
let currentOwner = null ;
58
- let currentFiber : Fiber ;
58
+ let currentInstance : ReactEventComponentInstance ;
59
59
let currentEventQueue : EventQueue ;
60
60
61
61
const eventResponderContext : ResponderContext = {
@@ -140,12 +140,10 @@ const eventResponderContext: ResponderContext = {
140
140
return false ;
141
141
} ,
142
142
isTargetWithinEventComponent ( target : Element | Document ) : boolean {
143
- const eventFiber = currentFiber ;
144
-
145
143
if ( target != null ) {
146
144
let fiber = getClosestInstanceFromNode ( target ) ;
147
145
while ( fiber !== null ) {
148
- if ( fiber === eventFiber || fiber === eventFiber . alternate ) {
146
+ if ( fiber . stateNode === currentInstance ) {
149
147
return true ;
150
148
}
151
149
fiber = fiber . return ;
@@ -174,78 +172,78 @@ const eventResponderContext: ResponderContext = {
174
172
rootEventTypes : Array < ReactEventResponderEventType > ,
175
173
) : void {
176
174
listenToResponderEventTypesImpl ( rootEventTypes , doc ) ;
177
- const eventComponent = currentFiber ;
178
175
for ( let i = 0 ; i < rootEventTypes . length ; i ++ ) {
179
176
const rootEventType = rootEventTypes [ i ] ;
180
177
const topLevelEventType =
181
178
typeof rootEventType === 'string' ? rootEventType : rootEventType . name ;
182
- let rootEventComponents = rootEventTypesToEventComponents . get (
179
+ let rootEventComponentInstances = rootEventTypesToEventComponentInstances . get (
183
180
topLevelEventType ,
184
181
) ;
185
- if ( rootEventComponents === undefined ) {
186
- rootEventComponents = new Set ( ) ;
187
- rootEventTypesToEventComponents . set (
182
+ if ( rootEventComponentInstances === undefined ) {
183
+ rootEventComponentInstances = new Set ( ) ;
184
+ rootEventTypesToEventComponentInstances . set (
188
185
topLevelEventType ,
189
- rootEventComponents ,
186
+ rootEventComponentInstances ,
190
187
) ;
191
188
}
192
- rootEventComponents . add ( eventComponent ) ;
189
+ rootEventComponentInstances . add ( currentInstance ) ;
193
190
}
194
191
} ,
195
192
removeRootEventTypes (
196
193
rootEventTypes : Array < ReactEventResponderEventType > ,
197
194
) : void {
198
- const eventComponent = currentFiber ;
199
195
for ( let i = 0 ; i < rootEventTypes . length ; i ++ ) {
200
196
const rootEventType = rootEventTypes [ i ] ;
201
197
const topLevelEventType =
202
198
typeof rootEventType === 'string' ? rootEventType : rootEventType . name ;
203
- let rootEventComponents = rootEventTypesToEventComponents . get (
199
+ let rootEventComponents = rootEventTypesToEventComponentInstances . get (
204
200
topLevelEventType ,
205
201
) ;
206
202
if ( rootEventComponents !== undefined ) {
207
- rootEventComponents . delete ( eventComponent ) ;
203
+ rootEventComponents . delete ( currentInstance ) ;
208
204
}
209
205
}
210
206
} ,
211
207
hasOwnership ( ) : boolean {
212
- return currentOwner === currentFiber ;
208
+ return currentOwner === currentInstance ;
213
209
} ,
214
210
requestOwnership ( ) : boolean {
215
211
if ( currentOwner !== null ) {
216
212
return false ;
217
213
}
218
- currentOwner = currentFiber ;
214
+ currentOwner = currentInstance ;
215
+ triggerOwnershipListeners ( ) ;
219
216
return true ;
220
217
} ,
221
218
releaseOwnership ( ) : boolean {
222
- if ( currentOwner !== currentFiber ) {
219
+ if ( currentOwner !== currentInstance ) {
223
220
return false ;
224
221
}
225
222
currentOwner = null ;
223
+ triggerOwnershipListeners ( ) ;
226
224
return false ;
227
225
} ,
228
226
setTimeout ( func : ( ) = > void , delay ) : TimeoutID {
229
- const contextFiber = currentFiber ;
227
+ const contextInstance = currentInstance ;
230
228
return setTimeout ( ( ) => {
231
229
const previousEventQueue = currentEventQueue ;
232
- const previousFiber = currentFiber ;
230
+ const previousInstance = currentInstance ;
233
231
currentEventQueue = createEventQueue ( ) ;
234
- currentFiber = contextFiber ;
232
+ currentInstance = contextInstance ;
235
233
try {
236
234
func ( ) ;
237
235
batchedUpdates ( processEventQueue , currentEventQueue ) ;
238
236
} finally {
239
- currentFiber = previousFiber ;
237
+ currentInstance = previousInstance ;
240
238
currentEventQueue = previousEventQueue ;
241
239
}
242
240
} , delay ) ;
243
241
} ,
244
242
} ;
245
243
246
- const rootEventTypesToEventComponents : Map <
244
+ const rootEventTypesToEventComponentInstances : Map <
247
245
DOMTopLevelEventType | string ,
248
- Set < Fiber > ,
246
+ Set < ReactEventComponentInstance > ,
249
247
> = new Map ( ) ;
250
248
const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set ;
251
249
const eventsWithStopPropagation :
@@ -255,6 +253,7 @@ const targetEventTypeCached: Map<
255
253
Array < ReactEventResponderEventType > ,
256
254
Set< DOMTopLevelEventType > ,
257
255
> = new Map ( ) ;
256
+ const ownershipChangeListeners : Set < ReactEventComponentInstance > = new Set();
258
257
259
258
function createResponderEvent(
260
259
topLevelType: string,
@@ -343,25 +342,24 @@ function getTargetEventTypes(
343
342
344
343
function handleTopLevelType(
345
344
topLevelType: DOMTopLevelEventType,
346
- fiber : Fiber ,
347
345
responderEvent: ResponderEvent,
346
+ eventComponentInstance: ReactEventComponentInstance,
348
347
isRootLevelEvent: boolean,
349
348
): void {
350
- const responder : ReactEventResponder = fiber . type . responder ;
349
+ let { props , responder , state } = eventComponentInstance ;
351
350
if (!isRootLevelEvent) {
352
351
// Validate the target event type exists on the responder
353
352
const targetEventTypes = getTargetEventTypes ( responder . targetEventTypes ) ;
354
353
if ( ! targetEventTypes . has ( topLevelType ) ) {
355
354
return;
356
355
}
357
356
}
358
- let { props, state} = fiber . stateNode ;
359
- const previousFiber = currentFiber ;
360
- currentFiber = fiber ;
357
+ const previousInstance = currentInstance;
358
+ currentInstance = eventComponentInstance;
361
359
try {
362
360
responder . onEvent ( responderEvent , eventResponderContext , props , state ) ;
363
361
} finally {
364
- currentFiber = previousFiber ;
362
+ currentInstance = previousInstance ;
365
363
}
366
364
}
367
365
@@ -384,23 +382,29 @@ export function runResponderEventsInBatch(
384
382
// Traverse up the fiber tree till we find event component fibers.
385
383
while ( node !== null ) {
386
384
if ( node . tag === EventComponent ) {
387
- handleTopLevelType ( topLevelType , node , responderEvent , false ) ;
385
+ const eventComponentInstance = node . stateNode ;
386
+ handleTopLevelType (
387
+ topLevelType ,
388
+ responderEvent ,
389
+ eventComponentInstance ,
390
+ false ,
391
+ ) ;
388
392
}
389
393
node = node . return ;
390
394
}
391
395
// Handle root level events
392
- const rootEventComponents = rootEventTypesToEventComponents . get (
396
+ const rootEventInstances = rootEventTypesToEventComponentInstances . get (
393
397
topLevelType ,
394
398
) ;
395
- if ( rootEventComponents !== undefined ) {
396
- const rootEventComponentFibers = Array . from ( rootEventComponents ) ;
399
+ if ( rootEventInstances !== undefined ) {
400
+ const rootEventComponentInstances = Array . from ( rootEventInstances ) ;
397
401
398
- for ( let i = 0 ; i < rootEventComponentFibers . length ; i ++ ) {
399
- const rootEventComponentFiber = rootEventComponentFibers [ i ] ;
402
+ for ( let i = 0 ; i < rootEventComponentInstances . length ; i ++ ) {
403
+ const rootEventComponentInstance = rootEventComponentInstances [ i ] ;
400
404
handleTopLevelType (
401
405
topLevelType ,
402
- rootEventComponentFiber ,
403
406
responderEvent ,
407
+ rootEventComponentInstance ,
404
408
true ,
405
409
) ;
406
410
}
@@ -409,26 +413,53 @@ export function runResponderEventsInBatch(
409
413
}
410
414
}
411
415
416
+ function triggerOwnershipListeners(): void {
417
+ const listeningInstances = Array . from ( ownershipChangeListeners ) ;
418
+ const previousInstance = currentInstance ;
419
+ for ( let i = 0 ; i < listeningInstances . length ; i ++ ) {
420
+ const instance = listeningInstances [ i ] ;
421
+ const { props, responder, state} = instance ;
422
+ currentInstance = instance ;
423
+ try {
424
+ responder. onOwnershipChange ( eventResponderContext , props , state ) ;
425
+ } finally {
426
+ currentInstance = previousInstance ;
427
+ }
428
+ }
429
+ }
430
+
431
+ export function mountEventResponder(
432
+ eventComponentInstance: ReactEventComponentInstance,
433
+ ) {
434
+ const responder = eventComponentInstance . responder ;
435
+ if ( responder . onOwnershipChange !== undefined ) {
436
+ ownershipChangeListeners . add ( eventComponentInstance ) ;
437
+ }
438
+ }
439
+
412
440
export function unmountEventResponder (
413
- responder : ReactEventResponder ,
414
- fiber : Fiber ,
441
+ eventComponentInstance : ReactEventComponentInstance ,
415
442
) : void {
443
+ const responder = eventComponentInstance . responder ;
416
444
const onUnmount = responder . onUnmount ;
417
445
if ( onUnmount !== undefined ) {
418
- let { props , state } = fiber . stateNode ;
446
+ let { props, state} = eventComponentInstance ;
419
447
const previousEventQueue = currentEventQueue ;
420
- const previousFiber = currentFiber ;
448
+ const previousInstance = currentInstance ;
421
449
currentEventQueue = createEventQueue ( ) ;
422
- currentFiber = fiber ;
450
+ currentInstance = eventComponentInstance ;
423
451
try {
424
452
onUnmount ( eventResponderContext , props , state ) ;
425
453
} finally {
426
454
currentEventQueue = previousEventQueue ;
427
- currentFiber = previousFiber ;
455
+ currentInstance = previousInstance ;
428
456
}
429
457
}
430
- if ( currentOwner === fiber ) {
431
- // TODO fire owner changed callback
458
+ if ( currentOwner === eventComponentInstance ) {
432
459
currentOwner = null ;
460
+ triggerOwnershipListeners ( ) ;
461
+ }
462
+ if ( responder . onOwnershipChange !== undefined ) {
463
+ ownershipChangeListeners . delete ( eventComponentInstance ) ;
433
464
}
434
465
}
0 commit comments