mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
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
This commit is contained in:
+23
-7
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
enableDebugTracing,
|
||||
enableSchedulingProfiler,
|
||||
enableNewReconciler,
|
||||
decoupleUpdatePriorityFromScheduler,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
|
||||
@@ -1506,34 +1507,64 @@ function rerenderDeferredValue<T>(
|
||||
|
||||
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(
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
enableDebugTracing,
|
||||
enableSchedulingProfiler,
|
||||
enableNewReconciler,
|
||||
decoupleUpdatePriorityFromScheduler,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
|
||||
import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
|
||||
@@ -1505,34 +1506,64 @@ function rerenderDeferredValue<T>(
|
||||
|
||||
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(
|
||||
|
||||
@@ -1163,13 +1163,16 @@ export function flushDiscreteUpdates() {
|
||||
}
|
||||
|
||||
export function deferredUpdates<A>(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<A, B, C, D, R>(
|
||||
): 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<A, R>(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;
|
||||
|
||||
@@ -1147,13 +1147,16 @@ export function flushDiscreteUpdates() {
|
||||
}
|
||||
|
||||
export function deferredUpdates<A>(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<A, B, C, D, R>(
|
||||
): 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<A, R>(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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user