@@ -33,6 +33,7 @@ import {
3333 enableSchedulingProfiler ,
3434 enableScopeAPI ,
3535 enableDoubleInvokingEffects ,
36+ disableSchedulerTimeoutInWorkLoop ,
3637} from 'shared/ReactFeatureFlags' ;
3738import ReactSharedInternals from 'shared/ReactSharedInternals' ;
3839import invariant from 'shared/invariant' ;
@@ -775,7 +776,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
775776
776777// This is the entry point for every concurrent task, i.e. anything that
777778// goes through Scheduler.
778- function performConcurrentWorkOnRoot ( root ) {
779+ function performConcurrentWorkOnRoot ( root , didTimeout ) {
779780 if ( enableProfilerTimer && enableProfilerNestedUpdatePhase ) {
780781 resetNestedUpdateFlag ( ) ;
781782 }
@@ -819,6 +820,18 @@ function performConcurrentWorkOnRoot(root) {
819820 return null ;
820821 }
821822
823+ // TODO: We only check `didTimeout` defensively, to account for a Scheduler
824+ // bug we're still investigating. Once the bug in Scheduler is fixed,
825+ // we can remove this, since we track expiration ourselves.
826+ if ( ! disableSchedulerTimeoutInWorkLoop && didTimeout ) {
827+ // Something expired. Flush synchronously until there's no expired
828+ // work left.
829+ markRootExpired ( root , lanes ) ;
830+ // This will schedule a synchronous callback.
831+ ensureRootIsScheduled ( root , now ( ) ) ;
832+ return null ;
833+ }
834+
822835 let exitStatus = renderRootConcurrent ( root , lanes ) ;
823836
824837 if (
0 commit comments