@@ -236,7 +236,7 @@ import {
236
236
markSkippedUpdateLanes ,
237
237
getWorkInProgressRoot ,
238
238
pushRenderLanes ,
239
- getWorkInProgressTransitions ,
239
+ setRootPendingSuspenseBoundaries ,
240
240
} from './ReactFiberWorkLoop.old' ;
241
241
import { setWorkInProgressVersion } from './ReactMutableSource.old' ;
242
242
import { pushCacheProvider , CacheContext } from './ReactFiberCacheComponent.old' ;
@@ -256,6 +256,7 @@ import {
256
256
getSuspendedCache ,
257
257
pushTransition ,
258
258
getOffscreenDeferredCache ,
259
+ getSuspendedTransitions ,
259
260
} from './ReactFiberTransition.old' ;
260
261
261
262
const ReactCurrentOwner = ReactSharedInternals . ReactCurrentOwner ;
@@ -655,13 +656,14 @@ function updateOffscreenComponent(
655
656
const nextState : OffscreenState = {
656
657
baseLanes : NoLanes ,
657
658
cachePool : null ,
659
+ transitions : null ,
658
660
} ;
659
661
workInProgress . memoizedState = nextState ;
660
662
if ( enableCache ) {
661
663
// push the cache pool even though we're going to bail out
662
664
// because otherwise there'd be a context mismatch
663
665
if ( current !== null ) {
664
- pushTransition ( workInProgress , null ) ;
666
+ pushTransition ( workInProgress , null , null ) ;
665
667
}
666
668
}
667
669
pushRenderLanes ( workInProgress , renderLanes ) ;
@@ -688,14 +690,15 @@ function updateOffscreenComponent(
688
690
const nextState : OffscreenState = {
689
691
baseLanes : nextBaseLanes ,
690
692
cachePool : spawnedCachePool ,
693
+ transitions : null ,
691
694
} ;
692
695
workInProgress . memoizedState = nextState ;
693
696
workInProgress . updateQueue = null ;
694
697
if ( enableCache ) {
695
698
// push the cache pool even though we're going to bail out
696
699
// because otherwise there'd be a context mismatch
697
700
if ( current !== null ) {
698
- pushTransition ( workInProgress , null ) ;
701
+ pushTransition ( workInProgress , null , null ) ;
699
702
}
700
703
}
701
704
@@ -723,6 +726,7 @@ function updateOffscreenComponent(
723
726
const nextState : OffscreenState = {
724
727
baseLanes : NoLanes ,
725
728
cachePool : null ,
729
+ transitions : null ,
726
730
} ;
727
731
workInProgress . memoizedState = nextState ;
728
732
// Push the lanes that were skipped when we bailed out.
@@ -733,7 +737,7 @@ function updateOffscreenComponent(
733
737
// using the same cache. Unless the parent changed, since that means
734
738
// there was a refresh.
735
739
const prevCachePool = prevState !== null ? prevState . cachePool : null ;
736
- pushTransition ( workInProgress , prevCachePool ) ;
740
+ pushTransition ( workInProgress , prevCachePool , null ) ;
737
741
}
738
742
739
743
pushRenderLanes ( workInProgress , subtreeRenderLanes ) ;
@@ -746,14 +750,14 @@ function updateOffscreenComponent(
746
750
747
751
subtreeRenderLanes = mergeLanes ( prevState . baseLanes , renderLanes ) ;
748
752
749
- if ( enableCache ) {
753
+ if ( enableCache || enableTransitionTracing ) {
750
754
// If the render that spawned this one accessed the cache pool, resume
751
755
// using the same cache. Unless the parent changed, since that means
752
756
// there was a refresh.
753
757
const prevCachePool = prevState . cachePool ;
754
- pushTransition ( workInProgress , prevCachePool ) ;
758
+ const transitions = prevState . transitions ;
759
+ pushTransition ( workInProgress , prevCachePool , transitions ) ;
755
760
}
756
-
757
761
// Since we're not hidden anymore, reset the state
758
762
workInProgress . memoizedState = null ;
759
763
} else {
@@ -767,7 +771,7 @@ function updateOffscreenComponent(
767
771
// using the same cache. Unless the parent changed, since that means
768
772
// there was a refresh.
769
773
if ( current !== null ) {
770
- pushTransition ( workInProgress , null ) ;
774
+ pushTransition ( workInProgress , null , null ) ;
771
775
}
772
776
}
773
777
}
@@ -1325,29 +1329,57 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1325
1329
const nextProps = workInProgress . pendingProps ;
1326
1330
const prevState = workInProgress . memoizedState ;
1327
1331
const prevChildren = prevState . element ;
1332
+
1328
1333
cloneUpdateQueue ( current , workInProgress ) ;
1329
1334
processUpdateQueue ( workInProgress , nextProps , null , renderLanes ) ;
1330
-
1331
- const nextState : RootState = workInProgress . memoizedState ;
1332
1335
const root : FiberRoot = workInProgress . stateNode ;
1333
1336
1337
+ if ( enableCache || enableTransitionTracing ) {
1338
+ pushRootTransition ( workInProgress , root , renderLanes ) ;
1339
+ }
1340
+
1334
1341
if ( enableCache ) {
1335
- const nextCache : Cache = nextState . cache ;
1336
- pushRootTransition ( root ) ;
1342
+ const nextCache : Cache = workInProgress . memoizedState . cache ;
1337
1343
pushCacheProvider ( workInProgress , nextCache ) ;
1338
1344
if ( nextCache !== prevState . cache ) {
1339
1345
// The root cache refreshed.
1340
1346
propagateContextChange ( workInProgress , CacheContext , renderLanes ) ;
1341
1347
}
1342
1348
}
1343
1349
1350
+ let transitions = null ;
1351
+ let pendingSuspenseBoundaries = null ;
1344
1352
if ( enableTransitionTracing ) {
1345
- // FIXME: Slipped past code review. This is not a safe mutation:
1346
- // workInProgress.memoizedState is a shared object. Need to fix before
1347
- // rolling out the Transition Tracing experiment.
1348
- workInProgress . memoizedState . transitions = getWorkInProgressTransitions ( ) ;
1353
+ const currentTransitions = getSuspendedTransitions ( ) ;
1354
+ const prevTransitions = prevState . transitions ;
1355
+
1356
+ if ( currentTransitions !== null ) {
1357
+ if ( prevTransitions === null ) {
1358
+ transitions = currentTransitions ;
1359
+ } else {
1360
+ transitions = prevTransitions . concat ( currentTransitions ) ;
1361
+ }
1362
+ } else {
1363
+ transitions = prevTransitions ;
1364
+ }
1365
+
1366
+ if ( prevState . pendingSuspenseBoundaries === null ) {
1367
+ pendingSuspenseBoundaries = new Map ( ) ;
1368
+ } else {
1369
+ pendingSuspenseBoundaries = new Map ( prevState . pendingSuspenseBoundaries ) ;
1370
+ }
1371
+ setRootPendingSuspenseBoundaries ( pendingSuspenseBoundaries ) ;
1349
1372
}
1350
1373
1374
+ const nextState : RootState = {
1375
+ element : workInProgress . memoizedState . element ,
1376
+ cache : workInProgress . memoizedState . cache ,
1377
+ isDehydrated : workInProgress . memoizedState . isDehydrated ,
1378
+ pendingSuspenseBoundaries,
1379
+ transitions,
1380
+ } ;
1381
+ workInProgress . memoizedState = nextState ;
1382
+
1351
1383
// Caution: React DevTools currently depends on this property
1352
1384
// being called "element".
1353
1385
const nextChildren = nextState . element ;
@@ -1361,6 +1393,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1361
1393
element : nextChildren ,
1362
1394
isDehydrated : false ,
1363
1395
cache : nextState . cache ,
1396
+ pendingSuspenseBoundaries : nextState . pendingSuspenseBoundaries ,
1364
1397
transitions : nextState . transitions ,
1365
1398
} ;
1366
1399
const updateQueue : UpdateQueue < RootState > = (workInProgress.updateQueue: any);
@@ -1978,6 +2011,7 @@ function mountSuspenseOffscreenState(renderLanes: Lanes): OffscreenState {
1978
2011
return {
1979
2012
baseLanes : renderLanes ,
1980
2013
cachePool : getSuspendedCache ( ) ,
2014
+ transitions : getSuspendedTransitions ( ) ,
1981
2015
} ;
1982
2016
}
1983
2017
@@ -2009,9 +2043,22 @@ function updateSuspenseOffscreenState(
2009
2043
cachePool = getSuspendedCache ( ) ;
2010
2044
}
2011
2045
}
2046
+
2047
+ let transitions = null ;
2048
+ if ( enableTransitionTracing ) {
2049
+ const currentTransitions = getSuspendedTransitions ( ) ;
2050
+ const prevTransitions = prevOffscreenState . transitions ;
2051
+ if ( prevTransitions !== null ) {
2052
+ transitions = prevTransitions . concat ( currentTransitions ) ;
2053
+ } else {
2054
+ transitions = currentTransitions ;
2055
+ }
2056
+ }
2057
+
2012
2058
return {
2013
2059
baseLanes : mergeLanes ( prevOffscreenState . baseLanes , renderLanes ) ,
2014
2060
cachePool,
2061
+ transitions,
2015
2062
} ;
2016
2063
}
2017
2064
@@ -2345,9 +2392,16 @@ function mountSuspensePrimaryChildren(
2345
2392
renderLanes ,
2346
2393
) {
2347
2394
const mode = workInProgress . mode ;
2395
+ const props = workInProgress . memoizedProps ;
2396
+ let name = null ;
2397
+ if ( props !== null ) {
2398
+ name = props . name ;
2399
+ }
2400
+
2348
2401
const primaryChildProps : OffscreenProps = {
2349
2402
mode : 'visible' ,
2350
2403
children : primaryChildren ,
2404
+ name,
2351
2405
} ;
2352
2406
const primaryChildFragment = mountWorkInProgressOffscreenFiber (
2353
2407
primaryChildProps ,
@@ -2367,10 +2421,15 @@ function mountSuspenseFallbackChildren(
2367
2421
) {
2368
2422
const mode = workInProgress . mode ;
2369
2423
const progressedPrimaryFragment : Fiber | null = workInProgress . child ;
2370
-
2424
+ const props = workInProgress . memoizedProps ;
2425
+ let name = null ;
2426
+ if ( props !== null ) {
2427
+ name = props . name ;
2428
+ }
2371
2429
const primaryChildProps : OffscreenProps = {
2372
2430
mode : 'hidden' ,
2373
2431
children : primaryChildren ,
2432
+ name,
2374
2433
} ;
2375
2434
2376
2435
let primaryChildFragment ;
@@ -2448,6 +2507,7 @@ function updateSuspensePrimaryChildren(
2448
2507
primaryChildren ,
2449
2508
renderLanes ,
2450
2509
) {
2510
+ const name = workInProgress . pendingProps . name ;
2451
2511
const currentPrimaryChildFragment : Fiber = ( current . child : any ) ;
2452
2512
const currentFallbackChildFragment : Fiber | null =
2453
2513
currentPrimaryChildFragment . sibling ;
@@ -2457,6 +2517,7 @@ function updateSuspensePrimaryChildren(
2457
2517
{
2458
2518
mode : 'visible' ,
2459
2519
children : primaryChildren ,
2520
+ name,
2460
2521
} ,
2461
2522
) ;
2462
2523
if ( ( workInProgress . mode & ConcurrentMode ) === NoMode ) {
@@ -2486,6 +2547,7 @@ function updateSuspenseFallbackChildren(
2486
2547
fallbackChildren ,
2487
2548
renderLanes ,
2488
2549
) {
2550
+ const name = workInProgress . pendingProps . name ;
2489
2551
const mode = workInProgress . mode ;
2490
2552
const currentPrimaryChildFragment : Fiber = ( current . child : any ) ;
2491
2553
const currentFallbackChildFragment : Fiber | null =
@@ -2494,6 +2556,7 @@ function updateSuspenseFallbackChildren(
2494
2556
const primaryChildProps : OffscreenProps = {
2495
2557
mode : 'hidden' ,
2496
2558
children : primaryChildren ,
2559
+ name,
2497
2560
} ;
2498
2561
2499
2562
let primaryChildFragment ;
@@ -2652,10 +2715,12 @@ function mountSuspenseFallbackAfterRetryWithoutHydrating(
2652
2715
fallbackChildren ,
2653
2716
renderLanes ,
2654
2717
) {
2718
+ const name = workInProgress . pendingProps . name ;
2655
2719
const fiberMode = workInProgress . mode ;
2656
2720
const primaryChildProps : OffscreenProps = {
2657
2721
mode : 'visible' ,
2658
2722
children : primaryChildren ,
2723
+ name,
2659
2724
} ;
2660
2725
const primaryChildFragment = mountWorkInProgressOffscreenFiber (
2661
2726
primaryChildProps ,
@@ -3571,14 +3636,50 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3571
3636
case HostRoot :
3572
3637
pushHostRootContext ( workInProgress ) ;
3573
3638
const root : FiberRoot = workInProgress . stateNode ;
3639
+ if ( enableCache || enableTransitionTracing ) {
3640
+ pushRootTransition ( workInProgress , root , renderLanes ) ;
3641
+ }
3642
+
3574
3643
if ( enableCache ) {
3575
3644
const cache : Cache = current . memoizedState . cache ;
3576
3645
pushCacheProvider ( workInProgress , cache ) ;
3577
- pushRootTransition ( root ) ;
3578
3646
}
3647
+
3648
+ let transitions = null ;
3649
+ let pendingSuspenseBoundaries = null ;
3579
3650
if ( enableTransitionTracing ) {
3580
- workInProgress . memoizedState . transitions = getWorkInProgressTransitions ( ) ;
3651
+ const prevState = current . memoizedState ;
3652
+
3653
+ const currentTransitions = getSuspendedTransitions ( ) ;
3654
+ const prevTransitions = prevState . transitions ;
3655
+ if ( currentTransitions !== null ) {
3656
+ if ( prevTransitions === null ) {
3657
+ transitions = currentTransitions ;
3658
+ } else {
3659
+ transitions = prevTransitions . concat ( currentTransitions ) ;
3660
+ }
3661
+ } else {
3662
+ transitions = prevTransitions ;
3663
+ }
3664
+
3665
+ if ( prevState . pendingSuspenseBoundaries === null ) {
3666
+ pendingSuspenseBoundaries = new Map ( ) ;
3667
+ } else {
3668
+ pendingSuspenseBoundaries = new Map (
3669
+ prevState . pendingSuspenseBoundaries ,
3670
+ ) ;
3671
+ }
3672
+ setRootPendingSuspenseBoundaries ( pendingSuspenseBoundaries ) ;
3581
3673
}
3674
+
3675
+ const nextState : RootState = {
3676
+ element : workInProgress . memoizedState . element ,
3677
+ cache : workInProgress . memoizedState . cache ,
3678
+ isDehydrated : workInProgress . memoizedState . isDehydrated ,
3679
+ pendingSuspenseBoundaries,
3680
+ transitions,
3681
+ } ;
3682
+ workInProgress . memoizedState = nextState ;
3582
3683
resetHydrationState ( ) ;
3583
3684
break ;
3584
3685
case HostComponent :
0 commit comments