@@ -90,8 +90,18 @@ type PointerEvent = Event & {
90
90
...
91
91
} ;
92
92
93
+ declare export class NullTarget { }
94
+ export const nullTarget : NullTarget = ( { } : any ) ;
95
+ export function isBlocked (
96
+ blockedOn : NullTarget | null | Container | SuspenseInstance ,
97
+ ) : Container | SuspenseInstance | void {
98
+ if ( blockedOn !== nullTarget && blockedOn !== null ) {
99
+ return ( ( blockedOn : any ) : Container | SuspenseInstance ) ;
100
+ }
101
+ }
102
+
93
103
type QueuedReplayableEvent = { |
94
- blockedOn : typeof undefined | null | Container | SuspenseInstance ,
104
+ blockedOn : NullTarget | null | Container | SuspenseInstance ,
95
105
domEventName : DOMEventName ,
96
106
eventSystemFlags : EventSystemFlags ,
97
107
nativeEvent : AnyNativeEvent ,
@@ -116,7 +126,7 @@ const queuedPointerCaptures: Map<number, QueuedReplayableEvent> = new Map();
116
126
// We could consider replaying selectionchange and touchmoves too.
117
127
118
128
type QueuedHydrationTarget = { |
119
- blockedOn : typeof undefined | null | Container | SuspenseInstance ,
129
+ blockedOn : NullTarget | null | Container | SuspenseInstance ,
120
130
target : Node ,
121
131
priority : EventPriority ,
122
132
| } ;
@@ -168,7 +178,7 @@ export function isDiscreteEventThatRequiresHydration(
168
178
}
169
179
170
180
function createQueuedReplayableEvent (
171
- blockedOn : typeof undefined | null | Container | SuspenseInstance ,
181
+ blockedOn : NullTarget | null | Container | SuspenseInstance ,
172
182
domEventName : DOMEventName ,
173
183
eventSystemFlags : EventSystemFlags ,
174
184
targetContainer : EventTarget ,
@@ -184,7 +194,7 @@ function createQueuedReplayableEvent(
184
194
}
185
195
186
196
export function queueDiscreteEvent (
187
- blockedOn : typeof undefined | null | Container | SuspenseInstance ,
197
+ blockedOn : NullTarget | null | Container | SuspenseInstance ,
188
198
domEventName : DOMEventName ,
189
199
eventSystemFlags : EventSystemFlags ,
190
200
targetContainer : EventTarget ,
@@ -205,13 +215,15 @@ export function queueDiscreteEvent(
205
215
if ( queuedDiscreteEvents . length === 1 ) {
206
216
// If this was the first discrete event, we might be able to
207
217
// synchronously unblock it so that preventDefault still works.
208
- while ( queuedEvent . blockedOn != null ) {
209
- const fiber = getInstanceFromNode ( queuedEvent . blockedOn ) ;
218
+ let blockedOnInst ;
219
+ while ( ( blockedOnInst = isBlocked ( queuedEvent . blockedOn ) ) ) {
220
+ const fiber = getInstanceFromNode ( blockedOnInst ) ;
210
221
if ( fiber === null ) {
211
222
break ;
212
223
}
213
224
attemptSynchronousHydration ( fiber ) ;
214
- if ( queuedEvent . blockedOn == null ) {
225
+ blockedOnInst = isBlocked ( queuedEvent . blockedOn ) ;
226
+ if ( ! blockedOnInst ) {
215
227
// We got unblocked by hydration. Let's try again.
216
228
replayUnblockedEvents ( ) ;
217
229
// If we're reblocked, on an inner boundary, we might need
@@ -262,7 +274,7 @@ export function clearIfContinuousEvent(
262
274
263
275
function accumulateOrCreateContinuousQueuedReplayableEvent (
264
276
existingQueuedEvent : null | QueuedReplayableEvent ,
265
- blockedOn : typeof undefined | null | Container | SuspenseInstance ,
277
+ blockedOn : NullTarget | null | Container | SuspenseInstance ,
266
278
domEventName : DOMEventName ,
267
279
eventSystemFlags : EventSystemFlags ,
268
280
targetContainer : EventTarget ,
@@ -279,8 +291,9 @@ function accumulateOrCreateContinuousQueuedReplayableEvent(
279
291
targetContainer ,
280
292
nativeEvent ,
281
293
) ;
282
- if ( blockedOn != null ) {
283
- const fiber = getInstanceFromNode ( blockedOn ) ;
294
+ const blockedOnInst = isBlocked ( blockedOn ) ;
295
+ if ( blockedOnInst ) {
296
+ const fiber = getInstanceFromNode ( blockedOnInst ) ;
284
297
if ( fiber !== null ) {
285
298
// Attempt to increase the priority of this target.
286
299
attemptContinuousHydration ( fiber ) ;
@@ -304,7 +317,7 @@ function accumulateOrCreateContinuousQueuedReplayableEvent(
304
317
}
305
318
306
319
export function queueIfContinuousEvent (
307
- blockedOn : typeof undefined | null | Container | SuspenseInstance ,
320
+ blockedOn : NullTarget | null | Container | SuspenseInstance ,
308
321
domEventName : DOMEventName ,
309
322
eventSystemFlags : EventSystemFlags ,
310
323
targetContainer : EventTarget ,
@@ -386,7 +399,6 @@ export function queueIfContinuousEvent(
386
399
return false ;
387
400
}
388
401
389
- // Check if this target is unblocked. Returns true if it's unblocked.
390
402
function attemptExplicitHydrationTarget (
391
403
queuedTarget : QueuedHydrationTarget ,
392
404
) : void {
@@ -454,7 +466,8 @@ export function queueExplicitHydrationTarget(target: Node): void {
454
466
function attemptReplayContinuousQueuedEvent (
455
467
queuedEvent : QueuedReplayableEvent ,
456
468
) : boolean {
457
- if ( queuedEvent . blockedOn != null ) {
469
+ const blockedOnInst = isBlocked ( queuedEvent . blockedOn ) ;
470
+ if ( blockedOnInst ) {
458
471
return false ;
459
472
}
460
473
const targetContainers = queuedEvent . targetContainers ;
@@ -466,16 +479,17 @@ function attemptReplayContinuousQueuedEvent(
466
479
targetContainer ,
467
480
queuedEvent . nativeEvent ,
468
481
) ;
469
- if ( nextBlockedOn != null ) {
482
+ const nextBlockedOnInst = isBlocked ( nextBlockedOn ) ;
483
+ if ( nextBlockedOnInst ) {
470
484
// We're still blocked. Try again later.
471
- const fiber = getInstanceFromNode ( nextBlockedOn ) ;
485
+ const fiber = getInstanceFromNode ( nextBlockedOnInst ) ;
472
486
if ( fiber !== null ) {
473
487
attemptContinuousHydration ( fiber ) ;
474
488
}
475
489
queuedEvent . blockedOn = nextBlockedOn ;
476
490
return false ;
477
491
}
478
- replayEvent ( queuedEvent , targetContainer ) ;
492
+ replayEvent ( queuedEvent , targetContainer , nextBlockedOn ) ;
479
493
// This target container was successfully dispatched. Try the next.
480
494
targetContainers . shift ( ) ;
481
495
}
@@ -498,11 +512,13 @@ function replayUnblockedEvents() {
498
512
// First replay discrete events.
499
513
while ( queuedDiscreteEvents . length > 0 ) {
500
514
const nextDiscreteEvent = queuedDiscreteEvents [ 0 ] ;
501
- if ( nextDiscreteEvent . blockedOn != null ) {
515
+ const blockedOn = nextDiscreteEvent . blockedOn ;
516
+ const blockedOnInst = isBlocked ( blockedOn ) ;
517
+ if ( blockedOnInst ) {
502
518
// We're still blocked.
503
519
// Increase the priority of this boundary to unblock
504
520
// the next discrete event.
505
- const fiber = getInstanceFromNode ( nextDiscreteEvent . blockedOn ) ;
521
+ const fiber = getInstanceFromNode ( blockedOnInst ) ;
506
522
if ( fiber !== null ) {
507
523
attemptDiscreteHydration ( fiber ) ;
508
524
}
@@ -517,16 +533,20 @@ function replayUnblockedEvents() {
517
533
targetContainer ,
518
534
nextDiscreteEvent . nativeEvent ,
519
535
) ;
520
- if ( nextBlockedOn != null ) {
536
+ const nextBlockedOnInst = isBlocked ( nextBlockedOn ) ;
537
+ if ( nextBlockedOnInst ) {
521
538
// We're still blocked. Try again later.
522
- nextDiscreteEvent . blockedOn = nextBlockedOn ;
539
+ nextDiscreteEvent . blockedOn = nextBlockedOnInst ;
523
540
break ;
524
541
}
525
- replayEvent ( nextDiscreteEvent , targetContainer ) ;
542
+ replayEvent ( nextDiscreteEvent , targetContainer , nextBlockedOn ) ;
526
543
// This target container was successfully dispatched. Try the next.
527
544
targetContainers . shift ( ) ;
528
545
}
529
- if ( nextDiscreteEvent . blockedOn == null ) {
546
+ if (
547
+ nextDiscreteEvent . blockedOn === null ||
548
+ nextDiscreteEvent . blockedOn === nullTarget
549
+ ) {
530
550
// We've successfully replayed the first event. Let's try the next one.
531
551
queuedDiscreteEvents . shift ( ) ;
532
552
}
@@ -603,12 +623,13 @@ export function retryIfBlockedOn(
603
623
604
624
while ( queuedExplicitHydrationTargets . length > 0 ) {
605
625
const nextExplicitTarget = queuedExplicitHydrationTargets [ 0 ] ;
606
- if ( nextExplicitTarget . blockedOn != null ) {
626
+ const blockedOnInst = isBlocked ( nextExplicitTarget . blockedOn ) ;
627
+ if ( blockedOnInst ) {
607
628
// We're still blocked.
608
629
break ;
609
630
} else {
610
631
attemptExplicitHydrationTarget ( nextExplicitTarget ) ;
611
- if ( nextExplicitTarget . blockedOn == null ) {
632
+ if ( ! isBlocked ( nextExplicitTarget . blockedOn ) ) {
612
633
// We're unblocked.
613
634
queuedExplicitHydrationTargets . shift ( ) ;
614
635
}
@@ -619,6 +640,7 @@ export function retryIfBlockedOn(
619
640
function replayEvent (
620
641
queuedEvent : QueuedReplayableEvent ,
621
642
targetContainer : EventTarget ,
643
+ targetInst : null | NullTarget | Container | SuspenseInstance ,
622
644
) {
623
645
const event = queuedEvent . nativeEvent ;
624
646
if ( enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay ) {
@@ -632,7 +654,9 @@ function replayEvent(
632
654
queuedEvent . domEventName ,
633
655
queuedEvent . eventSystemFlags ,
634
656
event ,
635
- getClosestInstanceFromNode ( getEventTarget ( queuedEvent . nativeEvent ) ) ,
657
+ targetInst === nullTarget
658
+ ? null
659
+ : getClosestInstanceFromNode ( getEventTarget ( queuedEvent . nativeEvent ) ) ,
636
660
targetContainer ,
637
661
) ;
638
662
} ) ;
0 commit comments