diff --git a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
index 25a560c5c32af..5ffdb38131552 100644
--- a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
@@ -13,6 +13,7 @@ let React = require('react');
let ReactDOM = require('react-dom');
let ReactDOMServer = require('react-dom/server');
let Scheduler = require('scheduler');
+let act;
describe('ReactDOMRoot', () => {
let container;
@@ -24,6 +25,7 @@ describe('ReactDOMRoot', () => {
ReactDOM = require('react-dom');
ReactDOMServer = require('react-dom/server');
Scheduler = require('scheduler');
+ act = require('react-dom/test-utils').unstable_concurrentAct;
});
if (!__EXPERIMENTAL__) {
@@ -316,4 +318,37 @@ describe('ReactDOMRoot', () => {
{withoutStack: true},
);
});
+
+ // @gate experimental
+ it('opts-in to concurrent default updates', async () => {
+ const root = ReactDOM.unstable_createRoot(container, {
+ unstable_concurrentUpdatesByDefault: true,
+ });
+
+ function Foo({value}) {
+ Scheduler.unstable_yieldValue(value);
+ return
{value}
;
+ }
+
+ await act(async () => {
+ root.render();
+ });
+
+ expect(container.textContent).toEqual('a');
+
+ await act(async () => {
+ root.render();
+
+ expect(Scheduler).toHaveYielded(['a']);
+ expect(container.textContent).toEqual('a');
+
+ expect(Scheduler).toFlushAndYieldThrough(['b']);
+ if (gate(flags => flags.allowConcurrentByDefault)) {
+ expect(container.textContent).toEqual('a');
+ } else {
+ expect(container.textContent).toEqual('b');
+ }
+ });
+ expect(container.textContent).toEqual('b');
+ });
});
diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js
index 56532d5d67488..0a78f61ad0977 100644
--- a/packages/react-dom/src/client/ReactDOMRoot.js
+++ b/packages/react-dom/src/client/ReactDOMRoot.js
@@ -28,6 +28,7 @@ export type RootOptions = {
...
},
unstable_strictModeLevel?: number,
+ unstable_concurrentUpdatesByDefault?: boolean,
...
};
@@ -52,6 +53,7 @@ import {
} from 'react-reconciler/src/ReactFiberReconciler';
import invariant from 'shared/invariant';
import {ConcurrentRoot, LegacyRoot} from 'react-reconciler/src/ReactRootTags';
+import {allowConcurrentByDefault} from 'shared/ReactFeatureFlags';
function ReactDOMRoot(container: Container, options: void | RootOptions) {
this._internalRoot = createRootImpl(container, ConcurrentRoot, options);
@@ -126,12 +128,21 @@ function createRootImpl(
? options.unstable_strictModeLevel
: null;
+ let concurrentUpdatesByDefaultOverride = null;
+ if (allowConcurrentByDefault) {
+ concurrentUpdatesByDefaultOverride =
+ options != null && options.unstable_concurrentUpdatesByDefault != null
+ ? options.unstable_concurrentUpdatesByDefault
+ : null;
+ }
+
const root = createContainer(
container,
tag,
hydrate,
hydrationCallbacks,
strictModeLevelOverride,
+ concurrentUpdatesByDefaultOverride,
);
markContainerAsRoot(root.current, container);
diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js
index 9f1f44f51cf49..b319cb22c7b7b 100644
--- a/packages/react-native-renderer/src/ReactFabric.js
+++ b/packages/react-native-renderer/src/ReactFabric.js
@@ -207,7 +207,7 @@ function render(
if (!root) {
// TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.
- root = createContainer(containerTag, LegacyRoot, false, null, null);
+ root = createContainer(containerTag, LegacyRoot, false, null, null, null);
roots.set(containerTag, root);
}
updateContainer(element, root, null, callback);
diff --git a/packages/react-native-renderer/src/ReactNativeRenderer.js b/packages/react-native-renderer/src/ReactNativeRenderer.js
index de42c6e41a58c..4f73377320378 100644
--- a/packages/react-native-renderer/src/ReactNativeRenderer.js
+++ b/packages/react-native-renderer/src/ReactNativeRenderer.js
@@ -203,7 +203,7 @@ function render(
if (!root) {
// TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.
- root = createContainer(containerTag, LegacyRoot, false, null, null);
+ root = createContainer(containerTag, LegacyRoot, false, null, null, null);
roots.set(containerTag, root);
}
updateContainer(element, root, null, callback);
diff --git a/packages/react-reconciler/src/ReactFiber.new.js b/packages/react-reconciler/src/ReactFiber.new.js
index 95a5340b18730..c883079028a53 100644
--- a/packages/react-reconciler/src/ReactFiber.new.js
+++ b/packages/react-reconciler/src/ReactFiber.new.js
@@ -24,6 +24,8 @@ import {
enableStrictEffects,
enableProfilerTimer,
enableScopeAPI,
+ enableSyncDefaultUpdates,
+ allowConcurrentByDefault,
} from 'shared/ReactFeatureFlags';
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
import {ConcurrentRoot} from './ReactRootTags';
@@ -68,6 +70,7 @@ import {
ProfileMode,
StrictLegacyMode,
StrictEffectsMode,
+ ConcurrentUpdatesByDefaultMode,
} from './ReactTypeOfMode';
import {
REACT_FORWARD_REF_TYPE,
@@ -420,6 +423,7 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
export function createHostRootFiber(
tag: RootTag,
strictModeLevelOverride: null | number,
+ concurrentUpdatesByDefaultOverride: null | boolean,
): Fiber {
let mode;
if (tag === ConcurrentRoot) {
@@ -440,6 +444,15 @@ export function createHostRootFiber(
mode |= StrictLegacyMode;
}
}
+ if (
+ // We only use this flag for our repo tests to check both behaviors.
+ // TODO: Flip this flag and rename it something like "forceConcurrentByDefaultForTesting"
+ !enableSyncDefaultUpdates ||
+ // Only for internal experiments.
+ (allowConcurrentByDefault && concurrentUpdatesByDefaultOverride)
+ ) {
+ mode |= ConcurrentUpdatesByDefaultMode;
+ }
} else {
mode = NoMode;
}
diff --git a/packages/react-reconciler/src/ReactFiber.old.js b/packages/react-reconciler/src/ReactFiber.old.js
index 159557e86a166..e33c0e7cd835f 100644
--- a/packages/react-reconciler/src/ReactFiber.old.js
+++ b/packages/react-reconciler/src/ReactFiber.old.js
@@ -24,6 +24,8 @@ import {
enableStrictEffects,
enableProfilerTimer,
enableScopeAPI,
+ enableSyncDefaultUpdates,
+ allowConcurrentByDefault,
} from 'shared/ReactFeatureFlags';
import {NoFlags, Placement, StaticMask} from './ReactFiberFlags';
import {ConcurrentRoot} from './ReactRootTags';
@@ -68,6 +70,7 @@ import {
ProfileMode,
StrictLegacyMode,
StrictEffectsMode,
+ ConcurrentUpdatesByDefaultMode,
} from './ReactTypeOfMode';
import {
REACT_FORWARD_REF_TYPE,
@@ -420,6 +423,7 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
export function createHostRootFiber(
tag: RootTag,
strictModeLevelOverride: null | number,
+ concurrentUpdatesByDefaultOverride: null | boolean,
): Fiber {
let mode;
if (tag === ConcurrentRoot) {
@@ -440,6 +444,15 @@ export function createHostRootFiber(
mode |= StrictLegacyMode;
}
}
+ if (
+ // We only use this flag for our repo tests to check both behaviors.
+ // TODO: Flip this flag and rename it something like "forceConcurrentByDefaultForTesting"
+ !enableSyncDefaultUpdates ||
+ // Only for internal experiments.
+ (allowConcurrentByDefault && concurrentUpdatesByDefaultOverride)
+ ) {
+ mode |= ConcurrentUpdatesByDefaultMode;
+ }
} else {
mode = NoMode;
}
diff --git a/packages/react-reconciler/src/ReactFiberLane.new.js b/packages/react-reconciler/src/ReactFiberLane.new.js
index 878fc433f3c53..59e04b1865d4d 100644
--- a/packages/react-reconciler/src/ReactFiberLane.new.js
+++ b/packages/react-reconciler/src/ReactFiberLane.new.js
@@ -20,9 +20,10 @@ import {
enableCache,
enableSchedulingProfiler,
enableUpdaterTracking,
- enableSyncDefaultUpdates,
+ allowConcurrentByDefault,
} from 'shared/ReactFeatureFlags';
import {isDevToolsPresent} from './ReactFiberDevToolsHook.new';
+import {ConcurrentUpdatesByDefaultMode, NoMode} from './ReactTypeOfMode';
// Lane values below should be kept in sync with getLabelsForLanes(), used by react-devtools-scheduling-profiler.
// If those values are changed that package should be rebuilt and redeployed.
@@ -253,11 +254,12 @@ export function getNextLanes(root: FiberRoot, wipLanes: Lanes): Lanes {
}
if (
- // TODO: Check for root override, once that lands
- enableSyncDefaultUpdates &&
- (nextLanes & InputContinuousLane) !== NoLanes
+ allowConcurrentByDefault &&
+ (root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode
) {
- // When updates are sync by default, we entangle continous priority updates
+ // Do nothing, use the lanes as they were assigned.
+ } else if ((nextLanes & InputContinuousLane) !== NoLanes) {
+ // When updates are sync by default, we entangle continuous priority updates
// and default updates, so they render in the same batch. The only reason
// they use separate lanes is because continuous updates should interrupt
// transitions, but default updates should not.
@@ -459,17 +461,21 @@ export function shouldTimeSlice(root: FiberRoot, lanes: Lanes) {
// finish rendering without yielding execution.
return false;
}
- if (enableSyncDefaultUpdates) {
- const SyncDefaultLanes =
- InputContinuousHydrationLane |
- InputContinuousLane |
- DefaultHydrationLane |
- DefaultLane;
- // TODO: Check for root override, once that lands
- return (lanes & SyncDefaultLanes) === NoLanes;
- } else {
+
+ if (
+ allowConcurrentByDefault &&
+ (root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode
+ ) {
+ // Concurrent updates by default always use time slicing.
return true;
}
+
+ const SyncDefaultLanes =
+ InputContinuousHydrationLane |
+ InputContinuousLane |
+ DefaultHydrationLane |
+ DefaultLane;
+ return (lanes & SyncDefaultLanes) === NoLanes;
}
export function isTransitionLane(lane: Lane) {
diff --git a/packages/react-reconciler/src/ReactFiberLane.old.js b/packages/react-reconciler/src/ReactFiberLane.old.js
index d4010468f0d74..458d3ec6290ec 100644
--- a/packages/react-reconciler/src/ReactFiberLane.old.js
+++ b/packages/react-reconciler/src/ReactFiberLane.old.js
@@ -20,9 +20,10 @@ import {
enableCache,
enableSchedulingProfiler,
enableUpdaterTracking,
- enableSyncDefaultUpdates,
+ allowConcurrentByDefault,
} from 'shared/ReactFeatureFlags';
import {isDevToolsPresent} from './ReactFiberDevToolsHook.old';
+import {ConcurrentUpdatesByDefaultMode, NoMode} from './ReactTypeOfMode';
// Lane values below should be kept in sync with getLabelsForLanes(), used by react-devtools-scheduling-profiler.
// If those values are changed that package should be rebuilt and redeployed.
@@ -253,11 +254,12 @@ export function getNextLanes(root: FiberRoot, wipLanes: Lanes): Lanes {
}
if (
- // TODO: Check for root override, once that lands
- enableSyncDefaultUpdates &&
- (nextLanes & InputContinuousLane) !== NoLanes
+ allowConcurrentByDefault &&
+ (root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode
) {
- // When updates are sync by default, we entangle continous priority updates
+ // Do nothing, use the lanes as they were assigned.
+ } else if ((nextLanes & InputContinuousLane) !== NoLanes) {
+ // When updates are sync by default, we entangle continuous priority updates
// and default updates, so they render in the same batch. The only reason
// they use separate lanes is because continuous updates should interrupt
// transitions, but default updates should not.
@@ -459,17 +461,21 @@ export function shouldTimeSlice(root: FiberRoot, lanes: Lanes) {
// finish rendering without yielding execution.
return false;
}
- if (enableSyncDefaultUpdates) {
- const SyncDefaultLanes =
- InputContinuousHydrationLane |
- InputContinuousLane |
- DefaultHydrationLane |
- DefaultLane;
- // TODO: Check for root override, once that lands
- return (lanes & SyncDefaultLanes) === NoLanes;
- } else {
+
+ if (
+ allowConcurrentByDefault &&
+ (root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode
+ ) {
+ // Concurrent updates by default always use time slicing.
return true;
}
+
+ const SyncDefaultLanes =
+ InputContinuousHydrationLane |
+ InputContinuousLane |
+ DefaultHydrationLane |
+ DefaultLane;
+ return (lanes & SyncDefaultLanes) === NoLanes;
}
export function isTransitionLane(lane: Lane) {
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.new.js b/packages/react-reconciler/src/ReactFiberReconciler.new.js
index f6318f0a03052..f53a24e86c60b 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.new.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.new.js
@@ -249,6 +249,7 @@ export function createContainer(
hydrate: boolean,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
strictModeLevelOverride: null | number,
+ concurrentUpdatesByDefaultOverride: null | boolean,
): OpaqueRoot {
return createFiberRoot(
containerInfo,
@@ -256,6 +257,7 @@ export function createContainer(
hydrate,
hydrationCallbacks,
strictModeLevelOverride,
+ concurrentUpdatesByDefaultOverride,
);
}
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.old.js b/packages/react-reconciler/src/ReactFiberReconciler.old.js
index 68a6ed619bbda..00c12b3406df8 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.old.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.old.js
@@ -249,6 +249,7 @@ export function createContainer(
hydrate: boolean,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
strictModeLevelOverride: null | number,
+ concurrentUpdatesByDefaultOverride: null | boolean,
): OpaqueRoot {
return createFiberRoot(
containerInfo,
@@ -256,6 +257,7 @@ export function createContainer(
hydrate,
hydrationCallbacks,
strictModeLevelOverride,
+ concurrentUpdatesByDefaultOverride,
);
}
diff --git a/packages/react-reconciler/src/ReactFiberRoot.new.js b/packages/react-reconciler/src/ReactFiberRoot.new.js
index e82262b5737e7..d2efcc5851d49 100644
--- a/packages/react-reconciler/src/ReactFiberRoot.new.js
+++ b/packages/react-reconciler/src/ReactFiberRoot.new.js
@@ -99,6 +99,7 @@ export function createFiberRoot(
hydrate: boolean,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
strictModeLevelOverride: null | number,
+ concurrentUpdatesByDefaultOverride: null | boolean,
): FiberRoot {
const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
if (enableSuspenseCallback) {
@@ -107,7 +108,11 @@ export function createFiberRoot(
// Cyclic construction. This cheats the type system right now because
// stateNode is any.
- const uninitializedFiber = createHostRootFiber(tag, strictModeLevelOverride);
+ const uninitializedFiber = createHostRootFiber(
+ tag,
+ strictModeLevelOverride,
+ concurrentUpdatesByDefaultOverride,
+ );
root.current = uninitializedFiber;
uninitializedFiber.stateNode = root;
diff --git a/packages/react-reconciler/src/ReactFiberRoot.old.js b/packages/react-reconciler/src/ReactFiberRoot.old.js
index 20c3cdaa6cbff..68d329492cf1b 100644
--- a/packages/react-reconciler/src/ReactFiberRoot.old.js
+++ b/packages/react-reconciler/src/ReactFiberRoot.old.js
@@ -99,6 +99,7 @@ export function createFiberRoot(
hydrate: boolean,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
strictModeLevelOverride: null | number,
+ concurrentUpdatesByDefaultOverride: null | boolean,
): FiberRoot {
const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
if (enableSuspenseCallback) {
@@ -107,7 +108,11 @@ export function createFiberRoot(
// Cyclic construction. This cheats the type system right now because
// stateNode is any.
- const uninitializedFiber = createHostRootFiber(tag, strictModeLevelOverride);
+ const uninitializedFiber = createHostRootFiber(
+ tag,
+ strictModeLevelOverride,
+ concurrentUpdatesByDefaultOverride,
+ );
root.current = uninitializedFiber;
uninitializedFiber.stateNode = root;
diff --git a/packages/react-reconciler/src/ReactTypeOfMode.js b/packages/react-reconciler/src/ReactTypeOfMode.js
index 466363fabd4e8..f16d2c51b76c0 100644
--- a/packages/react-reconciler/src/ReactTypeOfMode.js
+++ b/packages/react-reconciler/src/ReactTypeOfMode.js
@@ -9,10 +9,11 @@
export type TypeOfMode = number;
-export const NoMode = /* */ 0b000000;
+export const NoMode = /* */ 0b000000;
// TODO: Remove ConcurrentMode by reading from the root tag instead
-export const ConcurrentMode = /* */ 0b000001;
-export const ProfileMode = /* */ 0b000010;
-export const DebugTracingMode = /* */ 0b000100;
-export const StrictLegacyMode = /* */ 0b001000;
-export const StrictEffectsMode = /* */ 0b010000;
+export const ConcurrentMode = /* */ 0b000001;
+export const ProfileMode = /* */ 0b000010;
+export const DebugTracingMode = /* */ 0b000100;
+export const StrictLegacyMode = /* */ 0b001000;
+export const StrictEffectsMode = /* */ 0b010000;
+export const ConcurrentUpdatesByDefaultMode = /* */ 0b100000;
diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js
index 5c74c6e9e310c..7c64a16936005 100644
--- a/packages/react-test-renderer/src/ReactTestRenderer.js
+++ b/packages/react-test-renderer/src/ReactTestRenderer.js
@@ -51,6 +51,7 @@ import enqueueTask from 'shared/enqueueTask';
import {getPublicInstance} from './ReactTestHostConfig';
import {ConcurrentRoot, LegacyRoot} from 'react-reconciler/src/ReactRootTags';
+import {allowConcurrentByDefault} from 'shared/ReactFeatureFlags';
const {IsSomeRendererActing} = ReactSharedInternals;
@@ -58,6 +59,7 @@ type TestRendererOptions = {
createNodeMock: (element: React$Element) => any,
unstable_isConcurrent: boolean,
unstable_strictModeLevel: number,
+ unstable_concurrentUpdatesByDefault: boolean,
...
};
@@ -436,6 +438,7 @@ function create(element: React$Element, options: TestRendererOptions) {
let createNodeMock = defaultTestOptions.createNodeMock;
let isConcurrent = false;
let strictModeLevel = null;
+ let concurrentUpdatesByDefault = null;
if (typeof options === 'object' && options !== null) {
if (typeof options.createNodeMock === 'function') {
createNodeMock = options.createNodeMock;
@@ -446,6 +449,12 @@ function create(element: React$Element, options: TestRendererOptions) {
if (options.unstable_strictModeLevel !== undefined) {
strictModeLevel = options.unstable_strictModeLevel;
}
+ if (allowConcurrentByDefault) {
+ if (options.unstable_concurrentUpdatesByDefault !== undefined) {
+ concurrentUpdatesByDefault =
+ options.unstable_concurrentUpdatesByDefault;
+ }
+ }
}
let container = {
children: [],
@@ -458,6 +467,7 @@ function create(element: React$Element, options: TestRendererOptions) {
false,
null,
strictModeLevel,
+ concurrentUpdatesByDefault,
);
invariant(root != null, 'something went wrong');
updateContainer(element, root, null, null);
diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js
index 757d9ab28b784..ede084ff74ace 100644
--- a/packages/shared/ReactFeatureFlags.js
+++ b/packages/shared/ReactFeatureFlags.js
@@ -169,3 +169,5 @@ export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = false;
export const enableSyncDefaultUpdates = true;
+
+export const allowConcurrentByDefault = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js
index ea9224d5a9445..a2b9cc8446c4c 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-fb.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js
@@ -60,6 +60,7 @@ export const enableRecursiveCommitTraversal = false;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = false;
export const enableSyncDefaultUpdates = false;
+export const allowConcurrentByDefault = false;
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js
index 251bb310c1fb6..eb3a55187e7d5 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-oss.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js
@@ -59,6 +59,7 @@ export const enableRecursiveCommitTraversal = false;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = false;
export const enableSyncDefaultUpdates = true;
+export const allowConcurrentByDefault = false;
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js
index aeee968922f12..1a8a75a4c60fb 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js
@@ -59,6 +59,7 @@ export const enableRecursiveCommitTraversal = false;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = false;
export const enableSyncDefaultUpdates = true;
+export const allowConcurrentByDefault = false;
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
index 88f2287cd81b4..727e8764fc126 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
@@ -59,6 +59,7 @@ export const enableRecursiveCommitTraversal = false;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = false;
export const enableSyncDefaultUpdates = false;
+export const allowConcurrentByDefault = false;
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
index 5d43505fa1279..688d30ee9fe2b 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
@@ -59,6 +59,7 @@ export const enableRecursiveCommitTraversal = false;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = false;
export const enableSyncDefaultUpdates = false;
+export const allowConcurrentByDefault = true;
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
diff --git a/packages/shared/forks/ReactFeatureFlags.testing.js b/packages/shared/forks/ReactFeatureFlags.testing.js
index 0edbfad4ab170..d593aa3f9cee5 100644
--- a/packages/shared/forks/ReactFeatureFlags.testing.js
+++ b/packages/shared/forks/ReactFeatureFlags.testing.js
@@ -59,6 +59,7 @@ export const enableRecursiveCommitTraversal = false;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = false;
export const enableSyncDefaultUpdates = true;
+export const allowConcurrentByDefault = false;
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
diff --git a/packages/shared/forks/ReactFeatureFlags.testing.www.js b/packages/shared/forks/ReactFeatureFlags.testing.www.js
index 98dbae4505e08..01f184c1e4584 100644
--- a/packages/shared/forks/ReactFeatureFlags.testing.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.testing.www.js
@@ -59,6 +59,7 @@ export const enableRecursiveCommitTraversal = false;
export const disableSchedulerTimeoutInWorkLoop = false;
export const enableLazyContextPropagation = false;
export const enableSyncDefaultUpdates = true;
+export const allowConcurrentByDefault = true;
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js
index d0fc8e6177067..b8c7a56ce720c 100644
--- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js
+++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js
@@ -60,3 +60,4 @@ export const enableProfilerNestedUpdateScheduledHook = __VARIANT__;
export const disableSchedulerTimeoutInWorkLoop = __VARIANT__;
export const enableLazyContextPropagation = __VARIANT__;
export const enableSyncDefaultUpdates = __VARIANT__;
+export const allowConcurrentByDefault = true;
diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js
index afae32b4082fb..1d9c88cc8fcfb 100644
--- a/packages/shared/forks/ReactFeatureFlags.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.www.js
@@ -93,6 +93,8 @@ export const enableNewReconciler = __VARIANT__;
export const enableRecursiveCommitTraversal = false;
+export const allowConcurrentByDefault = true;
+
// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
type Check<_X, Y: _X, X: Y = _X> = null;