@@ -237,7 +237,6 @@ import {
237
237
markSkippedUpdateLanes ,
238
238
getWorkInProgressRoot ,
239
239
pushRenderLanes ,
240
- getWorkInProgressTransitions ,
241
240
} from './ReactFiberWorkLoop.old' ;
242
241
import { setWorkInProgressVersion } from './ReactMutableSource.old' ;
243
242
import { pushCacheProvider , CacheContext } from './ReactFiberCacheComponent.old' ;
@@ -257,6 +256,7 @@ import {
257
256
getSuspendedCache ,
258
257
pushTransition ,
259
258
getOffscreenDeferredCache ,
259
+ getSuspendedTransitions ,
260
260
} from './ReactFiberTransition.old' ;
261
261
262
262
const ReactCurrentOwner = ReactSharedInternals . ReactCurrentOwner ;
@@ -653,16 +653,18 @@ function updateOffscreenComponent(
653
653
// Rendering a hidden tree.
654
654
if ( ( workInProgress . mode & ConcurrentMode ) === NoMode ) {
655
655
// In legacy sync mode, don't defer the subtree. Render it now.
656
+ // TODO: Consider how Offscreen should work with transitions in the future
656
657
const nextState : OffscreenState = {
657
658
baseLanes : NoLanes ,
658
659
cachePool : null ,
660
+ transitions : null ,
659
661
} ;
660
662
workInProgress . memoizedState = nextState ;
661
663
if ( enableCache ) {
662
664
// push the cache pool even though we're going to bail out
663
665
// because otherwise there'd be a context mismatch
664
666
if ( current !== null ) {
665
- pushTransition ( workInProgress , null ) ;
667
+ pushTransition ( workInProgress , null , null ) ;
666
668
}
667
669
}
668
670
pushRenderLanes ( workInProgress , renderLanes ) ;
@@ -689,14 +691,15 @@ function updateOffscreenComponent(
689
691
const nextState : OffscreenState = {
690
692
baseLanes : nextBaseLanes ,
691
693
cachePool : spawnedCachePool ,
694
+ transitions : null ,
692
695
} ;
693
696
workInProgress . memoizedState = nextState ;
694
697
workInProgress . updateQueue = null ;
695
698
if ( enableCache ) {
696
699
// push the cache pool even though we're going to bail out
697
700
// because otherwise there'd be a context mismatch
698
701
if ( current !== null ) {
699
- pushTransition ( workInProgress , null ) ;
702
+ pushTransition ( workInProgress , null , null ) ;
700
703
}
701
704
}
702
705
@@ -724,6 +727,7 @@ function updateOffscreenComponent(
724
727
const nextState : OffscreenState = {
725
728
baseLanes : NoLanes ,
726
729
cachePool : null ,
730
+ transitions : null ,
727
731
} ;
728
732
workInProgress . memoizedState = nextState ;
729
733
// Push the lanes that were skipped when we bailed out.
@@ -734,7 +738,7 @@ function updateOffscreenComponent(
734
738
// using the same cache. Unless the parent changed, since that means
735
739
// there was a refresh.
736
740
const prevCachePool = prevState !== null ? prevState . cachePool : null ;
737
- pushTransition ( workInProgress , prevCachePool ) ;
741
+ pushTransition ( workInProgress , prevCachePool , null ) ;
738
742
}
739
743
740
744
pushRenderLanes ( workInProgress , subtreeRenderLanes ) ;
@@ -747,14 +751,21 @@ function updateOffscreenComponent(
747
751
748
752
subtreeRenderLanes = mergeLanes ( prevState . baseLanes , renderLanes ) ;
749
753
754
+ let prevCachePool = null ;
750
755
if ( enableCache ) {
751
756
// If the render that spawned this one accessed the cache pool, resume
752
757
// using the same cache. Unless the parent changed, since that means
753
758
// there was a refresh.
754
- const prevCachePool = prevState . cachePool ;
755
- pushTransition ( workInProgress , prevCachePool ) ;
759
+ prevCachePool = prevState . cachePool ;
756
760
}
757
761
762
+ let transitions = null ;
763
+ if ( enableTransitionTracing ) {
764
+ transitions = prevState . transitions ;
765
+ }
766
+
767
+ pushTransition ( workInProgress , prevCachePool , transitions ) ;
768
+
758
769
// Since we're not hidden anymore, reset the state
759
770
workInProgress . memoizedState = null ;
760
771
} else {
@@ -768,7 +779,7 @@ function updateOffscreenComponent(
768
779
// using the same cache. Unless the parent changed, since that means
769
780
// there was a refresh.
770
781
if ( current !== null ) {
771
- pushTransition ( workInProgress , null ) ;
782
+ pushTransition ( workInProgress , null , null ) ;
772
783
}
773
784
}
774
785
}
@@ -1326,28 +1337,25 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1326
1337
const nextProps = workInProgress . pendingProps ;
1327
1338
const prevState = workInProgress . memoizedState ;
1328
1339
const prevChildren = prevState . element ;
1340
+
1329
1341
cloneUpdateQueue ( current , workInProgress ) ;
1330
1342
processUpdateQueue ( workInProgress , nextProps , null , renderLanes ) ;
1331
1343
1332
1344
const nextState : RootState = workInProgress . memoizedState ;
1333
1345
const root : FiberRoot = workInProgress . stateNode ;
1334
1346
1347
+ pushRootTransition ( workInProgress , root , renderLanes ) ;
1348
+
1335
1349
if ( enableCache ) {
1336
- const nextCache : Cache = nextState . cache ;
1337
- pushRootTransition ( root ) ;
1350
+ const nextCache : Cache = workInProgress . memoizedState . cache ;
1338
1351
pushCacheProvider ( workInProgress , nextCache ) ;
1339
1352
if ( nextCache !== prevState . cache ) {
1340
1353
// The root cache refreshed.
1341
1354
propagateContextChange ( workInProgress , CacheContext , renderLanes ) ;
1342
1355
}
1343
1356
}
1344
1357
1345
- if ( enableTransitionTracing ) {
1346
- // FIXME: Slipped past code review. This is not a safe mutation:
1347
- // workInProgress.memoizedState is a shared object. Need to fix before
1348
- // rolling out the Transition Tracing experiment.
1349
- workInProgress . memoizedState . transitions = getWorkInProgressTransitions ( ) ;
1350
- }
1358
+ const pendingSuspenseBoundaries = nextState . pendingSuspenseBoundaries || null ;
1351
1359
1352
1360
// Caution: React DevTools currently depends on this property
1353
1361
// being called "element".
@@ -1362,6 +1370,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1362
1370
element : nextChildren ,
1363
1371
isDehydrated : false ,
1364
1372
cache : nextState . cache ,
1373
+ pendingSuspenseBoundaries,
1365
1374
transitions : nextState . transitions ,
1366
1375
} ;
1367
1376
const updateQueue : UpdateQueue < RootState > = (workInProgress.updateQueue: any);
@@ -1435,6 +1444,20 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1435
1444
}
1436
1445
}
1437
1446
} else {
1447
+ if ( enableTransitionTracing ) {
1448
+ if ( pendingSuspenseBoundaries !== nextState . pendingSuspenseBoundaries ) {
1449
+ const overrideState : RootState = {
1450
+ element : nextChildren ,
1451
+ isDehydrated : nextState . isDehydrated ,
1452
+ cache : nextState . cache ,
1453
+ pendingSuspenseBoundaries,
1454
+ transitions : nextState . transitions ,
1455
+ } ;
1456
+
1457
+ workInProgress . memoizedState = overrideState ;
1458
+ }
1459
+ }
1460
+
1438
1461
// Root is not dehydrated. Either this is a client-only root, or it
1439
1462
// already hydrated.
1440
1463
resetHydrationState ( ) ;
@@ -1979,6 +2002,7 @@ function mountSuspenseOffscreenState(renderLanes: Lanes): OffscreenState {
1979
2002
return {
1980
2003
baseLanes : renderLanes ,
1981
2004
cachePool : getSuspendedCache ( ) ,
2005
+ transitions : getSuspendedTransitions ( ) ,
1982
2006
} ;
1983
2007
}
1984
2008
@@ -2010,9 +2034,11 @@ function updateSuspenseOffscreenState(
2010
2034
cachePool = getSuspendedCache ( ) ;
2011
2035
}
2012
2036
}
2037
+
2013
2038
return {
2014
2039
baseLanes : mergeLanes ( prevOffscreenState . baseLanes , renderLanes ) ,
2015
2040
cachePool,
2041
+ transitions : prevOffscreenState . transitions ,
2016
2042
} ;
2017
2043
}
2018
2044
@@ -2103,6 +2129,8 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2103
2129
2104
2130
pushSuspenseContext ( workInProgress , suspenseContext ) ;
2105
2131
2132
+ const root = getWorkInProgressRoot ( ) ;
2133
+
2106
2134
// OK, the next part is confusing. We're about to reconcile the Suspense
2107
2135
// boundary's children. This involves some custom reconciliation logic. Two
2108
2136
// main reasons this is so complicated.
@@ -2143,7 +2171,6 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2143
2171
}
2144
2172
}
2145
2173
}
2146
-
2147
2174
const nextPrimaryChildren = nextProps . children ;
2148
2175
const nextFallbackChildren = nextProps . fallback ;
2149
2176
@@ -2159,6 +2186,18 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2159
2186
renderLanes ,
2160
2187
) ;
2161
2188
workInProgress . memoizedState = SUSPENDED_MARKER ;
2189
+ if ( enableTransitionTracing ) {
2190
+ const currentTransitions = getSuspendedTransitions ( ) ;
2191
+ if ( currentTransitions !== null ) {
2192
+ const primaryChildUpdateQueue : OffscreenQueue = {
2193
+ transitions : currentTransitions ,
2194
+ rootMemoizedState :
2195
+ root === null ? null : root . current . memoizedState ,
2196
+ } ;
2197
+ primaryChildFragment . updateQueue = primaryChildUpdateQueue ;
2198
+ }
2199
+ }
2200
+
2162
2201
return fallbackFragment ;
2163
2202
} else if (
2164
2203
enableCPUSuspense &&
@@ -2285,6 +2324,8 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2285
2324
if ( currentTransitions !== null ) {
2286
2325
const primaryChildUpdateQueue : OffscreenQueue = {
2287
2326
transitions : currentTransitions ,
2327
+ rootMemoizedState :
2328
+ root === null ? null : root . current . memoizedState ,
2288
2329
} ;
2289
2330
primaryChildFragment . updateQueue = primaryChildUpdateQueue ;
2290
2331
}
@@ -2336,6 +2377,8 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
2336
2377
if ( currentTransitions !== null ) {
2337
2378
const primaryChildUpdateQueue : OffscreenQueue = {
2338
2379
transitions : currentTransitions ,
2380
+ rootMemoizedState :
2381
+ root === null ? null : root . current . memoizedState ,
2339
2382
} ;
2340
2383
primaryChildFragment . updateQueue = primaryChildUpdateQueue ;
2341
2384
}
@@ -2368,6 +2411,7 @@ function mountSuspensePrimaryChildren(
2368
2411
renderLanes ,
2369
2412
) {
2370
2413
const mode = workInProgress . mode ;
2414
+
2371
2415
const primaryChildProps : OffscreenProps = {
2372
2416
mode : 'visible' ,
2373
2417
children : primaryChildren ,
@@ -2390,7 +2434,6 @@ function mountSuspenseFallbackChildren(
2390
2434
) {
2391
2435
const mode = workInProgress . mode ;
2392
2436
const progressedPrimaryFragment : Fiber | null = workInProgress . child ;
2393
-
2394
2437
const primaryChildProps : OffscreenProps = {
2395
2438
mode : 'hidden' ,
2396
2439
children : primaryChildren ,
@@ -3594,14 +3637,13 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
3594
3637
case HostRoot :
3595
3638
pushHostRootContext ( workInProgress ) ;
3596
3639
const root : FiberRoot = workInProgress . stateNode ;
3640
+ pushRootTransition ( workInProgress , root , renderLanes ) ;
3641
+
3597
3642
if ( enableCache ) {
3598
3643
const cache : Cache = current . memoizedState . cache ;
3599
3644
pushCacheProvider ( workInProgress , cache ) ;
3600
- pushRootTransition ( root ) ;
3601
- }
3602
- if ( enableTransitionTracing ) {
3603
- workInProgress . memoizedState . transitions = getWorkInProgressTransitions ( ) ;
3604
3645
}
3646
+
3605
3647
resetHydrationState ( ) ;
3606
3648
break ;
3607
3649
case HostComponent :
0 commit comments