From 32ff4286872d1a6bb8ce71730064f60ebbdd1509 Mon Sep 17 00:00:00 2001 From: Ricky Date: Thu, 6 Aug 2020 12:47:32 -0400 Subject: [PATCH] Add feature flag for setting update lane priority (#19401) * Add feature flag for setting update lane priority * Remove second feature flag * Refactor feature flag locations * Add missing else --- .../src/events/ReactDOMEventListener.js | 30 +++- .../src/ReactFiberHooks.new.js | 83 ++++++--- .../src/ReactFiberHooks.old.js | 83 ++++++--- .../src/ReactFiberWorkLoop.new.js | 167 ++++++++++++------ .../src/ReactFiberWorkLoop.old.js | 167 ++++++++++++------ .../src/SchedulerWithReactIntegration.new.js | 86 ++++++--- .../src/SchedulerWithReactIntegration.old.js | 86 ++++++--- 7 files changed, 479 insertions(+), 223 deletions(-) diff --git a/packages/react-dom/src/events/ReactDOMEventListener.js b/packages/react-dom/src/events/ReactDOMEventListener.js index 6f0b981ab95df..d92c6d5eb582a 100644 --- a/packages/react-dom/src/events/ReactDOMEventListener.js +++ b/packages/react-dom/src/events/ReactDOMEventListener.js @@ -38,7 +38,10 @@ import { import getEventTarget from './getEventTarget'; import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree'; -import {enableLegacyFBSupport} from 'shared/ReactFeatureFlags'; +import { + enableLegacyFBSupport, + decoupleUpdatePriorityFromScheduler, +} from 'shared/ReactFeatureFlags'; import { UserBlockingEvent, ContinuousEvent, @@ -147,10 +150,25 @@ function dispatchUserBlockingUpdate( container, nativeEvent, ) { - // TODO: Double wrapping is necessary while we decouple Scheduler priority. - const previousPriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(InputContinuousLanePriority); + if (decoupleUpdatePriorityFromScheduler) { + const previousPriority = getCurrentUpdateLanePriority(); + try { + // TODO: Double wrapping is necessary while we decouple Scheduler priority. + setCurrentUpdateLanePriority(InputContinuousLanePriority); + runWithPriority( + UserBlockingPriority, + dispatchEvent.bind( + null, + domEventName, + eventSystemFlags, + container, + nativeEvent, + ), + ); + } finally { + setCurrentUpdateLanePriority(previousPriority); + } + } else { runWithPriority( UserBlockingPriority, dispatchEvent.bind( @@ -161,8 +179,6 @@ function dispatchUserBlockingUpdate( nativeEvent, ), ); - } finally { - setCurrentUpdateLanePriority(previousPriority); } } diff --git a/packages/react-reconciler/src/ReactFiberHooks.new.js b/packages/react-reconciler/src/ReactFiberHooks.new.js index 0f1309ff70b02..99f367f606873 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.new.js +++ b/packages/react-reconciler/src/ReactFiberHooks.new.js @@ -26,6 +26,7 @@ import { enableDebugTracing, enableSchedulingProfiler, enableNewReconciler, + decoupleUpdatePriorityFromScheduler, } from 'shared/ReactFeatureFlags'; import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode'; @@ -1506,34 +1507,64 @@ function rerenderDeferredValue( function startTransition(setPending, config, callback) { const priorityLevel = getCurrentPriorityLevel(); - const previousLanePriority = getCurrentUpdateLanePriority(); - setCurrentUpdateLanePriority( - higherLanePriority(previousLanePriority, InputContinuousLanePriority), - ); - runWithPriority( - priorityLevel < UserBlockingPriority ? UserBlockingPriority : priorityLevel, - () => { - setPending(true); - }, - ); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + setCurrentUpdateLanePriority( + higherLanePriority(previousLanePriority, InputContinuousLanePriority), + ); - // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition. - setCurrentUpdateLanePriority(DefaultLanePriority); + runWithPriority( + priorityLevel < UserBlockingPriority + ? UserBlockingPriority + : priorityLevel, + () => { + setPending(true); + }, + ); - runWithPriority( - priorityLevel > NormalPriority ? NormalPriority : priorityLevel, - () => { - const previousConfig = ReactCurrentBatchConfig.suspense; - ReactCurrentBatchConfig.suspense = config === undefined ? null : config; - try { - setPending(false); - callback(); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - ReactCurrentBatchConfig.suspense = previousConfig; - } - }, - ); + // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition. + setCurrentUpdateLanePriority(DefaultLanePriority); + + runWithPriority( + priorityLevel > NormalPriority ? NormalPriority : priorityLevel, + () => { + const previousConfig = ReactCurrentBatchConfig.suspense; + ReactCurrentBatchConfig.suspense = config === undefined ? null : config; + try { + setPending(false); + callback(); + } finally { + if (decoupleUpdatePriorityFromScheduler) { + setCurrentUpdateLanePriority(previousLanePriority); + } + ReactCurrentBatchConfig.suspense = previousConfig; + } + }, + ); + } else { + runWithPriority( + priorityLevel < UserBlockingPriority + ? UserBlockingPriority + : priorityLevel, + () => { + setPending(true); + }, + ); + + runWithPriority( + priorityLevel > NormalPriority ? NormalPriority : priorityLevel, + () => { + const previousConfig = ReactCurrentBatchConfig.suspense; + ReactCurrentBatchConfig.suspense = config === undefined ? null : config; + try { + setPending(false); + callback(); + } finally { + ReactCurrentBatchConfig.suspense = previousConfig; + } + }, + ); + } } function mountTransition( diff --git a/packages/react-reconciler/src/ReactFiberHooks.old.js b/packages/react-reconciler/src/ReactFiberHooks.old.js index 328ae20d67546..380524df9aad6 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.old.js +++ b/packages/react-reconciler/src/ReactFiberHooks.old.js @@ -26,6 +26,7 @@ import { enableDebugTracing, enableSchedulingProfiler, enableNewReconciler, + decoupleUpdatePriorityFromScheduler, } from 'shared/ReactFeatureFlags'; import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode'; @@ -1505,34 +1506,64 @@ function rerenderDeferredValue( function startTransition(setPending, config, callback) { const priorityLevel = getCurrentPriorityLevel(); - const previousLanePriority = getCurrentUpdateLanePriority(); - setCurrentUpdateLanePriority( - higherLanePriority(previousLanePriority, InputContinuousLanePriority), - ); - runWithPriority( - priorityLevel < UserBlockingPriority ? UserBlockingPriority : priorityLevel, - () => { - setPending(true); - }, - ); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + setCurrentUpdateLanePriority( + higherLanePriority(previousLanePriority, InputContinuousLanePriority), + ); - // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition. - setCurrentUpdateLanePriority(DefaultLanePriority); + runWithPriority( + priorityLevel < UserBlockingPriority + ? UserBlockingPriority + : priorityLevel, + () => { + setPending(true); + }, + ); - runWithPriority( - priorityLevel > NormalPriority ? NormalPriority : priorityLevel, - () => { - const previousConfig = ReactCurrentBatchConfig.suspense; - ReactCurrentBatchConfig.suspense = config === undefined ? null : config; - try { - setPending(false); - callback(); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - ReactCurrentBatchConfig.suspense = previousConfig; - } - }, - ); + // If there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition. + setCurrentUpdateLanePriority(DefaultLanePriority); + + runWithPriority( + priorityLevel > NormalPriority ? NormalPriority : priorityLevel, + () => { + const previousConfig = ReactCurrentBatchConfig.suspense; + ReactCurrentBatchConfig.suspense = config === undefined ? null : config; + try { + setPending(false); + callback(); + } finally { + if (decoupleUpdatePriorityFromScheduler) { + setCurrentUpdateLanePriority(previousLanePriority); + } + ReactCurrentBatchConfig.suspense = previousConfig; + } + }, + ); + } else { + runWithPriority( + priorityLevel < UserBlockingPriority + ? UserBlockingPriority + : priorityLevel, + () => { + setPending(true); + }, + ); + + runWithPriority( + priorityLevel > NormalPriority ? NormalPriority : priorityLevel, + () => { + const previousConfig = ReactCurrentBatchConfig.suspense; + ReactCurrentBatchConfig.suspense = config === undefined ? null : config; + try { + setPending(false); + callback(); + } finally { + ReactCurrentBatchConfig.suspense = previousConfig; + } + }, + ); + } } function mountTransition( diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js index 63ffe2d356aae..9cd162cb01cf0 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js @@ -1163,13 +1163,16 @@ export function flushDiscreteUpdates() { } export function deferredUpdates(fn: () => A): A { - // TODO: Remove in favor of Scheduler.next - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(DefaultLanePriority); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority(DefaultLanePriority); + return runWithPriority(NormalSchedulerPriority, fn); + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + } + } else { return runWithPriority(NormalSchedulerPriority, fn); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); } } @@ -1225,20 +1228,35 @@ export function discreteUpdates( ): R { const prevExecutionContext = executionContext; executionContext |= DiscreteEventContext; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(InputDiscreteLanePriority); - // Should this - return runWithPriority( - UserBlockingSchedulerPriority, - fn.bind(null, a, b, c, d), - ); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - executionContext = prevExecutionContext; - if (executionContext === NoContext) { - // Flush the immediate callbacks that were scheduled during this batch - flushSyncCallbackQueue(); + + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority(InputDiscreteLanePriority); + return runWithPriority( + UserBlockingSchedulerPriority, + fn.bind(null, a, b, c, d), + ); + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + executionContext = prevExecutionContext; + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + flushSyncCallbackQueue(); + } + } + } else { + try { + return runWithPriority( + UserBlockingSchedulerPriority, + fn.bind(null, a, b, c, d), + ); + } finally { + executionContext = prevExecutionContext; + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + flushSyncCallbackQueue(); + } } } } @@ -1271,37 +1289,67 @@ export function flushSync(fn: A => R, a: A): R { return fn(a); } executionContext |= BatchedContext; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(SyncLanePriority); - if (fn) { - return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a)); - } else { - return (undefined: $FlowFixMe); + + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority(SyncLanePriority); + if (fn) { + return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a)); + } else { + return (undefined: $FlowFixMe); + } + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + executionContext = prevExecutionContext; + // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. + flushSyncCallbackQueue(); + } + } else { + try { + if (fn) { + return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a)); + } else { + return (undefined: $FlowFixMe); + } + } finally { + executionContext = prevExecutionContext; + // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. + flushSyncCallbackQueue(); } - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - executionContext = prevExecutionContext; - // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. - flushSyncCallbackQueue(); } } export function flushControlled(fn: () => mixed): void { const prevExecutionContext = executionContext; executionContext |= BatchedContext; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(SyncLanePriority); - runWithPriority(ImmediateSchedulerPriority, fn); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - executionContext = prevExecutionContext; - if (executionContext === NoContext) { - // Flush the immediate callbacks that were scheduled during this batch - flushSyncCallbackQueue(); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority(SyncLanePriority); + runWithPriority(ImmediateSchedulerPriority, fn); + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + + executionContext = prevExecutionContext; + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + flushSyncCallbackQueue(); + } + } + } else { + try { + runWithPriority(ImmediateSchedulerPriority, fn); + } finally { + executionContext = prevExecutionContext; + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + flushSyncCallbackQueue(); + } } } } @@ -2122,8 +2170,11 @@ function commitRootImpl(root, renderPriorityLevel) { } if (firstEffect !== null) { - const previousLanePriority = getCurrentUpdateLanePriority(); - setCurrentUpdateLanePriority(SyncLanePriority); + let previousLanePriority; + if (decoupleUpdatePriorityFromScheduler) { + previousLanePriority = getCurrentUpdateLanePriority(); + setCurrentUpdateLanePriority(SyncLanePriority); + } const prevExecutionContext = executionContext; executionContext |= CommitContext; @@ -2214,8 +2265,10 @@ function commitRootImpl(root, renderPriorityLevel) { } executionContext = prevExecutionContext; - // Reset the priority to the previous non-sync value. - setCurrentUpdateLanePriority(previousLanePriority); + if (decoupleUpdatePriorityFromScheduler && previousLanePriority != null) { + // Reset the priority to the previous non-sync value. + setCurrentUpdateLanePriority(previousLanePriority); + } } else { // No effects. root.current = finishedWork; @@ -2655,14 +2708,18 @@ export function flushPassiveEffects(): boolean { ? NormalSchedulerPriority : pendingPassiveEffectsRenderPriority; pendingPassiveEffectsRenderPriority = NoSchedulerPriority; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority( - schedulerPriorityToLanePriority(priorityLevel), - ); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority( + schedulerPriorityToLanePriority(priorityLevel), + ); + return runWithPriority(priorityLevel, flushPassiveEffectsImpl); + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + } + } else { return runWithPriority(priorityLevel, flushPassiveEffectsImpl); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); } } return false; diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js index 36670a257f0ec..4cb6e5093377e 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js @@ -1147,13 +1147,16 @@ export function flushDiscreteUpdates() { } export function deferredUpdates(fn: () => A): A { - // TODO: Remove in favor of Scheduler.next - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(DefaultLanePriority); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority(DefaultLanePriority); + return runWithPriority(NormalSchedulerPriority, fn); + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + } + } else { return runWithPriority(NormalSchedulerPriority, fn); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); } } @@ -1209,20 +1212,35 @@ export function discreteUpdates( ): R { const prevExecutionContext = executionContext; executionContext |= DiscreteEventContext; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(InputDiscreteLanePriority); - // Should this - return runWithPriority( - UserBlockingSchedulerPriority, - fn.bind(null, a, b, c, d), - ); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - executionContext = prevExecutionContext; - if (executionContext === NoContext) { - // Flush the immediate callbacks that were scheduled during this batch - flushSyncCallbackQueue(); + + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority(InputDiscreteLanePriority); + return runWithPriority( + UserBlockingSchedulerPriority, + fn.bind(null, a, b, c, d), + ); + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + executionContext = prevExecutionContext; + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + flushSyncCallbackQueue(); + } + } + } else { + try { + return runWithPriority( + UserBlockingSchedulerPriority, + fn.bind(null, a, b, c, d), + ); + } finally { + executionContext = prevExecutionContext; + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + flushSyncCallbackQueue(); + } } } } @@ -1255,37 +1273,67 @@ export function flushSync(fn: A => R, a: A): R { return fn(a); } executionContext |= BatchedContext; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(SyncLanePriority); - if (fn) { - return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a)); - } else { - return (undefined: $FlowFixMe); + + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority(SyncLanePriority); + if (fn) { + return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a)); + } else { + return (undefined: $FlowFixMe); + } + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + executionContext = prevExecutionContext; + // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. + flushSyncCallbackQueue(); + } + } else { + try { + if (fn) { + return runWithPriority(ImmediateSchedulerPriority, fn.bind(null, a)); + } else { + return (undefined: $FlowFixMe); + } + } finally { + executionContext = prevExecutionContext; + // Flush the immediate callbacks that were scheduled during this batch. + // Note that this will happen even if batchedUpdates is higher up + // the stack. + flushSyncCallbackQueue(); } - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - executionContext = prevExecutionContext; - // Flush the immediate callbacks that were scheduled during this batch. - // Note that this will happen even if batchedUpdates is higher up - // the stack. - flushSyncCallbackQueue(); } } export function flushControlled(fn: () => mixed): void { const prevExecutionContext = executionContext; executionContext |= BatchedContext; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority(SyncLanePriority); - runWithPriority(ImmediateSchedulerPriority, fn); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - executionContext = prevExecutionContext; - if (executionContext === NoContext) { - // Flush the immediate callbacks that were scheduled during this batch - flushSyncCallbackQueue(); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority(SyncLanePriority); + runWithPriority(ImmediateSchedulerPriority, fn); + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + + executionContext = prevExecutionContext; + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + flushSyncCallbackQueue(); + } + } + } else { + try { + runWithPriority(ImmediateSchedulerPriority, fn); + } finally { + executionContext = prevExecutionContext; + if (executionContext === NoContext) { + // Flush the immediate callbacks that were scheduled during this batch + flushSyncCallbackQueue(); + } } } } @@ -2019,8 +2067,11 @@ function commitRootImpl(root, renderPriorityLevel) { } if (firstEffect !== null) { - const previousLanePriority = getCurrentUpdateLanePriority(); - setCurrentUpdateLanePriority(SyncLanePriority); + let previousLanePriority; + if (decoupleUpdatePriorityFromScheduler) { + previousLanePriority = getCurrentUpdateLanePriority(); + setCurrentUpdateLanePriority(SyncLanePriority); + } const prevExecutionContext = executionContext; executionContext |= CommitContext; @@ -2143,8 +2194,10 @@ function commitRootImpl(root, renderPriorityLevel) { } executionContext = prevExecutionContext; - // Reset the priority to the previous non-sync value. - setCurrentUpdateLanePriority(previousLanePriority); + if (decoupleUpdatePriorityFromScheduler && previousLanePriority != null) { + // Reset the priority to the previous non-sync value. + setCurrentUpdateLanePriority(previousLanePriority); + } } else { // No effects. root.current = finishedWork; @@ -2463,14 +2516,18 @@ export function flushPassiveEffects(): boolean { ? NormalSchedulerPriority : pendingPassiveEffectsRenderPriority; pendingPassiveEffectsRenderPriority = NoSchedulerPriority; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - setCurrentUpdateLanePriority( - schedulerPriorityToLanePriority(priorityLevel), - ); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + setCurrentUpdateLanePriority( + schedulerPriorityToLanePriority(priorityLevel), + ); + return runWithPriority(priorityLevel, flushPassiveEffectsImpl); + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + } + } else { return runWithPriority(priorityLevel, flushPassiveEffectsImpl); - } finally { - setCurrentUpdateLanePriority(previousLanePriority); } } return false; diff --git a/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js b/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js index 99780f6dbaff3..18e4ba82ab36c 100644 --- a/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js +++ b/packages/react-reconciler/src/SchedulerWithReactIntegration.new.js @@ -13,7 +13,10 @@ import type {ReactPriorityLevel} from './ReactInternalTypes'; // CommonJS interop named imports. import * as Scheduler from 'scheduler'; import {__interactionsRef} from 'scheduler/tracing'; -import {enableSchedulerTracing} from 'shared/ReactFeatureFlags'; +import { + enableSchedulerTracing, + decoupleUpdatePriorityFromScheduler, +} from 'shared/ReactFeatureFlags'; import invariant from 'shared/invariant'; import { SyncLanePriority, @@ -176,34 +179,63 @@ function flushSyncCallbackQueueImpl() { // Prevent re-entrancy. isFlushingSyncQueue = true; let i = 0; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - const isSync = true; - const queue = syncQueue; - setCurrentUpdateLanePriority(SyncLanePriority); - runWithPriority(ImmediatePriority, () => { - for (; i < queue.length; i++) { - let callback = queue[i]; - do { - callback = callback(isSync); - } while (callback !== null); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + const isSync = true; + const queue = syncQueue; + setCurrentUpdateLanePriority(SyncLanePriority); + runWithPriority(ImmediatePriority, () => { + for (; i < queue.length; i++) { + let callback = queue[i]; + do { + callback = callback(isSync); + } while (callback !== null); + } + }); + syncQueue = null; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); + } + // Resume flushing in the next tick + Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueue, + ); + throw error; + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + isFlushingSyncQueue = false; + } + } else { + try { + const isSync = true; + const queue = syncQueue; + runWithPriority(ImmediatePriority, () => { + for (; i < queue.length; i++) { + let callback = queue[i]; + do { + callback = callback(isSync); + } while (callback !== null); + } + }); + syncQueue = null; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); } - }); - syncQueue = null; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - if (syncQueue !== null) { - syncQueue = syncQueue.slice(i + 1); + // Resume flushing in the next tick + Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueue, + ); + throw error; + } finally { + isFlushingSyncQueue = false; } - // Resume flushing in the next tick - Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueue, - ); - throw error; - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - isFlushingSyncQueue = false; } } } diff --git a/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js b/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js index 99780f6dbaff3..18e4ba82ab36c 100644 --- a/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js +++ b/packages/react-reconciler/src/SchedulerWithReactIntegration.old.js @@ -13,7 +13,10 @@ import type {ReactPriorityLevel} from './ReactInternalTypes'; // CommonJS interop named imports. import * as Scheduler from 'scheduler'; import {__interactionsRef} from 'scheduler/tracing'; -import {enableSchedulerTracing} from 'shared/ReactFeatureFlags'; +import { + enableSchedulerTracing, + decoupleUpdatePriorityFromScheduler, +} from 'shared/ReactFeatureFlags'; import invariant from 'shared/invariant'; import { SyncLanePriority, @@ -176,34 +179,63 @@ function flushSyncCallbackQueueImpl() { // Prevent re-entrancy. isFlushingSyncQueue = true; let i = 0; - const previousLanePriority = getCurrentUpdateLanePriority(); - try { - const isSync = true; - const queue = syncQueue; - setCurrentUpdateLanePriority(SyncLanePriority); - runWithPriority(ImmediatePriority, () => { - for (; i < queue.length; i++) { - let callback = queue[i]; - do { - callback = callback(isSync); - } while (callback !== null); + if (decoupleUpdatePriorityFromScheduler) { + const previousLanePriority = getCurrentUpdateLanePriority(); + try { + const isSync = true; + const queue = syncQueue; + setCurrentUpdateLanePriority(SyncLanePriority); + runWithPriority(ImmediatePriority, () => { + for (; i < queue.length; i++) { + let callback = queue[i]; + do { + callback = callback(isSync); + } while (callback !== null); + } + }); + syncQueue = null; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); + } + // Resume flushing in the next tick + Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueue, + ); + throw error; + } finally { + setCurrentUpdateLanePriority(previousLanePriority); + isFlushingSyncQueue = false; + } + } else { + try { + const isSync = true; + const queue = syncQueue; + runWithPriority(ImmediatePriority, () => { + for (; i < queue.length; i++) { + let callback = queue[i]; + do { + callback = callback(isSync); + } while (callback !== null); + } + }); + syncQueue = null; + } catch (error) { + // If something throws, leave the remaining callbacks on the queue. + if (syncQueue !== null) { + syncQueue = syncQueue.slice(i + 1); } - }); - syncQueue = null; - } catch (error) { - // If something throws, leave the remaining callbacks on the queue. - if (syncQueue !== null) { - syncQueue = syncQueue.slice(i + 1); + // Resume flushing in the next tick + Scheduler_scheduleCallback( + Scheduler_ImmediatePriority, + flushSyncCallbackQueue, + ); + throw error; + } finally { + isFlushingSyncQueue = false; } - // Resume flushing in the next tick - Scheduler_scheduleCallback( - Scheduler_ImmediatePriority, - flushSyncCallbackQueue, - ); - throw error; - } finally { - setCurrentUpdateLanePriority(previousLanePriority); - isFlushingSyncQueue = false; } } }