@@ -647,21 +647,10 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
647647 // Check if the render expired.
648648 const expirationTime = getNextRootExpirationTimeToWorkOn ( root ) ;
649649 if ( didTimeout ) {
650- if (
651- root === workInProgressRoot &&
652- expirationTime === renderExpirationTime
653- ) {
654- // We're already in the middle of working on this tree. Expire the tree at
655- // the already-rendering time so we don't throw out the partial work. If
656- // there's another expired level after that, we'll hit the `else` branch
657- // of this condition, which will batch together the remaining levels.
658- markRootExpiredAtTime ( root , renderExpirationTime ) ;
659- } else {
660- // This is a new tree. Expire the tree at the current time so that we
661- // render all the expired work in a single batch.
662- const currentTime = requestCurrentTimeForUpdate ( ) ;
663- markRootExpiredAtTime ( root , currentTime ) ;
664- }
650+ // The render task took too long to complete. Mark the current time as
651+ // expired to synchronously render all expired work in a single batch.
652+ const currentTime = requestCurrentTimeForUpdate ( ) ;
653+ markRootExpiredAtTime ( root , currentTime ) ;
665654 // This will schedule a synchronous callback.
666655 ensureRootIsScheduled ( root ) ;
667656 return null ;
@@ -997,19 +986,36 @@ function finishConcurrentRender(
997986// This is the entry point for synchronous tasks that don't go
998987// through Scheduler
999988function performSyncWorkOnRoot ( root ) {
1000- // Check if there's expired work on this root. Otherwise, render at Sync.
1001- const lastExpiredTime = root . lastExpiredTime ;
1002- const expirationTime = lastExpiredTime !== NoWork ? lastExpiredTime : Sync ;
1003989 invariant (
1004990 ( executionContext & ( RenderContext | CommitContext ) ) === NoContext ,
1005991 'Should not already be working.' ,
1006992 ) ;
1007993
1008994 flushPassiveEffects ( ) ;
1009995
1010- // If the root or expiration time have changed, throw out the existing stack
1011- // and prepare a fresh one. Otherwise we'll continue where we left off.
1012- if ( root !== workInProgressRoot || expirationTime !== renderExpirationTime ) {
996+ const lastExpiredTime = root . lastExpiredTime ;
997+
998+ let expirationTime ;
999+ if ( lastExpiredTime !== NoWork ) {
1000+ // There's expired work on this root. Check if we have a partial tree
1001+ // that we can reuse.
1002+ if (
1003+ root === workInProgressRoot &&
1004+ renderExpirationTime >= lastExpiredTime
1005+ ) {
1006+ // There's a partial tree with equal or greater than priority than the
1007+ // expired level. Finish rendering it before rendering the rest of the
1008+ // expired work.
1009+ expirationTime = renderExpirationTime ;
1010+ } else {
1011+ // Start a fresh tree.
1012+ expirationTime = lastExpiredTime ;
1013+ prepareFreshStack ( root , expirationTime ) ;
1014+ startWorkOnPendingInteractions ( root , expirationTime ) ;
1015+ }
1016+ } else {
1017+ // There's no expired work. This must be a new, synchronous render.
1018+ expirationTime = Sync ;
10131019 prepareFreshStack ( root , expirationTime ) ;
10141020 startWorkOnPendingInteractions ( root , expirationTime ) ;
10151021 }
@@ -1060,7 +1066,7 @@ function performSyncWorkOnRoot(root) {
10601066 stopFinishedWorkLoopTimer ( ) ;
10611067 root . finishedWork = ( root . current . alternate : any ) ;
10621068 root . finishedExpirationTime = expirationTime ;
1063- finishSyncRender ( root , workInProgressRootExitStatus ) ;
1069+ finishSyncRender ( root ) ;
10641070 }
10651071
10661072 // Before exiting, make sure there's a callback scheduled for the next
0 commit comments