diff --git a/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js b/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js index 9b7b939bcf912..8d4f4c553a227 100644 --- a/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js +++ b/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js @@ -16,6 +16,7 @@ import {__interactionsRef} from 'scheduler/tracing'; import { enableSchedulerTracing, decoupleUpdatePriorityFromScheduler, + enableSyncMicroTasks, } from 'shared/ReactFeatureFlags'; import invariant from 'shared/invariant'; import { @@ -145,12 +146,13 @@ export function scheduleSyncCallback(callback: SchedulerCallback) { // the next tick, or earlier if something calls `flushSyncCallbackQueue`. if (syncQueue === null) { syncQueue = [callback]; - // Flush the queue in the next tick, at the earliest. - // TODO: Figure out how to remove this It's only here as a last resort if we - // forget to explicitly flush. - if (supportsMicrotasks) { + if (enableSyncMicroTasks && supportsMicrotasks) { + // Flush the queue in a microtask. scheduleMicrotask(flushSyncCallbackQueueImpl); } else { + // Flush the queue in the next tick, at the earliest. + // TODO: Figure out how to remove this It's only here as a last resort if we + // forget to explicitly flush. immediateQueueCallbackNode = Scheduler_scheduleCallback( Scheduler_ImmediatePriority, flushSyncCallbackQueueImpl, diff --git a/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js b/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js index 51961a4ebd2b4..96a1077b380df 100644 --- a/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js +++ b/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js @@ -16,6 +16,7 @@ import {__interactionsRef} from 'scheduler/tracing'; import { enableSchedulerTracing, decoupleUpdatePriorityFromScheduler, + enableSyncMicroTasks, } from 'shared/ReactFeatureFlags'; import invariant from 'shared/invariant'; import { @@ -145,12 +146,13 @@ export function scheduleSyncCallback(callback: SchedulerCallback) { // the next tick, or earlier if something calls `flushSyncCallbackQueue`. if (syncQueue === null) { syncQueue = [callback]; - // Flush the queue in the next tick, at the earliest. - // TODO: Figure out how to remove this It's only here as a last resort if we - // forget to explicitly flush. - if (supportsMicrotasks) { + if (enableSyncMicroTasks && supportsMicrotasks) { + // Flush the queue in a microtask. scheduleMicrotask(flushSyncCallbackQueueImpl); } else { + // Flush the queue in the next tick, at the earliest. + // TODO: Figure out how to remove this It's only here as a last resort if we + // forget to explicitly flush. immediateQueueCallbackNode = Scheduler_scheduleCallback( Scheduler_ImmediatePriority, flushSyncCallbackQueueImpl, diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js index 4e42e60ebac94..4c7d308a9c909 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js @@ -1810,18 +1810,10 @@ describe('ReactHooksWithNoopRenderer', () => { await act(async () => { ReactNoop.renderLegacySyncRoot(); - if (gate(flags => flags.enableDiscreteEventMicroTasks)) { - // Flush microtasks. - await null; - - // Even in legacy mode, effects are deferred until after paint - expect(Scheduler).toHaveYielded(['Count: (empty)']); - expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); - } else { - // Even in legacy mode, effects are deferred until after paint - expect(Scheduler).toFlushAndYieldThrough(['Count: (empty)']); - expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); - } + // Even in legacy mode, effects are deferred until after paint + ReactNoop.flushSync(); + expect(Scheduler).toHaveYielded(['Count: (empty)']); + expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); }); // effects get forced on exiting act() diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index f568191681b67..613fe89d63279 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -1400,6 +1400,10 @@ describe('ReactIncrementalErrorHandling', () => { 'BrokenRenderAndUnmount componentWillUnmount', ]); expect(ReactNoop.getChildren()).toEqual([]); + + expect(() => { + ReactNoop.flushSync(); + }).toThrow('One does not simply unmount me.'); }); it('does not interrupt unmounting if detaching a ref throws', () => { diff --git a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js index bbd55f168ff42..b3f14e6ad1efc 100644 --- a/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js +++ b/packages/react-reconciler/src/__tests__/ReactOffscreen-test.js @@ -98,16 +98,11 @@ describe('ReactOffscreen', () => { , ); - if (gate(flags => flags.enableDiscreteEventMicroTasks)) { - // Flush microtasks. - await null; - // Should not defer the hidden tree - expect(Scheduler).toHaveYielded(['A', 'Outside']); - } else { - // Should not defer the hidden tree - expect(Scheduler).toFlushUntilNextPaint(['A', 'Outside']); - } + ReactNoop.flushSync(); + + // Should not defer the hidden tree + expect(Scheduler).toHaveYielded(['A', 'Outside']); }); expect(root).toMatchRenderedOutput( <> diff --git a/packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js b/packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js index a1ebb3065c957..ab9995d01cb5f 100644 --- a/packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js +++ b/packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js @@ -569,17 +569,11 @@ describe( ReactNoop.render(); }); - if (gate(flags => flags.enableDiscreteEventMicroTasks)) { - await null; - - // Because the render expired, React should finish the tree without - // consulting `shouldYield` again - expect(Scheduler).toHaveYielded(['B', 'C']); - } else { - // Because the render expired, React should finish the tree without - // consulting `shouldYield` again - expect(Scheduler).toFlushExpired(['B', 'C']); - } + ReactNoop.flushSync(); + + // Because the render expired, React should finish the tree without + // consulting `shouldYield` again + expect(Scheduler).toHaveYielded(['B', 'C']); }); }); }, diff --git a/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js index 15f7eba92e51b..b6e34104ad61f 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js @@ -331,14 +331,10 @@ describe('ReactSuspensePlaceholder', () => { jest.advanceTimersByTime(1000); expect(Scheduler).toHaveYielded(['Promise resolved [Loaded]']); - if (gate(flags => flags.enableDiscreteEventMicroTasks)) { - // Flush microtasks - await null; - - expect(Scheduler).toHaveYielded(['Loaded']); - } else { - expect(Scheduler).toFlushExpired(['Loaded']); - } + + ReactNoop.flushSync(); + + expect(Scheduler).toHaveYielded(['Loaded']); expect(ReactNoop).toMatchRenderedOutput('LoadedText'); expect(onRender).toHaveBeenCalledTimes(2); @@ -435,14 +431,9 @@ describe('ReactSuspensePlaceholder', () => { expect(Scheduler).toHaveYielded(['Promise resolved [Loaded]']); - if (gate(flags => flags.enableDiscreteEventMicroTasks)) { - // Flush microtasks - await null; + ReactNoop.flushSync(); - expect(Scheduler).toHaveYielded(['Loaded']); - } else { - expect(Scheduler).toFlushExpired(['Loaded']); - } + expect(Scheduler).toHaveYielded(['Loaded']); expect(ReactNoop).toMatchRenderedOutput('LoadedNew'); expect(onRender).toHaveBeenCalledTimes(4); diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 3d0362f4b3fcd..56ad7fa587afd 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -151,4 +151,6 @@ export const enableNonInterruptingNormalPri = false; export const enableDiscreteEventMicroTasks = false; +export const enableSyncMicroTasks = false; + export const enableNativeEventPriorityInference = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index f97f4f428c181..790887b7e7cee 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -59,6 +59,7 @@ export const enableRecursiveCommitTraversal = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableNonInterruptingNormalPri = false; export const enableDiscreteEventMicroTasks = false; +export const enableSyncMicroTasks = false; export const enableNativeEventPriorityInference = false; // Flow magic to verify the exports of this file match the original version. diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 9d160790b3fec..8b54ff76d2f6e 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -58,6 +58,7 @@ export const enableRecursiveCommitTraversal = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableNonInterruptingNormalPri = false; export const enableDiscreteEventMicroTasks = false; +export const enableSyncMicroTasks = false; export const enableNativeEventPriorityInference = false; // Flow magic to verify the exports of this file match the original version. diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 52990e5ec7b71..78f1ed1b9a098 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -58,6 +58,7 @@ export const enableRecursiveCommitTraversal = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableNonInterruptingNormalPri = false; export const enableDiscreteEventMicroTasks = false; +export const enableSyncMicroTasks = false; export const enableNativeEventPriorityInference = false; // Flow magic to verify the exports of this file match the original version. diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js index 3c739b7bccb39..c25b8e6e04029 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js @@ -58,6 +58,7 @@ export const enableRecursiveCommitTraversal = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableNonInterruptingNormalPri = false; export const enableDiscreteEventMicroTasks = false; +export const enableSyncMicroTasks = false; export const enableNativeEventPriorityInference = false; // Flow magic to verify the exports of this file match the original version. diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index fb2211763c03d..ff5c7c43d0864 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -58,6 +58,7 @@ export const enableRecursiveCommitTraversal = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableNonInterruptingNormalPri = false; export const enableDiscreteEventMicroTasks = false; +export const enableSyncMicroTasks = false; export const enableNativeEventPriorityInference = false; // Flow magic to verify the exports of this file match the original version. diff --git a/packages/shared/forks/ReactFeatureFlags.testing.js b/packages/shared/forks/ReactFeatureFlags.testing.js index 34e6d5315742f..696de3ce78dd7 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.js @@ -58,6 +58,7 @@ export const enableRecursiveCommitTraversal = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableNonInterruptingNormalPri = false; export const enableDiscreteEventMicroTasks = false; +export const enableSyncMicroTasks = false; export const enableNativeEventPriorityInference = false; // Flow magic to verify the exports of this file match the original version. diff --git a/packages/shared/forks/ReactFeatureFlags.testing.www.js b/packages/shared/forks/ReactFeatureFlags.testing.www.js index 4f0c56733eafd..d33d0683c15a7 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.www.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.www.js @@ -58,6 +58,7 @@ export const enableRecursiveCommitTraversal = false; export const disableSchedulerTimeoutInWorkLoop = false; export const enableNonInterruptingNormalPri = false; export const enableDiscreteEventMicroTasks = false; +export const enableSyncMicroTasks = false; export const enableNativeEventPriorityInference = false; // Flow magic to verify the exports of this file match the original version. diff --git a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js index b6e1d4260cc4a..b43f53fbfae19 100644 --- a/packages/shared/forks/ReactFeatureFlags.www-dynamic.js +++ b/packages/shared/forks/ReactFeatureFlags.www-dynamic.js @@ -57,4 +57,5 @@ export const enableProfilerNestedUpdateScheduledHook = __VARIANT__; export const disableSchedulerTimeoutInWorkLoop = __VARIANT__; export const enableNonInterruptingNormalPri = __VARIANT__; export const enableDiscreteEventMicroTasks = __VARIANT__; +export const enableSyncMicroTasks = __VARIANT__; export const enableNativeEventPriorityInference = __VARIANT__; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 924fd6ea9e5bd..21cc7979df98c 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -33,6 +33,7 @@ export const { disableSchedulerTimeoutInWorkLoop, enableNonInterruptingNormalPri, enableDiscreteEventMicroTasks, + enableSyncMicroTasks, enableNativeEventPriorityInference, } = dynamicFeatureFlags;