Skip to content

Commit a61fe06

Browse files
committed
Add feature flag to disable scheduler timeout in work loop
1 parent 99cae88 commit a61fe06

11 files changed

+40
-2
lines changed

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
enableSchedulingProfiler,
3131
enableScopeAPI,
3232
skipUnmountedBoundaries,
33+
disableSchedulerTimeoutInWorkLoop,
3334
} from 'shared/ReactFeatureFlags';
3435
import ReactSharedInternals from 'shared/ReactSharedInternals';
3536
import 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,19 @@ function performConcurrentWorkOnRoot(root) {
790791
return null;
791792
}
792793

794+
// TODO: We only check `didTimeout` defensively, to account for a Scheduler
795+
// bug where `shouldYield` sometimes returns `true` even if `didTimeout` is
796+
// true, which leads to an infinite loop. Once the bug in Scheduler is
797+
// fixed, we can remove this, since we track expiration ourselves.
798+
if (!disableSchedulerTimeoutInWorkLoop && didTimeout) {
799+
// Something expired. Flush synchronously until there's no expired
800+
// work left.
801+
markRootExpired(root, lanes);
802+
// This will schedule a synchronous callback.
803+
ensureRootIsScheduled(root, now());
804+
return null;
805+
}
806+
793807
let exitStatus = renderRootConcurrent(root, lanes);
794808

795809
if (

packages/react-reconciler/src/ReactFiberWorkLoop.old.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
enableSchedulingProfiler,
3131
enableScopeAPI,
3232
skipUnmountedBoundaries,
33+
disableSchedulerTimeoutInWorkLoop,
3334
} from 'shared/ReactFeatureFlags';
3435
import ReactSharedInternals from 'shared/ReactSharedInternals';
3536
import invariant from 'shared/invariant';
@@ -738,7 +739,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
738739

739740
// This is the entry point for every concurrent task, i.e. anything that
740741
// goes through Scheduler.
741-
function performConcurrentWorkOnRoot(root) {
742+
function performConcurrentWorkOnRoot(root, didTimeout) {
742743
// Since we know we're in a React event, we can clear the current
743744
// event time. The next update will compute a new event time.
744745
currentEventTime = NoTimestamp;
@@ -778,6 +779,19 @@ function performConcurrentWorkOnRoot(root) {
778779
return null;
779780
}
780781

782+
// TODO: We only check `didTimeout` defensively, to account for a Scheduler
783+
// bug where `shouldYield` sometimes returns `true` even if `didTimeout` is
784+
// true, which leads to an infinite loop. Once the bug in Scheduler is
785+
// fixed, we can remove this, since we track expiration ourselves.
786+
if (!disableSchedulerTimeoutInWorkLoop && didTimeout) {
787+
// Something expired. Flush synchronously until there's no expired
788+
// work left.
789+
markRootExpired(root, lanes);
790+
// This will schedule a synchronous callback.
791+
ensureRootIsScheduled(root, now());
792+
return null;
793+
}
794+
781795
let exitStatus = renderRootConcurrent(root, lanes);
782796

783797
if (

packages/shared/ReactFeatureFlags.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,5 @@ export const enablePassiveEventIntervention = true;
138138
export const disableOnScrollBubbling = true;
139139

140140
export const enableEagerRootListeners = true;
141+
142+
export const disableSchedulerTimeoutInWorkLoop = false;

packages/shared/forks/ReactFeatureFlags.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
5252
export const enableDiscreteEventFlushingChange = false;
5353
export const enablePassiveEventIntervention = true;
5454
export const enableEagerRootListeners = true;
55+
export const disableSchedulerTimeoutInWorkLoop = false;
5556

5657
// Flow magic to verify the exports of this file match the original version.
5758
// eslint-disable-next-line no-unused-vars

packages/shared/forks/ReactFeatureFlags.native-oss.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
5151
export const enableDiscreteEventFlushingChange = false;
5252
export const enablePassiveEventIntervention = true;
5353
export const enableEagerRootListeners = true;
54+
export const disableSchedulerTimeoutInWorkLoop = false;
5455

5556
// Flow magic to verify the exports of this file match the original version.
5657
// eslint-disable-next-line no-unused-vars

packages/shared/forks/ReactFeatureFlags.test-renderer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
5151
export const enableDiscreteEventFlushingChange = false;
5252
export const enablePassiveEventIntervention = true;
5353
export const enableEagerRootListeners = true;
54+
export const disableSchedulerTimeoutInWorkLoop = false;
5455

5556
// Flow magic to verify the exports of this file match the original version.
5657
// eslint-disable-next-line no-unused-vars

packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
5151
export const enableDiscreteEventFlushingChange = false;
5252
export const enablePassiveEventIntervention = true;
5353
export const enableEagerRootListeners = true;
54+
export const disableSchedulerTimeoutInWorkLoop = false;
5455

5556
// Flow magic to verify the exports of this file match the original version.
5657
// eslint-disable-next-line no-unused-vars

packages/shared/forks/ReactFeatureFlags.testing.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
5151
export const enableDiscreteEventFlushingChange = false;
5252
export const enablePassiveEventIntervention = true;
5353
export const enableEagerRootListeners = true;
54+
export const disableSchedulerTimeoutInWorkLoop = false;
5455

5556
// Flow magic to verify the exports of this file match the original version.
5657
// eslint-disable-next-line no-unused-vars

packages/shared/forks/ReactFeatureFlags.testing.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
5151
export const enableDiscreteEventFlushingChange = true;
5252
export const enablePassiveEventIntervention = true;
5353
export const enableEagerRootListeners = true;
54+
export const disableSchedulerTimeoutInWorkLoop = false;
5455

5556
// Flow magic to verify the exports of this file match the original version.
5657
// eslint-disable-next-line no-unused-vars

packages/shared/forks/ReactFeatureFlags.www-dynamic.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
4949
// to __VARIANT__.
5050
export const enableTrustedTypesIntegration = false;
5151
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
52+
export const disableSchedulerTimeoutInWorkLoop = __VARIANT__;

packages/shared/forks/ReactFeatureFlags.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export const {
3030
enablePassiveEventIntervention,
3131
disableOnScrollBubbling,
3232
enableEagerRootListeners,
33+
disableSchedulerTimeoutInWorkLoop,
3334
} = dynamicFeatureFlags;
3435

3536
// On WWW, __EXPERIMENTAL__ is used for a new modern build.

0 commit comments

Comments
 (0)