@@ -52,7 +52,7 @@ export const SyncUpdateLanes: Lane = enableUnifiedSyncLane
5252 : SyncLane ;
5353
5454const TransitionHydrationLane : Lane = /* */ 0b0000000000000000000000001000000 ;
55- const TransitionLanes : Lanes = /* */ 0b0000000011111111111111110000000 ;
55+ const TransitionLanes : Lanes = /* */ 0b0000000001111111111111110000000 ;
5656const TransitionLane1 : Lane = /* */ 0b0000000000000000000000010000000 ;
5757const TransitionLane2 : Lane = /* */ 0b0000000000000000000000100000000 ;
5858const TransitionLane3 : Lane = /* */ 0b0000000000000000000001000000000 ;
@@ -68,24 +68,24 @@ const TransitionLane12: Lane = /* */ 0b0000000000001000000
6868const TransitionLane13 : Lane = /* */ 0b0000000000010000000000000000000 ;
6969const TransitionLane14 : Lane = /* */ 0b0000000000100000000000000000000 ;
7070const TransitionLane15 : Lane = /* */ 0b0000000001000000000000000000000 ;
71- const TransitionLane16 : Lane = /* */ 0b0000000010000000000000000000000 ;
7271
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 ;
7877
7978export const SomeRetryLane : Lane = RetryLane1 ;
8079
81- export const SelectiveHydrationLane : Lane = /* */ 0b0001000000000000000000000000000 ;
80+ export const SelectiveHydrationLane : Lane = /* */ 0b0000100000000000000000000000000 ;
8281
83- const NonIdleLanes : Lanes = /* */ 0b0001111111111111111111111111111 ;
82+ const NonIdleLanes : Lanes = /* */ 0b0000111111111111111111111111111 ;
8483
85- export const IdleHydrationLane : Lane = /* */ 0b0010000000000000000000000000000 ;
86- export const IdleLane : Lane = /* */ 0b0100000000000000000000000000000 ;
84+ export const IdleHydrationLane : Lane = /* */ 0b0001000000000000000000000000000 ;
85+ export const IdleLane : Lane = /* */ 0b0010000000000000000000000000000 ;
8786
88- export const OffscreenLane : Lane = /* */ 0b1000000000000000000000000000000 ;
87+ export const OffscreenLane : Lane = /* */ 0b0100000000000000000000000000000 ;
88+ export const DeferredLane : Lane = /* */ 0b1000000000000000000000000000000 ;
8989
9090// Any lane that might schedule an update. This is used to detect infinite
9191// update loops, so it doesn't include hydration lanes or retries.
@@ -135,6 +135,9 @@ export function getLabelForLane(lane: Lane): string | void {
135135 if ( lane & OffscreenLane ) {
136136 return 'Offscreen' ;
137137 }
138+ if ( lane & DeferredLane ) {
139+ return 'Deferred' ;
140+ }
138141 }
139142}
140143
@@ -180,7 +183,6 @@ function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
180183 case TransitionLane13 :
181184 case TransitionLane14 :
182185 case TransitionLane15 :
183- case TransitionLane16 :
184186 return lanes & TransitionLanes ;
185187 case RetryLane1 :
186188 case RetryLane2 :
@@ -195,6 +197,10 @@ function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
195197 return IdleLane ;
196198 case OffscreenLane :
197199 return OffscreenLane ;
200+ case DeferredLane :
201+ // This shouldn't be reachable because deferred work is always entangled
202+ // with something else.
203+ return NoLanes ;
198204 default :
199205 if ( __DEV__ ) {
200206 console . error (
@@ -367,7 +373,6 @@ function computeExpirationTime(lane: Lane, currentTime: number) {
367373 case TransitionLane13 :
368374 case TransitionLane14 :
369375 case TransitionLane15 :
370- case TransitionLane16 :
371376 return currentTime + 5000 ;
372377 case RetryLane1 :
373378 case RetryLane2 :
@@ -383,6 +388,7 @@ function computeExpirationTime(lane: Lane, currentTime: number) {
383388 case IdleHydrationLane :
384389 case IdleLane :
385390 case OffscreenLane :
391+ case DeferredLane :
386392 // Anything idle priority or lower should never expire.
387393 return NoTimestamp ;
388394 default :
@@ -616,7 +622,11 @@ export function markRootUpdated(root: FiberRoot, updateLane: Lane) {
616622 }
617623}
618624
619- export function markRootSuspended ( root : FiberRoot , suspendedLanes : Lanes ) {
625+ export function markRootSuspended (
626+ root : FiberRoot ,
627+ suspendedLanes : Lanes ,
628+ spawnedLane : Lane ,
629+ ) {
620630 root . suspendedLanes |= suspendedLanes ;
621631 root . pingedLanes &= ~ suspendedLanes ;
622632
@@ -631,13 +641,21 @@ export function markRootSuspended(root: FiberRoot, suspendedLanes: Lanes) {
631641
632642 lanes &= ~ lane ;
633643 }
644+
645+ if ( spawnedLane !== NoLane ) {
646+ markSpawnedDeferredLane ( root , spawnedLane , suspendedLanes ) ;
647+ }
634648}
635649
636650export function markRootPinged(root: FiberRoot, pingedLanes: Lanes) {
637651 root . pingedLanes |= root . suspendedLanes & pingedLanes ;
638652}
639653
640- export function markRootFinished(root: FiberRoot, remainingLanes: Lanes) {
654+ export function markRootFinished(
655+ root: FiberRoot,
656+ remainingLanes: Lanes,
657+ spawnedLane: Lane,
658+ ) {
641659 const noLongerPendingLanes = root . pendingLanes & ~ remainingLanes ;
642660
643661 root . pendingLanes = remainingLanes ;
@@ -683,6 +701,37 @@ export function markRootFinished(root: FiberRoot, remainingLanes: Lanes) {
683701
684702 lanes &= ~ lane ;
685703 }
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 ;
686735}
687736
688737export function markRootEntangled(root: FiberRoot, entangledLanes: Lanes) {
@@ -795,7 +844,6 @@ export function getBumpedLaneForHydration(
795844 case TransitionLane13:
796845 case TransitionLane14:
797846 case TransitionLane15:
798- case TransitionLane16:
799847 case RetryLane1:
800848 case RetryLane2:
801849 case RetryLane3:
0 commit comments