Add feature flag to disable scheduler timeout in work loop (#19771)
Ricky committed
Sep 4, 2020 at 10:58 UTC
36df483af4a626fd4021c060fcb0f62471e82af1
12 files changed
+39
-2
packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+14
-1
@@ -30,6 +30,7 @@ import {
30
enableSchedulingProfiler,
31
enableScopeAPI,
32
skipUnmountedBoundaries,
33
+ disableSchedulerTimeoutInWorkLoop,
34
} from 'shared/ReactFeatureFlags';
35
import ReactSharedInternals from 'shared/ReactSharedInternals';
36
import invariant from 'shared/invariant';
@@ -750,7 +751,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
751
752
// This is the entry point for every concurrent task, i.e. anything that
753
// goes through Scheduler.
753
-function performConcurrentWorkOnRoot(root) {
754
+function performConcurrentWorkOnRoot(root, didTimeout) {
755
// Since we know we're in a React event, we can clear the current
756
// event time. The next update will compute a new event time.
757
currentEventTime = NoTimestamp;
@@ -790,6 +791,18 @@ function performConcurrentWorkOnRoot(root) {
791
return null;
792
}
793
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
+
806
let exitStatus = renderRootConcurrent(root, lanes);
807
808
if (
packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+14
-1
@@ -30,6 +30,7 @@ import {
30
enableSchedulingProfiler,
31
enableScopeAPI,
32
skipUnmountedBoundaries,
33
+ disableSchedulerTimeoutInWorkLoop,
34
} from 'shared/ReactFeatureFlags';
35
import ReactSharedInternals from 'shared/ReactSharedInternals';
36
import invariant from 'shared/invariant';
@@ -738,7 +739,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
739
740
// This is the entry point for every concurrent task, i.e. anything that
741
// goes through Scheduler.
741
-function performConcurrentWorkOnRoot(root) {
742
+function performConcurrentWorkOnRoot(root, didTimeout) {
743
// Since we know we're in a React event, we can clear the current
744
// event time. The next update will compute a new event time.
745
currentEventTime = NoTimestamp;
@@ -778,6 +779,18 @@ function performConcurrentWorkOnRoot(root) {
779
return null;
780
}
781
782
+ // TODO: We only check `didTimeout` defensively, to account for a Scheduler
783
+ // bug we're still investigating. Once the bug in Scheduler is fixed,
784
+ // we can remove this, since we track expiration ourselves.
785
+ if (!disableSchedulerTimeoutInWorkLoop && didTimeout) {
786
+ // Something expired. Flush synchronously until there's no expired
787
+ // work left.
788
+ markRootExpired(root, lanes);
789
+ // This will schedule a synchronous callback.
790
+ ensureRootIsScheduled(root, now());
791
+ return null;
792
+ }
793
+
794
let exitStatus = renderRootConcurrent(root, lanes);
795
796
if (
packages/shared/ReactFeatureFlags.js
+2
@@ -137,3 +137,5 @@ export const enableDiscreteEventFlushingChange = false;
137
export const enablePassiveEventIntervention = true;
138
139
export const enableEagerRootListeners = true;
140
+
141
+export const disableSchedulerTimeoutInWorkLoop = false;
packages/shared/forks/ReactFeatureFlags.native-fb.js
+1
@@ -51,6 +51,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
51
export const enableDiscreteEventFlushingChange = false;
52
export const enablePassiveEventIntervention = true;
53
export const enableEagerRootListeners = true;
54
+export const disableSchedulerTimeoutInWorkLoop = false;
55
56
// Flow magic to verify the exports of this file match the original version.
57
// eslint-disable-next-line no-unused-vars
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1
@@ -50,6 +50,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
50
export const enableDiscreteEventFlushingChange = false;
51
export const enablePassiveEventIntervention = true;
52
export const enableEagerRootListeners = true;
53
+export const disableSchedulerTimeoutInWorkLoop = false;
54
55
// Flow magic to verify the exports of this file match the original version.
56
// eslint-disable-next-line no-unused-vars
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1
@@ -50,6 +50,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
50
export const enableDiscreteEventFlushingChange = false;
51
export const enablePassiveEventIntervention = true;
52
export const enableEagerRootListeners = true;
53
+export const disableSchedulerTimeoutInWorkLoop = false;
54
55
// Flow magic to verify the exports of this file match the original version.
56
// eslint-disable-next-line no-unused-vars
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+1
@@ -50,6 +50,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
50
export const enableDiscreteEventFlushingChange = false;
51
export const enablePassiveEventIntervention = true;
52
export const enableEagerRootListeners = true;
53
+export const disableSchedulerTimeoutInWorkLoop = false;
54
55
// Flow magic to verify the exports of this file match the original version.
56
// eslint-disable-next-line no-unused-vars
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1
@@ -50,6 +50,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
50
export const enableDiscreteEventFlushingChange = false;
51
export const enablePassiveEventIntervention = true;
52
export const enableEagerRootListeners = true;
53
+export const disableSchedulerTimeoutInWorkLoop = false;
54
55
// Flow magic to verify the exports of this file match the original version.
56
// eslint-disable-next-line no-unused-vars
packages/shared/forks/ReactFeatureFlags.testing.js
+1
@@ -50,6 +50,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
50
export const enableDiscreteEventFlushingChange = false;
51
export const enablePassiveEventIntervention = true;
52
export const enableEagerRootListeners = true;
53
+export const disableSchedulerTimeoutInWorkLoop = false;
54
55
// Flow magic to verify the exports of this file match the original version.
56
// eslint-disable-next-line no-unused-vars
packages/shared/forks/ReactFeatureFlags.testing.www.js
+1
@@ -50,6 +50,7 @@ export const decoupleUpdatePriorityFromScheduler = false;
50
export const enableDiscreteEventFlushingChange = true;
51
export const enablePassiveEventIntervention = true;
52
export const enableEagerRootListeners = true;
53
+export const disableSchedulerTimeoutInWorkLoop = false;
54
55
// Flow magic to verify the exports of this file match the original version.
56
// eslint-disable-next-line no-unused-vars
packages/shared/forks/ReactFeatureFlags.www-dynamic.js
+1
@@ -48,3 +48,4 @@ export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
48
// to __VARIANT__.
49
export const enableTrustedTypesIntegration = false;
50
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
51
+export const disableSchedulerTimeoutInWorkLoop = __VARIANT__;
packages/shared/forks/ReactFeatureFlags.www.js
+1
@@ -29,6 +29,7 @@ export const {
29
skipUnmountedBoundaries,
30
enablePassiveEventIntervention,
31
enableEagerRootListeners,
32
+ disableSchedulerTimeoutInWorkLoop,
33
} = dynamicFeatureFlags;
34
35
// On WWW, __EXPERIMENTAL__ is used for a new modern build.