@@ -649,21 +649,10 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
649649 // Check if the render expired.
650650 const expirationTime = getNextRootExpirationTimeToWorkOn ( root ) ;
651651 if ( didTimeout ) {
652- if (
653- root === workInProgressRoot &&
654- expirationTime === renderExpirationTime
655- ) {
656- // We're already in the middle of working on this tree. Expire the tree at
657- // the already-rendering time so we don't throw out the partial work. If
658- // there's another expired level after that, we'll hit the `else` branch
659- // of this condition, which will batch together the remaining levels.
660- markRootExpiredAtTime ( root , renderExpirationTime ) ;
661- } else {
662- // This is a new tree. Expire the tree at the current time so that we
663- // render all the expired work in a single batch.
664- const currentTime = requestCurrentTimeForUpdate ( ) ;
665- markRootExpiredAtTime ( root , currentTime ) ;
666- }
652+ // The render task took too long to complete. Mark the current time as
653+ // expired to synchronously render all expired work in a single batch.
654+ const currentTime = requestCurrentTimeForUpdate ( ) ;
655+ markRootExpiredAtTime ( root , currentTime ) ;
667656 // This will schedule a synchronous callback.
668657 ensureRootIsScheduled ( root ) ;
669658 return null ;
@@ -999,19 +988,36 @@ function finishConcurrentRender(
999988// This is the entry point for synchronous tasks that don't go
1000989// through Scheduler
1001990function performSyncWorkOnRoot ( root ) {
1002- // Check if there's expired work on this root. Otherwise, render at Sync.
1003- const lastExpiredTime = root . lastExpiredTime ;
1004- const expirationTime = lastExpiredTime !== NoWork ? lastExpiredTime : Sync ;
1005991 invariant (
1006992 ( executionContext & ( RenderContext | CommitContext ) ) === NoContext ,
1007993 'Should not already be working.' ,
1008994 ) ;
1009995
1010996 flushPassiveEffects ( ) ;
1011997
1012- // If the root or expiration time have changed, throw out the existing stack
1013- // and prepare a fresh one. Otherwise we'll continue where we left off.
1014- if ( root !== workInProgressRoot || expirationTime !== renderExpirationTime ) {
998+ const lastExpiredTime = root . lastExpiredTime ;
999+
1000+ let expirationTime ;
1001+ if ( lastExpiredTime !== NoWork ) {
1002+ // There's expired work on this root. Check if we have a partial tree
1003+ // that we can reuse.
1004+ if (
1005+ root === workInProgressRoot &&
1006+ renderExpirationTime >= lastExpiredTime
1007+ ) {
1008+ // There's a partial tree with equal or greater than priority than the
1009+ // expired level. Finish rendering it before rendering the rest of the
1010+ // expired work.
1011+ expirationTime = renderExpirationTime ;
1012+ } else {
1013+ // Start a fresh tree.
1014+ expirationTime = lastExpiredTime ;
1015+ prepareFreshStack ( root , expirationTime ) ;
1016+ startWorkOnPendingInteractions ( root , expirationTime ) ;
1017+ }
1018+ } else {
1019+ // There's no expired work. This must be a new, synchronous render.
1020+ expirationTime = Sync ;
10151021 prepareFreshStack ( root , expirationTime ) ;
10161022 startWorkOnPendingInteractions ( root , expirationTime ) ;
10171023 }
0 commit comments