From 76158e3d086e65079b2f98e1f9cdd47368530f4b Mon Sep 17 00:00:00 2001 From: Ricky Date: Thu, 1 Jun 2023 09:24:56 -0400 Subject: [PATCH] Clean up enableSyncDefaultUpdates flag a bit (#26858) ## Overview Does a few things: - Renames `enableSyncDefaultUpdates` to `forceConcurrentByDefaultForTesting` - Changes the way it's used so it's dead-code eliminated separate from `allowConcurrentByDefault` - Deletes a bunch of the gated code The gates that are deleted are unnecessary now. We were keeping them when we originally thought we would come back to being concurrent by default. But we've shifted and now sync-by default is the desired behavior long term, so there's no need to keep all these forked tests around. I'll follow up to delete more of the forked behavior if possible. Ideally we wouldn't need this flag even if we're still using `allowConcurrentByDefault`. --- .../react-art/src/__tests__/ReactART-test.js | 2 +- .../ReactDOMNativeEventHeuristic-test.js | 6 +- ...DOMServerPartialHydration-test.internal.js | 6 +- .../DOMPluginEventSystem-test.internal.js | 8 +- packages/react-reconciler/src/ReactFiber.js | 11 +- .../src/__tests__/ReactExpiration-test.js | 160 ++++++--------- .../src/__tests__/ReactFlushSync-test.js | 8 +- .../ReactHooksWithNoopRenderer-test.js | 53 ++--- .../src/__tests__/ReactIncremental-test.js | 111 ++--------- ...tIncrementalErrorHandling-test.internal.js | 92 ++------- .../ReactIncrementalReflection-test.js | 40 +--- .../ReactIncrementalScheduling-test.js | 41 +--- .../ReactIncrementalSideEffects-test.js | 32 +-- .../__tests__/ReactIncrementalUpdates-test.js | 103 ++++------ .../__tests__/ReactInterleavedUpdates-test.js | 18 +- .../src/__tests__/ReactNewContext-test.js | 16 +- .../ReactSchedulerIntegration-test.js | 8 +- .../__tests__/ReactSuspense-test.internal.js | 18 +- .../src/__tests__/ReactSuspenseList-test.js | 24 +-- .../ReactSuspenseWithNoopRenderer-test.js | 70 ++----- .../useMutableSource-test.internal.js | 188 ++++-------------- .../useMutableSourceHydration-test.js | 14 +- .../__tests__/ReactTestRendererAsync-test.js | 20 +- .../__tests__/ReactProfiler-test.internal.js | 88 ++------ ...ofilerDevToolsIntegration-test.internal.js | 8 +- packages/shared/ReactFeatureFlags.js | 5 +- .../forks/ReactFeatureFlags.native-fb.js | 2 +- .../forks/ReactFeatureFlags.native-oss.js | 2 +- .../forks/ReactFeatureFlags.test-renderer.js | 2 +- .../ReactFeatureFlags.test-renderer.native.js | 2 +- .../ReactFeatureFlags.test-renderer.www.js | 2 +- .../forks/ReactFeatureFlags.www-dynamic.js | 2 +- .../shared/forks/ReactFeatureFlags.www.js | 2 +- .../src/__tests__/useSubscription-test.js | 32 +-- scripts/jest/setupTests.www.js | 2 +- 35 files changed, 316 insertions(+), 882 deletions(-) diff --git a/packages/react-art/src/__tests__/ReactART-test.js b/packages/react-art/src/__tests__/ReactART-test.js index 9f73006d0201a..47b5958cf4c9c 100644 --- a/packages/react-art/src/__tests__/ReactART-test.js +++ b/packages/react-art/src/__tests__/ReactART-test.js @@ -364,7 +364,7 @@ describe('ReactART', () => { expect(onClick2).toBeCalled(); }); - // @gate !enableSyncDefaultUpdates + // @gate forceConcurrentByDefaultForTesting it('can concurrently render with a "primary" renderer while sharing context', async () => { const CurrentRendererContext = React.createContext(null); diff --git a/packages/react-dom/src/__tests__/ReactDOMNativeEventHeuristic-test.js b/packages/react-dom/src/__tests__/ReactDOMNativeEventHeuristic-test.js index 3300dc1bb35c3..6b445f9cf8d61 100644 --- a/packages/react-dom/src/__tests__/ReactDOMNativeEventHeuristic-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMNativeEventHeuristic-test.js @@ -312,10 +312,10 @@ describe('ReactDOMNativeEventHeuristic-test', () => { expect(container.textContent).toEqual('not hovered'); await waitFor(['hovered']); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - expect(container.textContent).toEqual('hovered'); - } else { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { expect(container.textContent).toEqual('not hovered'); + } else { + expect(container.textContent).toEqual('hovered'); } }); expect(container.textContent).toEqual('hovered'); diff --git a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js index ab09c63a7bcb9..4384bc03651bc 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js @@ -2036,13 +2036,13 @@ describe('ReactDOMServerPartialHydration', () => { suspend = true; await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - await waitFor(['Before', 'After']); - } else { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { await waitFor(['Before']); // This took a long time to render. Scheduler.unstable_advanceTime(1000); await waitFor(['After']); + } else { + await waitFor(['Before', 'After']); } // This will cause us to skip the second row completely. diff --git a/packages/react-dom/src/events/__tests__/DOMPluginEventSystem-test.internal.js b/packages/react-dom/src/events/__tests__/DOMPluginEventSystem-test.internal.js index 4b6c5717fa29b..1a1769e82c07e 100644 --- a/packages/react-dom/src/events/__tests__/DOMPluginEventSystem-test.internal.js +++ b/packages/react-dom/src/events/__tests__/DOMPluginEventSystem-test.internal.js @@ -1984,13 +1984,9 @@ describe('DOMPluginEventSystem', () => { log.length = 0; // Increase counter - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); // Yield before committing await waitFor(['Test']); diff --git a/packages/react-reconciler/src/ReactFiber.js b/packages/react-reconciler/src/ReactFiber.js index 7eefefa1c4d14..84ef41f4fb97b 100644 --- a/packages/react-reconciler/src/ReactFiber.js +++ b/packages/react-reconciler/src/ReactFiber.js @@ -33,7 +33,7 @@ import { enableProfilerTimer, enableScopeAPI, enableLegacyHidden, - enableSyncDefaultUpdates, + forceConcurrentByDefaultForTesting, allowConcurrentByDefault, enableTransitionTracing, enableDebugTracing, @@ -460,10 +460,13 @@ export function createHostRootFiber( } 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 || + forceConcurrentByDefaultForTesting + ) { + mode |= ConcurrentUpdatesByDefaultMode; + } else if ( // Only for internal experiments. - (allowConcurrentByDefault && concurrentUpdatesByDefaultOverride) + allowConcurrentByDefault && + concurrentUpdatesByDefaultOverride ) { mode |= ConcurrentUpdatesByDefaultMode; } diff --git a/packages/react-reconciler/src/__tests__/ReactExpiration-test.js b/packages/react-reconciler/src/__tests__/ReactExpiration-test.js index 653bc304600bb..cd09ca347885b 100644 --- a/packages/react-reconciler/src/__tests__/ReactExpiration-test.js +++ b/packages/react-reconciler/src/__tests__/ReactExpiration-test.js @@ -125,7 +125,22 @@ describe('ReactExpiration', () => { } it('increases priority of updates as time progresses', async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { + ReactNoop.render(); + expect(ReactNoop).toMatchRenderedOutput(null); + + // Nothing has expired yet because time hasn't advanced. + flushNextRenderIfExpired(); + expect(ReactNoop).toMatchRenderedOutput(null); + // Advance time a bit, but not enough to expire the low pri update. + ReactNoop.expire(4500); + flushNextRenderIfExpired(); + expect(ReactNoop).toMatchRenderedOutput(null); + // Advance by another second. Now the update should expire and flush. + ReactNoop.expire(500); + flushNextRenderIfExpired(); + expect(ReactNoop).toMatchRenderedOutput(); + } else { ReactNoop.render(); React.startTransition(() => { ReactNoop.render(); @@ -147,21 +162,6 @@ describe('ReactExpiration', () => { ReactNoop.expire(500); await unstable_waitForExpired(['Step 2']); expect(ReactNoop).toMatchRenderedOutput('Step 2'); - } else { - ReactNoop.render(); - expect(ReactNoop).toMatchRenderedOutput(null); - - // Nothing has expired yet because time hasn't advanced. - flushNextRenderIfExpired(); - expect(ReactNoop).toMatchRenderedOutput(null); - // Advance time a bit, but not enough to expire the low pri update. - ReactNoop.expire(4500); - flushNextRenderIfExpired(); - expect(ReactNoop).toMatchRenderedOutput(null); - // Advance by another second. Now the update should expire and flush. - ReactNoop.expire(500); - flushNextRenderIfExpired(); - expect(ReactNoop).toMatchRenderedOutput(); } }); @@ -187,13 +187,9 @@ describe('ReactExpiration', () => { // First, show what happens for updates in two separate events. // Schedule an update. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Advance the timer. Scheduler.unstable_advanceTime(2000); // Partially flush the first update, then interrupt it. @@ -248,13 +244,10 @@ describe('ReactExpiration', () => { // First, show what happens for updates in two separate events. // Schedule an update. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); + // Advance the timer. Scheduler.unstable_advanceTime(2000); // Partially flush the first update, then interrupt it. @@ -320,13 +313,10 @@ describe('ReactExpiration', () => { } // Initial mount - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); + await waitForAll([ 'initial [A] [render]', 'initial [B] [render]', @@ -339,13 +329,10 @@ describe('ReactExpiration', () => { ]); // Partial update - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - subscribers.forEach(s => s.setState({text: '1'})); - }); - } else { + React.startTransition(() => { subscribers.forEach(s => s.setState({text: '1'})); - } + }); + await waitFor(['1 [A] [render]', '1 [B] [render]']); // Before the update can finish, update again. Even though no time has @@ -371,13 +358,9 @@ describe('ReactExpiration', () => { ); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); await waitFor(['A']); await waitFor(['B']); @@ -404,13 +387,9 @@ describe('ReactExpiration', () => { ); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); await waitFor(['A']); await waitFor(['B']); @@ -429,7 +408,26 @@ describe('ReactExpiration', () => { jest.resetModules(); Scheduler = require('scheduler'); - if (gate(flags => flags.enableSyncDefaultUpdates)) { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { + // Before importing the renderer, advance the current time by a number + // larger than the maximum allowed for bitwise operations. + const maxSigned31BitInt = 1073741823; + Scheduler.unstable_advanceTime(maxSigned31BitInt * 100); + // Now import the renderer. On module initialization, it will read the + // current time. + ReactNoop = require('react-noop-renderer'); + ReactNoop.render('Hi'); + + // The update should not have expired yet. + flushNextRenderIfExpired(); + await waitFor([]); + expect(ReactNoop).toMatchRenderedOutput(null); + // Advance the time some more to expire the update. + Scheduler.unstable_advanceTime(10000); + flushNextRenderIfExpired(); + await waitFor([]); + expect(ReactNoop).toMatchRenderedOutput('Hi'); + } else { const InternalTestUtils = require('internal-test-utils'); waitFor = InternalTestUtils.waitFor; assertLog = InternalTestUtils.assertLog; @@ -446,14 +444,10 @@ describe('ReactExpiration', () => { React = require('react'); ReactNoop.render(); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - await waitFor(['Step 1']); - } else { - ReactNoop.render('Hi'); - } + React.startTransition(() => { + ReactNoop.render(); + }); + await waitFor(['Step 1']); // The update should not have expired yet. await unstable_waitForExpired([]); @@ -464,25 +458,6 @@ describe('ReactExpiration', () => { Scheduler.unstable_advanceTime(10000); await unstable_waitForExpired(['Step 2']); expect(ReactNoop).toMatchRenderedOutput('Step 2'); - } else { - // Before importing the renderer, advance the current time by a number - // larger than the maximum allowed for bitwise operations. - const maxSigned31BitInt = 1073741823; - Scheduler.unstable_advanceTime(maxSigned31BitInt * 100); - // Now import the renderer. On module initialization, it will read the - // current time. - ReactNoop = require('react-noop-renderer'); - ReactNoop.render('Hi'); - - // The update should not have expired yet. - flushNextRenderIfExpired(); - await waitFor([]); - expect(ReactNoop).toMatchRenderedOutput(null); - // Advance the time some more to expire the update. - Scheduler.unstable_advanceTime(10000); - flushNextRenderIfExpired(); - await waitFor([]); - expect(ReactNoop).toMatchRenderedOutput('Hi'); } }); @@ -494,13 +469,10 @@ describe('ReactExpiration', () => { // Before scheduling an update, advance the current time. Scheduler.unstable_advanceTime(10000); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render('Hi'); - }); - } else { + React.startTransition(() => { ReactNoop.render('Hi'); - } + }); + await unstable_waitForExpired([]); expect(ReactNoop).toMatchRenderedOutput(null); @@ -541,13 +513,9 @@ describe('ReactExpiration', () => { // First demonstrate what happens when there's no starvation await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - updateNormalPri(); - }); - } else { + React.startTransition(() => { updateNormalPri(); - } + }); await waitFor(['Sync pri: 0']); updateSyncPri(); assertLog(['Sync pri: 1', 'Normal pri: 0']); @@ -565,13 +533,9 @@ describe('ReactExpiration', () => { // Do the same thing, but starve the first update await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - updateNormalPri(); - }); - } else { + React.startTransition(() => { updateNormalPri(); - } + }); await waitFor(['Sync pri: 1']); // This time, a lot of time has elapsed since the normal pri update diff --git a/packages/react-reconciler/src/__tests__/ReactFlushSync-test.js b/packages/react-reconciler/src/__tests__/ReactFlushSync-test.js index 57e2aad2e3334..e2d9ba76660f9 100644 --- a/packages/react-reconciler/src/__tests__/ReactFlushSync-test.js +++ b/packages/react-reconciler/src/__tests__/ReactFlushSync-test.js @@ -49,13 +49,9 @@ describe('ReactFlushSync', () => { const root = ReactNoop.createRoot(); await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); // This will yield right before the passive effect fires await waitForPaint(['0, 0']); diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js index 5609b462258ad..8e32084cf7c49 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js @@ -179,15 +179,10 @@ describe('ReactHooksWithNoopRenderer', () => { // Schedule some updates await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - counter.current.updateCount(1); - counter.current.updateCount(count => count + 10); - }); - } else { + React.startTransition(() => { counter.current.updateCount(1); counter.current.updateCount(count => count + 10); - } + }); // Partially flush without committing await waitFor(['Count: 11']); @@ -800,13 +795,9 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.discreteUpdates(() => { setRow(5); }); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - setRow(20); - }); - } else { + React.startTransition(() => { setRow(20); - } + }); }); assertLog(['Up', 'Down']); expect(root).toMatchRenderedOutput(); @@ -1318,13 +1309,9 @@ describe('ReactHooksWithNoopRenderer', () => { ]); // Schedule another update for children, and partially process it. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - setChildStates.forEach(setChildState => setChildState(2)); - }); - } else { + React.startTransition(() => { setChildStates.forEach(setChildState => setChildState(2)); - } + }); await waitFor(['Child one render']); // Schedule unmount for the parent that unmounts children with pending update. @@ -1598,29 +1585,21 @@ describe('ReactHooksWithNoopRenderer', () => { expect(ReactNoop).toMatchRenderedOutput(); // Rendering again should flush the previous commit's effects - if (gate(flags => flags.enableSyncDefaultUpdates)) { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { + ReactNoop.render(, () => + Scheduler.log('Sync effect'), + ); + } else { React.startTransition(() => { ReactNoop.render(, () => Scheduler.log('Sync effect'), ); }); - } else { - ReactNoop.render(, () => - Scheduler.log('Sync effect'), - ); } await waitFor(['Schedule update [0]', 'Count: 0']); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - expect(ReactNoop).toMatchRenderedOutput(); - await waitFor([ - 'Count: 0', - 'Sync effect', - 'Schedule update [1]', - 'Count: 1', - ]); - } else { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { expect(ReactNoop).toMatchRenderedOutput( , ); @@ -1630,6 +1609,14 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.flushPassiveEffects(); assertLog(['Schedule update [1]']); await waitForAll(['Count: 1']); + } else { + expect(ReactNoop).toMatchRenderedOutput(); + await waitFor([ + 'Count: 0', + 'Sync effect', + 'Schedule update [1]', + 'Count: 1', + ]); } expect(ReactNoop).toMatchRenderedOutput(); diff --git a/packages/react-reconciler/src/__tests__/ReactIncremental-test.js b/packages/react-reconciler/src/__tests__/ReactIncremental-test.js index 4a51c737350d6..13f904bf9d014 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncremental-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncremental-test.js @@ -75,13 +75,9 @@ describe('ReactIncremental', () => { return [, ]; } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(, () => Scheduler.log('callback')); - }); - } else { + React.startTransition(() => { ReactNoop.render(, () => Scheduler.log('callback')); - } + }); // Do one step of work. await waitFor(['Foo']); @@ -168,26 +164,18 @@ describe('ReactIncremental', () => { ReactNoop.render(); await waitForAll(['Foo', 'Bar', 'Bar']); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Flush part of the work await waitFor(['Foo', 'Bar']); // This will abort the previous work and restart ReactNoop.flushSync(() => ReactNoop.render(null)); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Flush part of the new work await waitFor(['Foo', 'Bar']); @@ -221,17 +209,7 @@ describe('ReactIncremental', () => { ReactNoop.render(); await waitForAll([]); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - inst.setState( - () => { - Scheduler.log('setState1'); - return {text: 'bar'}; - }, - () => Scheduler.log('callback1'), - ); - }); - } else { + React.startTransition(() => { inst.setState( () => { Scheduler.log('setState1'); @@ -239,24 +217,14 @@ describe('ReactIncremental', () => { }, () => Scheduler.log('callback1'), ); - } + }); // Flush part of the work await waitFor(['setState1']); // This will abort the previous work and restart ReactNoop.flushSync(() => ReactNoop.render()); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - inst.setState( - () => { - Scheduler.log('setState2'); - return {text2: 'baz'}; - }, - () => Scheduler.log('callback2'), - ); - }); - } else { + React.startTransition(() => { inst.setState( () => { Scheduler.log('setState2'); @@ -264,7 +232,7 @@ describe('ReactIncremental', () => { }, () => Scheduler.log('callback2'), ); - } + }); // Flush the rest of the work which now includes the low priority await waitForAll(['setState1', 'setState2', 'callback1', 'callback2']); @@ -1825,18 +1793,7 @@ describe('ReactIncremental', () => { 'ShowLocale {"locale":"de"}', 'ShowBoth {"locale":"de"}', ]); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - - -
- -
-
, - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( @@ -1845,7 +1802,7 @@ describe('ReactIncremental', () => { , ); - } + }); await waitFor(['Intl {}']); ReactNoop.render( @@ -1977,22 +1934,7 @@ describe('ReactIncremental', () => { } } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - - - - - - - - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( @@ -2005,7 +1947,8 @@ describe('ReactIncremental', () => { , ); - } + }); + await waitFor([ 'Intl {}', 'ShowLocale {"locale":"fr"}', @@ -2682,13 +2625,9 @@ describe('ReactIncremental', () => { return null; } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitFor(['Parent: 1']); // Interrupt at same priority @@ -2708,13 +2647,9 @@ describe('ReactIncremental', () => { return null; } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitFor(['Parent: 1']); // Interrupt at lower priority @@ -2735,13 +2670,9 @@ describe('ReactIncremental', () => { return null; } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitFor(['Parent: 1']); // Interrupt at higher priority diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index ac606f1e6870a..2f6b225f2f60e 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -97,25 +97,7 @@ describe('ReactIncrementalErrorHandling', () => { throw new Error('oops!'); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - - - - - - - - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> @@ -131,7 +113,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - } + }); // Start rendering asynchronously await waitFor([ @@ -214,25 +196,7 @@ describe('ReactIncrementalErrorHandling', () => { throw new Error('oops!'); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - - - - - - - - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> @@ -248,7 +212,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - } + }); // Start rendering asynchronously await waitFor([ @@ -416,13 +380,9 @@ describe('ReactIncrementalErrorHandling', () => { ); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(, () => Scheduler.log('commit')); - }); - } else { + React.startTransition(() => { ReactNoop.render(, () => Scheduler.log('commit')); - } + }); // Render the bad component asynchronously await waitFor(['Parent', 'BadRender']); @@ -458,13 +418,9 @@ describe('ReactIncrementalErrorHandling', () => { ); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Render part of the tree await waitFor(['A', 'B']); @@ -595,21 +551,13 @@ describe('ReactIncrementalErrorHandling', () => { throw new Error('Hello'); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( , ); - } + }); await waitFor(['ErrorBoundary render success']); expect(ReactNoop).toMatchRenderedOutput(null); @@ -783,21 +731,13 @@ describe('ReactIncrementalErrorHandling', () => { throw new Error('Hello'); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( , ); - } + }); await waitFor(['RethrowErrorBoundary render']); @@ -1856,13 +1796,9 @@ describe('ReactIncrementalErrorHandling', () => { } await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); // Render past the component that throws, then yield. await waitFor(['Oops']); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.js index 2ae5002b97f74..cffd690e64715 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.js @@ -65,13 +65,9 @@ describe('ReactIncrementalReflection', () => { return ; } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Render part way through but don't yet commit the updates. await waitFor(['componentWillMount: false']); @@ -117,13 +113,9 @@ describe('ReactIncrementalReflection', () => { expect(instances[0]._isMounted()).toBe(true); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Render part way through but don't yet commit the updates so it is not // fully unmounted yet. await waitFor(['Other']); @@ -191,13 +183,9 @@ describe('ReactIncrementalReflection', () => { return [, ]; } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Flush past Component but don't complete rendering everything yet. await waitFor([['componentWillMount', null], 'render', 'render sibling']); @@ -227,13 +215,9 @@ describe('ReactIncrementalReflection', () => { // The next step will render a new host node but won't get committed yet. // We expect this to mutate the original Fiber. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitFor([ ['componentWillUpdate', hostSpan], 'render', @@ -254,13 +238,9 @@ describe('ReactIncrementalReflection', () => { expect(ReactNoop.findInstance(classInstance)).toBe(hostDiv); // Render to null but don't commit it yet. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitFor([ ['componentWillUpdate', hostDiv], 'render', diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.js index 6a1f16fdc2c7d..8c00ec741206e 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.js @@ -115,15 +115,10 @@ describe('ReactIncrementalScheduling', () => { // Schedule deferred work in the reverse order await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.renderToRootWithID(, 'c'); - ReactNoop.renderToRootWithID(, 'b'); - }); - } else { + React.startTransition(() => { ReactNoop.renderToRootWithID(, 'c'); ReactNoop.renderToRootWithID(, 'b'); - } + }); // Ensure it starts in the order it was scheduled await waitFor(['c:2']); @@ -132,13 +127,9 @@ describe('ReactIncrementalScheduling', () => { expect(ReactNoop.getChildrenAsJSX('c')).toEqual('c:2'); // Schedule last bit of work, it will get processed the last - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.renderToRootWithID(, 'a'); - }); - } else { + React.startTransition(() => { ReactNoop.renderToRootWithID(, 'a'); - } + }); // Keep performing work in the order it was scheduled await waitFor(['b:2']); @@ -189,13 +180,9 @@ describe('ReactIncrementalScheduling', () => { } } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Render without committing await waitFor(['render: 0']); @@ -209,13 +196,9 @@ describe('ReactIncrementalScheduling', () => { 'componentDidUpdate: 1', ]); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - instance.setState({tick: 2}); - }); - } else { + React.startTransition(() => { instance.setState({tick: 2}); - } + }); await waitFor(['render: 2']); expect(ReactNoop.flushNextYield()).toEqual([ 'componentDidUpdate: 2', @@ -316,13 +299,9 @@ describe('ReactIncrementalScheduling', () => { return ; } } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // This should be just enough to complete all the work, but not enough to // commit it. diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js index 5df785b7e03cd..b47897e54d92e 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js @@ -464,13 +464,9 @@ describe('ReactIncrementalSideEffects', () => { , ); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Flush some of the work without committing await waitFor(['Foo', 'Bar']); @@ -703,13 +699,9 @@ describe('ReactIncrementalSideEffects', () => { Scheduler.log('Foo ' + props.step); return ; } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // This should be just enough to complete the tree without committing it await waitFor(['Foo 1']); expect(ReactNoop.getChildrenAsJSX()).toEqual(null); @@ -718,26 +710,18 @@ describe('ReactIncrementalSideEffects', () => { await waitForPaint([]); expect(ReactNoop.getChildrenAsJSX()).toEqual(); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // This should be just enough to complete the tree without committing it await waitFor(['Foo 2']); expect(ReactNoop.getChildrenAsJSX()).toEqual(); // This time, before we commit the tree, we update the root component with // new props - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); expect(ReactNoop.getChildrenAsJSX()).toEqual(); // Now let's commit. We already had a commit that was pending, which will // render 2. diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js index 13488a7c899de..f3d5cbc675c52 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js @@ -158,7 +158,9 @@ describe('ReactIncrementalUpdates', () => { // Schedule some async updates if ( gate( - flags => flags.enableSyncDefaultUpdates || flags.enableUnifiedSyncLane, + flags => + !flags.forceConcurrentByDefaultForTesting || + flags.enableUnifiedSyncLane, ) ) { React.startTransition(() => { @@ -189,7 +191,9 @@ describe('ReactIncrementalUpdates', () => { // The sync updates should have flushed, but not the async ones. if ( gate( - flags => flags.enableSyncDefaultUpdates && flags.enableUnifiedSyncLane, + flags => + !flags.forceConcurrentByDefaultForTesting && + flags.enableUnifiedSyncLane, ) ) { assertLog(['d', 'e', 'f']); @@ -205,7 +209,9 @@ describe('ReactIncrementalUpdates', () => { // is deterministic. if ( gate( - flags => flags.enableSyncDefaultUpdates && !flags.enableUnifiedSyncLane, + flags => + !flags.forceConcurrentByDefaultForTesting && + !flags.enableUnifiedSyncLane, ) ) { await waitForAll([ @@ -263,7 +269,9 @@ describe('ReactIncrementalUpdates', () => { // Schedule some async updates if ( gate( - flags => flags.enableSyncDefaultUpdates || flags.enableUnifiedSyncLane, + flags => + !flags.forceConcurrentByDefaultForTesting || + flags.enableUnifiedSyncLane, ) ) { React.startTransition(() => { @@ -297,7 +305,9 @@ describe('ReactIncrementalUpdates', () => { // The sync updates should have flushed, but not the async ones. if ( gate( - flags => flags.enableSyncDefaultUpdates && flags.enableUnifiedSyncLane, + flags => + !flags.forceConcurrentByDefaultForTesting && + flags.enableUnifiedSyncLane, ) ) { assertLog(['d', 'e', 'f']); @@ -312,7 +322,9 @@ describe('ReactIncrementalUpdates', () => { // is deterministic. if ( gate( - flags => flags.enableSyncDefaultUpdates && !flags.enableUnifiedSyncLane, + flags => + !flags.forceConcurrentByDefaultForTesting && + !flags.enableUnifiedSyncLane, ) ) { await waitForAll([ @@ -543,13 +555,9 @@ describe('ReactIncrementalUpdates', () => { } await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); assertLog([]); await waitForAll([ 'Render: 0', @@ -560,13 +568,9 @@ describe('ReactIncrementalUpdates', () => { ]); Scheduler.unstable_advanceTime(10000); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - setCount(2); - }); - } else { + React.startTransition(() => { setCount(2); - } + }); // The transition should not have expired, so we should be able to // partially render it. await waitFor(['Render: 2']); @@ -583,18 +587,7 @@ describe('ReactIncrementalUpdates', () => { Scheduler.unstable_advanceTime(10000); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> @@ -603,7 +596,7 @@ describe('ReactIncrementalUpdates', () => { , ); - } + }); // The transition should not have expired, so we should be able to // partially render it. await waitFor(['A']); @@ -612,18 +605,7 @@ describe('ReactIncrementalUpdates', () => { }); it('regression: does not expire soon due to previous expired work', async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> @@ -632,7 +614,8 @@ describe('ReactIncrementalUpdates', () => { , ); - } + }); + await waitFor(['A']); // This will expire the rest of the update Scheduler.unstable_advanceTime(10000); @@ -643,18 +626,7 @@ describe('ReactIncrementalUpdates', () => { Scheduler.unstable_advanceTime(10000); // Now do another transition. This one should not expire. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> @@ -663,7 +635,8 @@ describe('ReactIncrementalUpdates', () => { , ); - } + }); + // The transition should not have expired, so we should be able to // partially render it. await waitFor(['A']); @@ -703,13 +676,9 @@ describe('ReactIncrementalUpdates', () => { expect(root).toMatchRenderedOutput(null); await act(() => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - pushToLog('A'); - }); - } else { + React.startTransition(() => { pushToLog('A'); - } + }); ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () => pushToLog('B'), @@ -768,13 +737,9 @@ describe('ReactIncrementalUpdates', () => { expect(root).toMatchRenderedOutput(null); await act(() => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - pushToLog('A'); - }); - } else { + React.startTransition(() => { pushToLog('A'); - } + }); ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () => pushToLog('B'), ); diff --git a/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js b/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js index 61e8985ebb0a0..7e676861b5d31 100644 --- a/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js +++ b/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js @@ -65,25 +65,17 @@ describe('ReactInterleavedUpdates', () => { expect(root).toMatchRenderedOutput('000'); await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - updateChildren(1); - }); - } else { + React.startTransition(() => { updateChildren(1); - } + }); // Partially render the children. Only the first one. await waitFor([1]); // In an interleaved event, schedule an update on each of the children. // Including the two that haven't rendered yet. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - updateChildren(2); - }); - } else { + React.startTransition(() => { updateChildren(2); - } + }); // We should continue rendering without including the interleaved updates. await waitForPaint([1, 1]); @@ -94,7 +86,7 @@ describe('ReactInterleavedUpdates', () => { expect(root).toMatchRenderedOutput('222'); }); - // @gate !enableSyncDefaultUpdates + // @gate forceConcurrentByDefaultForTesting test('low priority update during an interleaved event is not processed during the current render', async () => { // Same as previous test, but the interleaved update is lower priority than // the in-progress render. diff --git a/packages/react-reconciler/src/__tests__/ReactNewContext-test.js b/packages/react-reconciler/src/__tests__/ReactNewContext-test.js index b6be6309e00c1..288eb5734d359 100644 --- a/packages/react-reconciler/src/__tests__/ReactNewContext-test.js +++ b/packages/react-reconciler/src/__tests__/ReactNewContext-test.js @@ -885,13 +885,9 @@ describe('ReactNewContext', () => { ); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); // Render past the Provider, but don't commit yet await waitFor(['Foo']); @@ -934,13 +930,9 @@ describe('ReactNewContext', () => { ); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitForAll(['Foo', 'Foo']); // Get a new copy of ReactNoop diff --git a/packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js b/packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js index f67e2549862bd..17067638ac811 100644 --- a/packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js @@ -109,13 +109,9 @@ describe('ReactSchedulerIntegration', () => { scheduleCallback(NormalPriority, () => Scheduler.log('C')); // Schedule a React render. React will request a paint after committing it. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render('Update'); - }); - } else { + React.startTransition(() => { root.render('Update'); - } + }); // Perform just a little bit of work. By now, the React task will have // already been scheduled, behind A, B, and C. diff --git a/packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js index aff316ae10965..6e347b900f655 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js @@ -224,19 +224,7 @@ describe('ReactSuspense', () => { expect(root).toMatchRenderedOutput('Initial'); // The update will suspend. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.update( - <> - }> - - - - - , - ); - }); - } else { + React.startTransition(() => { root.update( <> }> @@ -246,7 +234,7 @@ describe('ReactSuspense', () => { , ); - } + }); // Yield past the Suspense boundary but don't complete the last sibling. await waitFor(['Suspend!', 'Loading...', 'After Suspense']); @@ -339,7 +327,7 @@ describe('ReactSuspense', () => { expect(root).toMatchRenderedOutput('AB'); }); - // @gate !enableSyncDefaultUpdates + // @gate forceConcurrentByDefaultForTesting it( 'interrupts current render when something suspends with a ' + "delay and we've already skipped over a lower priority update in " + diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js index bbb0b2912b1cc..42e758b4da8df 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js @@ -2497,13 +2497,9 @@ describe('ReactSuspenseList', () => { await act(async () => { // Add a few items at the end. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - updateLowPri(true); - }); - } else { + React.startTransition(() => { updateLowPri(true); - } + }); // Flush partially through. await waitFor(['B', 'C']); @@ -2639,13 +2635,9 @@ describe('ReactSuspenseList', () => { ); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitFor(['App', 'First Pass A', 'Mount A', 'A']); expect(ReactNoop).toMatchRenderedOutput(A); @@ -2707,13 +2699,9 @@ describe('ReactSuspenseList', () => { ); } - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitFor([ 'App', diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js index 1b05f8a2f4f50..d93c8bcf606ab 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js @@ -681,35 +681,23 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Schedule an update at several distinct expiration times await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); Scheduler.unstable_advanceTime(1000); await waitFor(['Sibling']); interrupt(); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); Scheduler.unstable_advanceTime(1000); await waitFor(['Sibling']); interrupt(); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); Scheduler.unstable_advanceTime(1000); await waitFor(['Sibling']); interrupt(); @@ -865,18 +853,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { ); await waitForAll([]); expect(root).toMatchRenderedOutput(null); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render( - <> - }> - - - - , - ); - }); - } else { + React.startTransition(() => { root.render( <> }> @@ -885,7 +862,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { , ); - } + }); await waitFor(['Suspend! [Async]']); await resolveText('Async'); @@ -2256,26 +2233,26 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll(['Foo', 'A']); expect(ReactNoop).toMatchRenderedOutput(); - if (gate(flags => flags.enableSyncDefaultUpdates)) { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { + ReactNoop.render(); + } else { React.startTransition(() => { ReactNoop.render(); }); - } else { - ReactNoop.render(); } await waitForAll(['Foo', 'A', 'Suspend! [B]', 'Loading B...']); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - // Transitions never fall back. - expect(ReactNoop).toMatchRenderedOutput(); - } else { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { expect(ReactNoop).toMatchRenderedOutput( <> , ); + } else { + // Transitions never fall back. + expect(ReactNoop).toMatchRenderedOutput(); } }); @@ -2301,13 +2278,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { await waitForAll(['Foo', 'A']); expect(ReactNoop).toMatchRenderedOutput(); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render(); - }); - } else { + React.startTransition(() => { ReactNoop.render(); - } + }); await waitForAll([ 'Foo', @@ -2322,12 +2295,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { Scheduler.unstable_advanceTime(600); await advanceTimers(600); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - // Transitions never fall back. - expect(ReactNoop).toMatchRenderedOutput(); - } else { - expect(ReactNoop).toMatchRenderedOutput(); - } + expect(ReactNoop).toMatchRenderedOutput(); }); describe('startTransition', () => { @@ -3537,7 +3505,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { }); // @gate enableLegacyCache - // @gate !enableSyncDefaultUpdates + // @gate forceConcurrentByDefaultForTesting it('regression: ping at high priority causes update to be dropped', async () => { const {useState, useTransition} = React; diff --git a/packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js b/packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js index 4ae03ac8250ca..73a4c557ee1e1 100644 --- a/packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js +++ b/packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js @@ -221,27 +221,7 @@ describe('useMutableSource', () => { const mutableSource = createMutableSource(source, param => param.version); await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - , - () => Scheduler.log('Sync effect'), - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> { , () => Scheduler.log('Sync effect'), ); - } + }); + // Do enough work to read from one component await waitFor(['a:one']); @@ -456,13 +437,9 @@ describe('useMutableSource', () => { // Changing values should schedule an update with React. // Start working on this update but don't finish it. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - source.value = 'two'; - }); - } else { + React.startTransition(() => { source.value = 'two'; - } + }); await waitFor(['a:two']); // Re-renders that occur before the update is processed @@ -720,33 +697,7 @@ describe('useMutableSource', () => { // Because the store has not changed yet, there are no pending updates, // so it is considered safe to read from when we start this render. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - - , - () => Scheduler.log('Sync effect'), - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> { , () => Scheduler.log('Sync effect'), ); - } + }); + await waitFor(['a:a:one', 'b:b:one']); // Mutating the source should trigger a tear detection on the next read, @@ -856,26 +808,7 @@ describe('useMutableSource', () => { await act(async () => { // Start a render that uses the mutable source. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> { /> , ); - } + }); + await waitFor(['a:one']); // Mutate source @@ -1524,17 +1458,7 @@ describe('useMutableSource', () => { expect(root).toMatchRenderedOutput('a0'); await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render( - <> - - - - , - ); - }); - } else { + React.startTransition(() => { root.render( <> @@ -1542,7 +1466,7 @@ describe('useMutableSource', () => { , ); - } + }); await waitFor(['a0', 'b0']); // Mutate in an event. This schedules a subscription update on a, which @@ -1676,13 +1600,9 @@ describe('useMutableSource', () => { await act(async () => { // Switch the parent and the child to read using the same config - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.render(); - }); - } else { + React.startTransition(() => { root.render(); - } + }); // Start rendering the parent, but yield before rendering the child await waitFor(['Parent: 2']); @@ -1693,21 +1613,7 @@ describe('useMutableSource', () => { source.valueB = '3'; }); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - // In default sync mode, all of the updates flush sync. - await waitFor([ - // The partial render completes - 'Child: 2', - 'Commit: 2, 2', - 'Parent: 3', - 'Child: 3', - ]); - - await waitForAll([ - // Now finish the rest of the update - 'Commit: 3, 3', - ]); - } else { + if (gate(flags => flags.forceConcurrentByDefaultForTesting)) { await waitFor([ // The partial render completes 'Child: 2', @@ -1727,6 +1633,20 @@ describe('useMutableSource', () => { 'Child: 3', 'Commit: 3, 3', ]); + } else { + // In default sync mode, all of the updates flush sync. + await waitFor([ + // The partial render completes + 'Child: 2', + 'Commit: 2, 2', + 'Parent: 3', + 'Child: 3', + ]); + + await waitForAll([ + // Now finish the rest of the update + 'Commit: 3, 3', + ]); } }); }); @@ -1843,26 +1763,7 @@ describe('useMutableSource', () => { await act(async () => { // Start a render that uses the mutable source. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> { /> , ); - } + }); + await waitFor(['a:one']); const PrevScheduler = Scheduler; @@ -1924,26 +1826,7 @@ describe('useMutableSource', () => { await act(async () => { // Start a render that uses the mutable source. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactNoop.render( - <> - - - , - ); - }); - } else { + React.startTransition(() => { ReactNoop.render( <> { /> , ); - } + }); + await waitFor(['a:one']); const PrevScheduler = Scheduler; diff --git a/packages/react-reconciler/src/__tests__/useMutableSourceHydration-test.js b/packages/react-reconciler/src/__tests__/useMutableSourceHydration-test.js index 87a9d2ea4fb5f..adf98fb4ede9a 100644 --- a/packages/react-reconciler/src/__tests__/useMutableSourceHydration-test.js +++ b/packages/react-reconciler/src/__tests__/useMutableSourceHydration-test.js @@ -260,23 +260,15 @@ describe('useMutableSourceHydration', () => { await expect(async () => { await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactDOMClient.hydrateRoot(container, , { - mutableSources: [mutableSource], - onRecoverableError(error) { - Scheduler.log('Log error: ' + error.message); - }, - }); - }); - } else { + React.startTransition(() => { ReactDOMClient.hydrateRoot(container, , { mutableSources: [mutableSource], onRecoverableError(error) { Scheduler.log('Log error: ' + error.message); }, }); - } + }); + await waitFor(['a:one']); source.value = 'two'; }); diff --git a/packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js b/packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js index 3e29b28500003..468f62d39a722 100644 --- a/packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js +++ b/packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js @@ -95,17 +95,11 @@ describe('ReactTestRendererAsync', () => { } let renderer; - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - renderer = ReactTestRenderer.create(, { - unstable_isConcurrent: true, - }); - }); - } else { + React.startTransition(() => { renderer = ReactTestRenderer.create(, { unstable_isConcurrent: true, }); - } + }); // Flush the first two siblings await waitFor(['A:1', 'B:1']); @@ -141,17 +135,11 @@ describe('ReactTestRendererAsync', () => { } let renderer; - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - renderer = ReactTestRenderer.create(, { - unstable_isConcurrent: true, - }); - }); - } else { + React.startTransition(() => { renderer = ReactTestRenderer.create(, { unstable_isConcurrent: true, }); - } + }); // Flush the some of the changes, but don't commit await waitFor(['A:1']); diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index d728d002587b7..25386df33abcf 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -206,19 +206,7 @@ describe(`onRender`, () => { return null; }; - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactTestRenderer.create( - - - - , - { - unstable_isConcurrent: true, - }, - ); - }); - } else { + React.startTransition(() => { ReactTestRenderer.create( @@ -228,7 +216,7 @@ describe(`onRender`, () => { unstable_isConcurrent: true, }, ); - } + }); // Times are logged until a render is committed. await waitFor(['first']); @@ -758,17 +746,7 @@ describe(`onRender`, () => { Scheduler.unstable_advanceTime(5); // 0 -> 5 // Render partially, but run out of time before completing. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactTestRenderer.create( - - - - , - {unstable_isConcurrent: true}, - ); - }); - } else { + React.startTransition(() => { ReactTestRenderer.create( @@ -776,7 +754,8 @@ describe(`onRender`, () => { , {unstable_isConcurrent: true}, ); - } + }); + await waitFor(['Yield:2']); expect(callback).toHaveBeenCalledTimes(0); @@ -805,20 +784,7 @@ describe(`onRender`, () => { // Render partially, but don't finish. // This partial render should take 5ms of simulated time. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - ReactTestRenderer.create( - - - - - - - , - {unstable_isConcurrent: true}, - ); - }); - } else { + React.startTransition(() => { ReactTestRenderer.create( @@ -829,7 +795,8 @@ describe(`onRender`, () => { , {unstable_isConcurrent: true}, ); - } + }); + await waitFor(['Yield:5']); expect(callback).toHaveBeenCalledTimes(0); @@ -871,17 +838,7 @@ describe(`onRender`, () => { // Render a partially update, but don't finish. // This partial render should take 10ms of simulated time. let renderer; - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - renderer = ReactTestRenderer.create( - - - - , - {unstable_isConcurrent: true}, - ); - }); - } else { + React.startTransition(() => { renderer = ReactTestRenderer.create( @@ -889,7 +846,8 @@ describe(`onRender`, () => { , {unstable_isConcurrent: true}, ); - } + }); + await waitFor(['Yield:10']); expect(callback).toHaveBeenCalledTimes(0); @@ -958,17 +916,7 @@ describe(`onRender`, () => { // Render a partially update, but don't finish. // This partial render should take 3ms of simulated time. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - renderer.update( - - - - - , - ); - }); - } else { + React.startTransition(() => { renderer.update( @@ -976,7 +924,8 @@ describe(`onRender`, () => { , ); - } + }); + await waitFor(['Yield:3']); expect(callback).toHaveBeenCalledTimes(0); @@ -1078,13 +1027,10 @@ describe(`onRender`, () => { // Render a partially update, but don't finish. // This partial render will take 10ms of actual render time. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - first.setState({renderTime: 10}); - }); - } else { + React.startTransition(() => { first.setState({renderTime: 10}); - } + }); + await waitFor(['FirstComponent:10']); expect(callback).toHaveBeenCalledTimes(0); diff --git a/packages/react/src/__tests__/ReactProfilerDevToolsIntegration-test.internal.js b/packages/react/src/__tests__/ReactProfilerDevToolsIntegration-test.internal.js index 218cd3a2daabb..d28e2ad8de64a 100644 --- a/packages/react/src/__tests__/ReactProfilerDevToolsIntegration-test.internal.js +++ b/packages/react/src/__tests__/ReactProfilerDevToolsIntegration-test.internal.js @@ -161,13 +161,9 @@ describe('ReactProfiler DevTools integration', () => { // for updates. Scheduler.unstable_advanceTime(10000); // Schedule an update. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - root.update(); - }); - } else { + React.startTransition(() => { root.update(); - } + }); // Update B should not instantly expire. await waitFor([]); diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 791ed622a0ff6..7cb339c83cc85 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -145,12 +145,11 @@ export const disableLegacyContext = false; export const enableUseRefAccessWarning = false; // Enables time slicing for updates that aren't wrapped in startTransition. -export const enableSyncDefaultUpdates = true; +export const forceConcurrentByDefaultForTesting = false; export const enableUnifiedSyncLane = __EXPERIMENTAL__; -// Adds an opt-in to time slicing for updates that aren't wrapped in -// startTransition. Only relevant when enableSyncDefaultUpdates is disabled. +// Adds an opt-in to time slicing for updates that aren't wrapped in startTransition. export const allowConcurrentByDefault = false; // ----------------------------------------------------------------------------- diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 239228901600d..e96ce86b00286 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -66,7 +66,7 @@ export const createRootStrictEffectsByDefault = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableLazyContextPropagation = false; export const enableLegacyHidden = true; -export const enableSyncDefaultUpdates = true; +export const forceConcurrentByDefaultForTesting = false; export const enableUnifiedSyncLane = false; export const allowConcurrentByDefault = true; export const enableCustomElementPropertySupport = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 326f7d5385b46..97556a05514ce 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -53,7 +53,7 @@ export const enableUseRefAccessWarning = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableLazyContextPropagation = false; export const enableLegacyHidden = false; -export const enableSyncDefaultUpdates = true; +export const forceConcurrentByDefaultForTesting = false; export const enableUnifiedSyncLane = false; export const allowConcurrentByDefault = false; export const enableCustomElementPropertySupport = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index bbc988448c543..6437b4de07086 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -53,7 +53,7 @@ export const enableUseRefAccessWarning = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableLazyContextPropagation = false; export const enableLegacyHidden = false; -export const enableSyncDefaultUpdates = true; +export const forceConcurrentByDefaultForTesting = false; export const enableUnifiedSyncLane = __EXPERIMENTAL__; export const allowConcurrentByDefault = false; export const enableCustomElementPropertySupport = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js index 751695f8eb0b1..55535ce5e464d 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js @@ -52,7 +52,7 @@ export const enableUseRefAccessWarning = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableLazyContextPropagation = false; export const enableLegacyHidden = false; -export const enableSyncDefaultUpdates = true; +export const forceConcurrentByDefaultForTesting = false; export const enableUnifiedSyncLane = false; export const allowConcurrentByDefault = true; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 31d2292dcf4e8..1df2ff6b9eeea 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -53,7 +53,7 @@ export const enableUseRefAccessWarning = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableLazyContextPropagation = false; export const enableLegacyHidden = false; -export const enableSyncDefaultUpdates = true; +export const forceConcurrentByDefaultForTesting = false; export const enableUnifiedSyncLane = false; export const allowConcurrentByDefault = true; export const enableCustomElementPropertySupport = false; diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js index 827d1413b5949..58cfcdfff4214 100644 --- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js @@ -20,7 +20,7 @@ export const enableUseRefAccessWarning = __VARIANT__; export const enableProfilerNestedUpdateScheduledHook = __VARIANT__; export const disableSchedulerTimeoutInWorkLoop = __VARIANT__; export const enableLazyContextPropagation = __VARIANT__; -export const enableSyncDefaultUpdates = __VARIANT__; +export const forceConcurrentByDefaultForTesting = __VARIANT__; export const enableUnifiedSyncLane = __VARIANT__; export const enableTransitionTracing = __VARIANT__; export const enableCustomElementPropertySupport = __VARIANT__; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 88951390b16ab..426a9ec8013e6 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -105,7 +105,7 @@ export const enableUseMutableSource = true; export const useModernStrictMode = false; export const enableFizzExternalRuntime = true; -export const enableSyncDefaultUpdates = true; +export const forceConcurrentByDefaultForTesting = false; // Flow magic to verify the exports of this file match the original version. ((((null: any): ExportsType): FeatureFlagsType): ExportsType); diff --git a/packages/use-subscription/src/__tests__/useSubscription-test.js b/packages/use-subscription/src/__tests__/useSubscription-test.js index f3d8d3905320a..19eba0a15be8e 100644 --- a/packages/use-subscription/src/__tests__/useSubscription-test.js +++ b/packages/use-subscription/src/__tests__/useSubscription-test.js @@ -339,13 +339,9 @@ describe('useSubscription', () => { // Start React update, but don't finish await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - renderer.update(); - }); - } else { + React.startTransition(() => { renderer.update(); - } + }); await waitFor(['Child: b-0']); expect(log).toEqual(['Parent.componentDidMount']); @@ -447,13 +443,9 @@ describe('useSubscription', () => { // Start React update, but don't finish await act(async () => { - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - renderer.update(); - }); - } else { + React.startTransition(() => { renderer.update(); - } + }); await waitFor(['Child: b-0']); expect(log).toEqual([]); @@ -632,21 +624,13 @@ describe('useSubscription', () => { // Interrupt with a second mutation "C" -> "D". // This update will not be eagerly evaluated, // but useSubscription() should eagerly close over the updated value to avoid tearing. - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - mutate('C'); - }); - } else { + React.startTransition(() => { mutate('C'); - } + }); await waitFor(['render:first:C', 'render:second:C']); - if (gate(flags => flags.enableSyncDefaultUpdates)) { - React.startTransition(() => { - mutate('D'); - }); - } else { + React.startTransition(() => { mutate('D'); - } + }); await waitForAll(['render:first:D', 'render:second:D']); // No more pending updates diff --git a/scripts/jest/setupTests.www.js b/scripts/jest/setupTests.www.js index a51b5838ee439..2fc6da49d55ed 100644 --- a/scripts/jest/setupTests.www.js +++ b/scripts/jest/setupTests.www.js @@ -9,7 +9,7 @@ jest.mock('shared/ReactFeatureFlags', () => { const actual = jest.requireActual('shared/forks/ReactFeatureFlags.www'); // This flag is only used by tests, it should never be set elsewhere. - actual.enableSyncDefaultUpdates = __VARIANT__; + actual.forceConcurrentByDefaultForTesting = !__VARIANT__; return actual; });