@@ -52,7 +52,7 @@ export const SyncUpdateLanes: Lane = enableUnifiedSyncLane
52
52
: SyncLane ;
53
53
54
54
const TransitionHydrationLane : Lane = /* */ 0b0000000000000000000000001000000 ;
55
- const TransitionLanes : Lanes = /* */ 0b0000000011111111111111110000000 ;
55
+ const TransitionLanes : Lanes = /* */ 0b0000000001111111111111110000000 ;
56
56
const TransitionLane1 : Lane = /* */ 0b0000000000000000000000010000000 ;
57
57
const TransitionLane2 : Lane = /* */ 0b0000000000000000000000100000000 ;
58
58
const TransitionLane3 : Lane = /* */ 0b0000000000000000000001000000000 ;
@@ -68,24 +68,24 @@ const TransitionLane12: Lane = /* */ 0b0000000000001000000
68
68
const TransitionLane13 : Lane = /* */ 0b0000000000010000000000000000000 ;
69
69
const TransitionLane14 : Lane = /* */ 0b0000000000100000000000000000000 ;
70
70
const TransitionLane15 : Lane = /* */ 0b0000000001000000000000000000000 ;
71
- const TransitionLane16 : Lane = /* */ 0b0000000010000000000000000000000 ;
72
71
73
- const RetryLanes : Lanes = /* */ 0b0000111100000000000000000000000 ;
74
- const RetryLane1 : Lane = /* */ 0b0000000100000000000000000000000 ;
75
- const RetryLane2 : Lane = /* */ 0b0000001000000000000000000000000 ;
76
- const RetryLane3 : Lane = /* */ 0b0000010000000000000000000000000 ;
77
- const RetryLane4 : Lane = /* */ 0b0000100000000000000000000000000 ;
72
+ const RetryLanes : Lanes = /* */ 0b0000011110000000000000000000000 ;
73
+ const RetryLane1 : Lane = /* */ 0b0000000010000000000000000000000 ;
74
+ const RetryLane2 : Lane = /* */ 0b0000000100000000000000000000000 ;
75
+ const RetryLane3 : Lane = /* */ 0b0000001000000000000000000000000 ;
76
+ const RetryLane4 : Lane = /* */ 0b0000010000000000000000000000000 ;
78
77
79
78
export const SomeRetryLane : Lane = RetryLane1 ;
80
79
81
- export const SelectiveHydrationLane : Lane = /* */ 0b0001000000000000000000000000000 ;
80
+ export const SelectiveHydrationLane : Lane = /* */ 0b0000100000000000000000000000000 ;
82
81
83
- const NonIdleLanes : Lanes = /* */ 0b0001111111111111111111111111111 ;
82
+ const NonIdleLanes : Lanes = /* */ 0b0000111111111111111111111111111 ;
84
83
85
- export const IdleHydrationLane : Lane = /* */ 0b0010000000000000000000000000000 ;
86
- export const IdleLane : Lane = /* */ 0b0100000000000000000000000000000 ;
84
+ export const IdleHydrationLane : Lane = /* */ 0b0001000000000000000000000000000 ;
85
+ export const IdleLane : Lane = /* */ 0b0010000000000000000000000000000 ;
87
86
88
- export const OffscreenLane : Lane = /* */ 0b1000000000000000000000000000000 ;
87
+ export const OffscreenLane : Lane = /* */ 0b0100000000000000000000000000000 ;
88
+ export const DeferredLane : Lane = /* */ 0b1000000000000000000000000000000 ;
89
89
90
90
// Any lane that might schedule an update. This is used to detect infinite
91
91
// update loops, so it doesn't include hydration lanes or retries.
@@ -135,6 +135,9 @@ export function getLabelForLane(lane: Lane): string | void {
135
135
if ( lane & OffscreenLane ) {
136
136
return 'Offscreen' ;
137
137
}
138
+ if ( lane & DeferredLane ) {
139
+ return 'Deferred' ;
140
+ }
138
141
}
139
142
}
140
143
@@ -180,7 +183,6 @@ function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
180
183
case TransitionLane13 :
181
184
case TransitionLane14 :
182
185
case TransitionLane15 :
183
- case TransitionLane16 :
184
186
return lanes & TransitionLanes ;
185
187
case RetryLane1 :
186
188
case RetryLane2 :
@@ -195,6 +197,10 @@ function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
195
197
return IdleLane ;
196
198
case OffscreenLane :
197
199
return OffscreenLane ;
200
+ case DeferredLane :
201
+ // This shouldn't be reachable because deferred work is always entangled
202
+ // with something else.
203
+ return NoLanes ;
198
204
default :
199
205
if ( __DEV__ ) {
200
206
console . error (
@@ -367,7 +373,6 @@ function computeExpirationTime(lane: Lane, currentTime: number) {
367
373
case TransitionLane13 :
368
374
case TransitionLane14 :
369
375
case TransitionLane15 :
370
- case TransitionLane16 :
371
376
return currentTime + 5000 ;
372
377
case RetryLane1 :
373
378
case RetryLane2 :
@@ -383,6 +388,7 @@ function computeExpirationTime(lane: Lane, currentTime: number) {
383
388
case IdleHydrationLane :
384
389
case IdleLane :
385
390
case OffscreenLane :
391
+ case DeferredLane :
386
392
// Anything idle priority or lower should never expire.
387
393
return NoTimestamp ;
388
394
default :
@@ -616,7 +622,11 @@ export function markRootUpdated(root: FiberRoot, updateLane: Lane) {
616
622
}
617
623
}
618
624
619
- export function markRootSuspended ( root : FiberRoot , suspendedLanes : Lanes ) {
625
+ export function markRootSuspended (
626
+ root : FiberRoot ,
627
+ suspendedLanes : Lanes ,
628
+ spawnedLane : Lane ,
629
+ ) {
620
630
root . suspendedLanes |= suspendedLanes ;
621
631
root . pingedLanes &= ~ suspendedLanes ;
622
632
@@ -631,13 +641,21 @@ export function markRootSuspended(root: FiberRoot, suspendedLanes: Lanes) {
631
641
632
642
lanes &= ~ lane ;
633
643
}
644
+
645
+ if ( spawnedLane !== NoLane ) {
646
+ markSpawnedDeferredLane ( root , spawnedLane , suspendedLanes ) ;
647
+ }
634
648
}
635
649
636
650
export function markRootPinged(root: FiberRoot, pingedLanes: Lanes) {
637
651
root . pingedLanes |= root . suspendedLanes & pingedLanes ;
638
652
}
639
653
640
- export function markRootFinished(root: FiberRoot, remainingLanes: Lanes) {
654
+ export function markRootFinished(
655
+ root: FiberRoot,
656
+ remainingLanes: Lanes,
657
+ spawnedLane: Lane,
658
+ ) {
641
659
const noLongerPendingLanes = root . pendingLanes & ~ remainingLanes ;
642
660
643
661
root . pendingLanes = remainingLanes ;
@@ -683,6 +701,37 @@ export function markRootFinished(root: FiberRoot, remainingLanes: Lanes) {
683
701
684
702
lanes &= ~ lane ;
685
703
}
704
+
705
+ if ( spawnedLane !== NoLane ) {
706
+ markSpawnedDeferredLane (
707
+ root ,
708
+ spawnedLane ,
709
+ // This render finished successfully without suspending, so we don't need
710
+ // to entangle the spawned task with the parent task.
711
+ NoLanes ,
712
+ ) ;
713
+ }
714
+ }
715
+
716
+ function markSpawnedDeferredLane(
717
+ root: FiberRoot,
718
+ spawnedLane: Lane,
719
+ entangledLanes: Lanes,
720
+ ) {
721
+ // This render spawned a deferred task. Mark it as pending.
722
+ root . pendingLanes |= spawnedLane ;
723
+ root . suspendedLanes &= ~ spawnedLane ;
724
+
725
+ // Entangle the spawned lane with the DeferredLane bit so that we know it
726
+ // was the result of another render. This lets us avoid a useDeferredValue
727
+ // waterfall — only the first level will defer.
728
+ const spawnedLaneIndex = laneToIndex ( spawnedLane ) ;
729
+ root . entangledLanes |= spawnedLane ;
730
+ root . entanglements [ spawnedLaneIndex ] |=
731
+ DeferredLane |
732
+ // If the parent render task suspended, we must also entangle those lanes
733
+ // with the spawned task.
734
+ entangledLanes ;
686
735
}
687
736
688
737
export function markRootEntangled(root: FiberRoot, entangledLanes: Lanes) {
@@ -795,7 +844,6 @@ export function getBumpedLaneForHydration(
795
844
case TransitionLane13:
796
845
case TransitionLane14:
797
846
case TransitionLane15:
798
- case TransitionLane16:
799
847
case RetryLane1:
800
848
case RetryLane2:
801
849
case RetryLane3:
0 commit comments