@@ -30,6 +30,7 @@ import {
3030 enableSchedulingProfiler ,
3131 enableScopeAPI ,
3232 skipUnmountedBoundaries ,
33+ disableSchedulerTimeoutInWorkLoop ,
3334} from 'shared/ReactFeatureFlags' ;
3435import ReactSharedInternals from 'shared/ReactSharedInternals' ;
3536import invariant from 'shared/invariant' ;
@@ -750,7 +751,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
750751
751752// This is the entry point for every concurrent task, i.e. anything that
752753// goes through Scheduler.
753- function performConcurrentWorkOnRoot ( root ) {
754+ function performConcurrentWorkOnRoot ( root , didTimeout ) {
754755 // Since we know we're in a React event, we can clear the current
755756 // event time. The next update will compute a new event time.
756757 currentEventTime = NoTimestamp ;
@@ -790,6 +791,18 @@ function performConcurrentWorkOnRoot(root) {
790791 return null ;
791792 }
792793
794+ // TODO: We only check `didTimeout` defensively, to account for a Scheduler
795+ // bug we're still investigating. Once the bug in Scheduler is fixed,
796+ // we can remove this, since we track expiration ourselves.
797+ if (!disableSchedulerTimeoutInWorkLoop && didTimeout ) {
798+ // Something expired. Flush synchronously until there's no expired
799+ // work left.
800+ markRootExpired ( root , lanes ) ;
801+ // This will schedule a synchronous callback.
802+ ensureRootIsScheduled ( root , now ( ) ) ;
803+ return null ;
804+ }
805+
793806 let exitStatus = renderRootConcurrent(root, lanes);
794807
795808 if (
0 commit comments