Decouple update priority tracking from Scheduler package (#19121)
* Initial currentLanePriority implementation * Minor updates from review * Fix typos and enable flag * Fix feature flags and lint * Fix simple event tests by switching to withSuspenseConfig * Don't lower the priority of setPending in startTransition below InputContinuous * Move currentUpdateLanePriority in commit root into the first effect block * Refactor requestUpdateLane to log for priority mismatches Also verifies that the update lane priority matches the scheduler lane priority before using it * Fix four tests by adding ReactDOM.unstable_runWithPriority * Fix partial hydration when using update lane priority * Fix partial hydration when using update lane priority * Rename feature flag and only log for now * Move unstable_runWithPriority to ReactFiberReconciler * Add unstable_runWithPriority to ReactNoopPersistent too * Bug fixes and performance improvements * Initial currentLanePriority implementation * Minor updates from review * Fix typos and enable flag * Remove higherLanePriority from ReactDOMEventReplaying.js * Change warning implementation and startTransition update lane priority * Inject reconciler functions to avoid importing src/ * Fix feature flags and lint * Fix simple event tests by switching to withSuspenseConfig * Don't lower the priority of setPending in startTransition below InputContinuous * Move currentUpdateLanePriority in commit root into the first effect block * Refactor requestUpdateLane to log for priority mismatches Also verifies that the update lane priority matches the scheduler lane priority before using it * Fix four tests by adding ReactDOM.unstable_runWithPriority * Fix partial hydration when using update lane priority * Fix partial hydration when using update lane priority * Rename feature flag and only log for now * Move unstable_runWithPriority to ReactFiberReconciler * Bug fixes and performance improvements * Remove higherLanePriority from ReactDOMEventReplaying.js * Change warning implementation and startTransition update lane priority * Inject reconciler functions to avoid importing src/ * Fixes from bad rebase
This commit is contained in:
parent
c3e42a962b
commit
91a2e8173f
|
@ -34,6 +34,7 @@ export {
|
|||
createBlockingRoot as unstable_createBlockingRoot,
|
||||
unstable_flushControlled,
|
||||
unstable_scheduleHydration,
|
||||
unstable_runWithPriority,
|
||||
unstable_renderSubtreeIntoContainer,
|
||||
unstable_createPortal,
|
||||
unstable_createEventHandle,
|
||||
|
|
|
@ -23,6 +23,8 @@ export {
|
|||
createBlockingRoot as unstable_createBlockingRoot,
|
||||
unstable_flushControlled,
|
||||
unstable_scheduleHydration,
|
||||
// DO NOT USE: Temporarily exposing this to migrate off of Scheduler.runWithPriority.
|
||||
unstable_runWithPriority,
|
||||
// Disabled behind disableUnstableRenderSubtreeIntoContainer
|
||||
unstable_renderSubtreeIntoContainer,
|
||||
// Disabled behind disableUnstableCreatePortal
|
||||
|
|
|
@ -25,6 +25,7 @@ export {
|
|||
createBlockingRoot as unstable_createBlockingRoot,
|
||||
unstable_flushControlled,
|
||||
unstable_scheduleHydration,
|
||||
unstable_runWithPriority,
|
||||
unstable_renderSubtreeIntoContainer,
|
||||
unstable_createPortal,
|
||||
unstable_createEventHandle,
|
||||
|
|
|
@ -19,6 +19,7 @@ export {
|
|||
createBlockingRoot as unstable_createBlockingRoot,
|
||||
unstable_flushControlled,
|
||||
unstable_scheduleHydration,
|
||||
unstable_runWithPriority,
|
||||
unstable_createEventHandle,
|
||||
unstable_isNewReconciler,
|
||||
} from './src/client/ReactDOM';
|
||||
|
|
|
@ -35,6 +35,8 @@ import {
|
|||
attemptUserBlockingHydration,
|
||||
attemptContinuousHydration,
|
||||
attemptHydrationAtCurrentPriority,
|
||||
runWithPriority,
|
||||
getCurrentUpdatePriority,
|
||||
} from 'react-reconciler/src/ReactFiberReconciler';
|
||||
import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
|
||||
import {canUseDOM} from 'shared/ExecutionEnvironment';
|
||||
|
@ -58,6 +60,8 @@ import {
|
|||
setAttemptContinuousHydration,
|
||||
setAttemptHydrationAtCurrentPriority,
|
||||
queueExplicitHydrationTarget,
|
||||
setGetCurrentUpdatePriority,
|
||||
setAttemptHydrationAtPriority,
|
||||
} from '../events/ReactDOMEventReplaying';
|
||||
import {setBatchingImplementation} from '../events/ReactDOMUpdateBatching';
|
||||
import {
|
||||
|
@ -70,6 +74,8 @@ setAttemptSynchronousHydration(attemptSynchronousHydration);
|
|||
setAttemptUserBlockingHydration(attemptUserBlockingHydration);
|
||||
setAttemptContinuousHydration(attemptContinuousHydration);
|
||||
setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
|
||||
setGetCurrentUpdatePriority(getCurrentUpdatePriority);
|
||||
setAttemptHydrationAtPriority(runWithPriority);
|
||||
|
||||
let didWarnAboutUnstableCreatePortal = false;
|
||||
let didWarnAboutUnstableRenderSubtreeIntoContainer = false;
|
||||
|
@ -205,6 +211,9 @@ export {
|
|||
unstable_createPortal,
|
||||
// enableCreateEventHandleAPI
|
||||
createEventHandle as unstable_createEventHandle,
|
||||
// TODO: Remove this once callers migrate to alternatives.
|
||||
// This should only be used by React internals.
|
||||
runWithPriority as unstable_runWithPriority,
|
||||
};
|
||||
|
||||
const foundDevTools = injectIntoDevTools({
|
||||
|
|
|
@ -12,7 +12,10 @@ import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
|
|||
import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes';
|
||||
import type {ElementListenerMap} from '../client/ReactDOMComponentTree';
|
||||
import type {EventSystemFlags} from './EventSystemFlags';
|
||||
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
|
||||
import type {
|
||||
FiberRoot,
|
||||
ReactPriorityLevel,
|
||||
} from 'react-reconciler/src/ReactInternalTypes';
|
||||
|
||||
import {
|
||||
enableDeprecatedFlareAPI,
|
||||
|
@ -64,6 +67,23 @@ export function setAttemptHydrationAtCurrentPriority(
|
|||
attemptHydrationAtCurrentPriority = fn;
|
||||
}
|
||||
|
||||
let getCurrentUpdatePriority: () => ReactPriorityLevel;
|
||||
|
||||
export function setGetCurrentUpdatePriority(fn: () => ReactPriorityLevel) {
|
||||
getCurrentUpdatePriority = fn;
|
||||
}
|
||||
|
||||
let attemptHydrationAtPriority: <T>(
|
||||
priority: ReactPriorityLevel,
|
||||
fn: () => T,
|
||||
) => T;
|
||||
|
||||
export function setAttemptHydrationAtPriority(
|
||||
fn: <T>(priority: ReactPriorityLevel, fn: () => T) => T,
|
||||
) {
|
||||
attemptHydrationAtPriority = fn;
|
||||
}
|
||||
|
||||
// TODO: Upgrade this definition once we're on a newer version of Flow that
|
||||
// has this definition built-in.
|
||||
type PointerEvent = Event & {
|
||||
|
@ -147,6 +167,7 @@ type QueuedHydrationTarget = {|
|
|||
blockedOn: null | Container | SuspenseInstance,
|
||||
target: Node,
|
||||
priority: number,
|
||||
lanePriority: ReactPriorityLevel,
|
||||
|};
|
||||
const queuedExplicitHydrationTargets: Array<QueuedHydrationTarget> = [];
|
||||
|
||||
|
@ -508,9 +529,12 @@ function attemptExplicitHydrationTarget(
|
|||
// We're blocked on hydrating this boundary.
|
||||
// Increase its priority.
|
||||
queuedTarget.blockedOn = instance;
|
||||
attemptHydrationAtPriority(queuedTarget.lanePriority, () => {
|
||||
runWithPriority(queuedTarget.priority, () => {
|
||||
attemptHydrationAtCurrentPriority(nearestMounted);
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
} else if (tag === HostRoot) {
|
||||
|
@ -529,15 +553,17 @@ function attemptExplicitHydrationTarget(
|
|||
|
||||
export function queueExplicitHydrationTarget(target: Node): void {
|
||||
if (enableSelectiveHydration) {
|
||||
const priority = getCurrentPriorityLevel();
|
||||
const schedulerPriority = getCurrentPriorityLevel();
|
||||
const updateLanePriority = getCurrentUpdatePriority();
|
||||
const queuedTarget: QueuedHydrationTarget = {
|
||||
blockedOn: null,
|
||||
target: target,
|
||||
priority: priority,
|
||||
priority: schedulerPriority,
|
||||
lanePriority: updateLanePriority,
|
||||
};
|
||||
let i = 0;
|
||||
for (; i < queuedExplicitHydrationTargets.length; i++) {
|
||||
if (priority <= queuedExplicitHydrationTargets[i].priority) {
|
||||
if (schedulerPriority <= queuedExplicitHydrationTargets[i].priority) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -231,6 +231,8 @@ describe('SimpleEventPlugin', function() {
|
|||
describe('interactive events, in concurrent mode', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
|
||||
React = require('react');
|
||||
ReactDOM = require('react-dom');
|
||||
Scheduler = require('scheduler');
|
||||
});
|
||||
|
@ -377,11 +379,14 @@ describe('SimpleEventPlugin', function() {
|
|||
<button
|
||||
ref={el => (button = el)}
|
||||
onClick={() => {
|
||||
Scheduler.unstable_next(() => {
|
||||
React.unstable_withSuspenseConfig(
|
||||
() => {
|
||||
this.setState(state => ({
|
||||
lowPriCount: state.lowPriCount + 1,
|
||||
}));
|
||||
});
|
||||
},
|
||||
{timeoutMs: 5000},
|
||||
);
|
||||
}}>
|
||||
{text}
|
||||
</button>
|
||||
|
|
|
@ -47,6 +47,9 @@ export const {
|
|||
act,
|
||||
dumpTree,
|
||||
getRoot,
|
||||
// TODO: Remove this once callers migrate to alternatives.
|
||||
// This should only be used by React internals.
|
||||
unstable_runWithPriority,
|
||||
} = createReactNoop(
|
||||
ReactFiberReconciler, // reconciler
|
||||
true, // useMutation
|
||||
|
|
|
@ -47,6 +47,9 @@ export const {
|
|||
act,
|
||||
dumpTree,
|
||||
getRoot,
|
||||
// TODO: Remove this once callers migrate to alternatives.
|
||||
// This should only be used by React internals.
|
||||
unstable_runWithPriority,
|
||||
} = createReactNoop(
|
||||
ReactFiberReconciler, // reconciler
|
||||
false, // useMutation
|
||||
|
|
|
@ -954,6 +954,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
|||
return Scheduler.unstable_flushExpired();
|
||||
},
|
||||
|
||||
unstable_runWithPriority: NoopRenderer.runWithPriority,
|
||||
|
||||
batchedUpdates: NoopRenderer.batchedUpdates,
|
||||
|
||||
deferredUpdates: NoopRenderer.deferredUpdates,
|
||||
|
|
|
@ -30,11 +30,16 @@ import {NoMode, BlockingMode} from './ReactTypeOfMode';
|
|||
import {
|
||||
NoLane,
|
||||
NoLanes,
|
||||
InputContinuousLanePriority,
|
||||
isSubsetOfLanes,
|
||||
mergeLanes,
|
||||
removeLanes,
|
||||
markRootEntangled,
|
||||
markRootMutableRead,
|
||||
getCurrentUpdateLanePriority,
|
||||
setCurrentUpdateLanePriority,
|
||||
higherLanePriority,
|
||||
DefaultLanePriority,
|
||||
} from './ReactFiberLane';
|
||||
import {readContext} from './ReactFiberNewContext.new';
|
||||
import {createDeprecatedResponderListener} from './ReactFiberDeprecatedEvents.new';
|
||||
|
@ -1498,12 +1503,20 @@ 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 there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
|
||||
setCurrentUpdateLanePriority(DefaultLanePriority);
|
||||
|
||||
runWithPriority(
|
||||
priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
|
||||
() => {
|
||||
|
@ -1513,6 +1526,7 @@ function startTransition(setPending, config, callback) {
|
|||
setPending(false);
|
||||
callback();
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
ReactCurrentBatchConfig.suspense = previousConfig;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -33,11 +33,16 @@ import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
|
|||
import {
|
||||
NoLane,
|
||||
NoLanes,
|
||||
InputContinuousLanePriority,
|
||||
isSubsetOfLanes,
|
||||
mergeLanes,
|
||||
removeLanes,
|
||||
markRootEntangled,
|
||||
markRootMutableRead,
|
||||
getCurrentUpdateLanePriority,
|
||||
setCurrentUpdateLanePriority,
|
||||
higherLanePriority,
|
||||
DefaultLanePriority,
|
||||
} from './ReactFiberLane';
|
||||
import {readContext} from './ReactFiberNewContext.old';
|
||||
import {createDeprecatedResponderListener} from './ReactFiberDeprecatedEvents.old';
|
||||
|
@ -1502,12 +1507,20 @@ 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 there's no SuspenseConfig set, we'll use the DefaultLanePriority for this transition.
|
||||
setCurrentUpdateLanePriority(DefaultLanePriority);
|
||||
|
||||
runWithPriority(
|
||||
priorityLevel > NormalPriority ? NormalPriority : priorityLevel,
|
||||
() => {
|
||||
|
@ -1517,6 +1530,7 @@ function startTransition(setPending, config, callback) {
|
|||
setPending(false);
|
||||
callback();
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
ReactCurrentBatchConfig.suspense = previousConfig;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -49,10 +49,10 @@ const InputDiscreteHydrationLanePriority: LanePriority = 14;
|
|||
export const InputDiscreteLanePriority: LanePriority = 13;
|
||||
|
||||
const InputContinuousHydrationLanePriority: LanePriority = 12;
|
||||
const InputContinuousLanePriority: LanePriority = 11;
|
||||
export const InputContinuousLanePriority: LanePriority = 11;
|
||||
|
||||
const DefaultHydrationLanePriority: LanePriority = 10;
|
||||
const DefaultLanePriority: LanePriority = 9;
|
||||
export const DefaultLanePriority: LanePriority = 9;
|
||||
|
||||
const TransitionShortHydrationLanePriority: LanePriority = 8;
|
||||
export const TransitionShortLanePriority: LanePriority = 7;
|
||||
|
@ -120,6 +120,16 @@ export const OffscreenLane: Lane = /* */ 0b1000000000000000000
|
|||
|
||||
export const NoTimestamp = -1;
|
||||
|
||||
let currentUpdateLanePriority: LanePriority = NoLanePriority;
|
||||
|
||||
export function getCurrentUpdateLanePriority(): LanePriority {
|
||||
return currentUpdateLanePriority;
|
||||
}
|
||||
|
||||
export function setCurrentUpdateLanePriority(newLanePriority: LanePriority) {
|
||||
currentUpdateLanePriority = newLanePriority;
|
||||
}
|
||||
|
||||
// "Registers" used to "return" multiple values
|
||||
// Used by getHighestPriorityLanes and getNextLanes:
|
||||
let return_highestLanePriority: LanePriority = DefaultLanePriority;
|
||||
|
@ -651,6 +661,13 @@ export function higherPriorityLane(a: Lane, b: Lane) {
|
|||
return a !== NoLane && a < b ? a : b;
|
||||
}
|
||||
|
||||
export function higherLanePriority(
|
||||
a: LanePriority,
|
||||
b: LanePriority,
|
||||
): LanePriority {
|
||||
return a !== NoLanePriority && a > b ? a : b;
|
||||
}
|
||||
|
||||
export function createLaneMap<T>(initial: T): LaneMap<T> {
|
||||
return new Array(TotalLanes).fill(initial);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ import {
|
|||
focusWithin as focusWithin_old,
|
||||
observeVisibleRects as observeVisibleRects_old,
|
||||
registerMutableSourceForHydration as registerMutableSourceForHydration_old,
|
||||
runWithPriority as runWithPriority_old,
|
||||
getCurrentUpdatePriority as getCurrentUpdatePriority_old,
|
||||
} from './ReactFiberReconciler.old';
|
||||
|
||||
import {
|
||||
|
@ -88,6 +90,8 @@ import {
|
|||
focusWithin as focusWithin_new,
|
||||
observeVisibleRects as observeVisibleRects_new,
|
||||
registerMutableSourceForHydration as registerMutableSourceForHydration_new,
|
||||
runWithPriority as runWithPriority_new,
|
||||
getCurrentUpdatePriority as getCurrentUpdatePriority_new,
|
||||
} from './ReactFiberReconciler.new';
|
||||
|
||||
export const createContainer = enableNewReconciler
|
||||
|
@ -139,6 +143,9 @@ export const attemptContinuousHydration = enableNewReconciler
|
|||
export const attemptHydrationAtCurrentPriority = enableNewReconciler
|
||||
? attemptHydrationAtCurrentPriority_new
|
||||
: attemptHydrationAtCurrentPriority_old;
|
||||
export const getCurrentUpdatePriority = enableNewReconciler
|
||||
? getCurrentUpdatePriority_new
|
||||
: getCurrentUpdatePriority_old;
|
||||
export const findHostInstance = enableNewReconciler
|
||||
? findHostInstance_new
|
||||
: findHostInstance_old;
|
||||
|
@ -194,3 +201,6 @@ export const observeVisibleRects = enableNewReconciler
|
|||
export const registerMutableSourceForHydration = enableNewReconciler
|
||||
? registerMutableSourceForHydration_new
|
||||
: registerMutableSourceForHydration_old;
|
||||
export const runWithPriority = enableNewReconciler
|
||||
? runWithPriority_new
|
||||
: runWithPriority_old;
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
import type {Fiber, SuspenseHydrationCallbacks} from './ReactInternalTypes';
|
||||
import type {
|
||||
Fiber,
|
||||
ReactPriorityLevel,
|
||||
SuspenseHydrationCallbacks,
|
||||
} from './ReactInternalTypes';
|
||||
import type {FiberRoot} from './ReactInternalTypes';
|
||||
import type {RootTag} from './ReactRootTags';
|
||||
import type {
|
||||
|
@ -79,6 +83,10 @@ import {
|
|||
NoTimestamp,
|
||||
getHighestPriorityPendingLanes,
|
||||
higherPriorityLane,
|
||||
getCurrentUpdateLanePriority,
|
||||
setCurrentUpdateLanePriority,
|
||||
schedulerPriorityToLanePriority,
|
||||
lanePriorityToSchedulerPriority,
|
||||
} from './ReactFiberLane';
|
||||
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
|
||||
import {
|
||||
|
@ -424,6 +432,20 @@ export function attemptHydrationAtCurrentPriority(fiber: Fiber): void {
|
|||
markRetryLaneIfNotHydrated(fiber, lane);
|
||||
}
|
||||
|
||||
export function runWithPriority<T>(priority: ReactPriorityLevel, fn: () => T) {
|
||||
const previousPriority = getCurrentUpdateLanePriority();
|
||||
try {
|
||||
setCurrentUpdateLanePriority(schedulerPriorityToLanePriority(priority));
|
||||
return fn();
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousPriority);
|
||||
}
|
||||
}
|
||||
|
||||
export function getCurrentUpdatePriority(): ReactPriorityLevel {
|
||||
return lanePriorityToSchedulerPriority(getCurrentUpdateLanePriority());
|
||||
}
|
||||
|
||||
export {findHostInstance};
|
||||
|
||||
export {findHostInstanceWithWarning};
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
import type {Fiber, SuspenseHydrationCallbacks} from './ReactInternalTypes';
|
||||
import type {
|
||||
Fiber,
|
||||
ReactPriorityLevel,
|
||||
SuspenseHydrationCallbacks,
|
||||
} from './ReactInternalTypes';
|
||||
import type {FiberRoot} from './ReactInternalTypes';
|
||||
import type {RootTag} from './ReactRootTags';
|
||||
import type {
|
||||
|
@ -79,6 +83,10 @@ import {
|
|||
NoTimestamp,
|
||||
getHighestPriorityPendingLanes,
|
||||
higherPriorityLane,
|
||||
getCurrentUpdateLanePriority,
|
||||
setCurrentUpdateLanePriority,
|
||||
schedulerPriorityToLanePriority,
|
||||
lanePriorityToSchedulerPriority,
|
||||
} from './ReactFiberLane';
|
||||
import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
|
||||
import {
|
||||
|
@ -424,6 +432,20 @@ export function attemptHydrationAtCurrentPriority(fiber: Fiber): void {
|
|||
markRetryLaneIfNotHydrated(fiber, lane);
|
||||
}
|
||||
|
||||
export function runWithPriority<T>(priority: ReactPriorityLevel, fn: () => T) {
|
||||
const previousPriority = getCurrentUpdateLanePriority();
|
||||
try {
|
||||
setCurrentUpdateLanePriority(schedulerPriorityToLanePriority(priority));
|
||||
return fn();
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousPriority);
|
||||
}
|
||||
}
|
||||
|
||||
export function getCurrentUpdatePriority(): ReactPriorityLevel {
|
||||
return lanePriorityToSchedulerPriority(getCurrentUpdateLanePriority());
|
||||
}
|
||||
|
||||
export {findHostInstance};
|
||||
|
||||
export {findHostInstanceWithWarning};
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
enableSchedulerTracing,
|
||||
warnAboutUnmockedScheduler,
|
||||
deferRenderPhaseUpdateToNextBatch,
|
||||
decoupleUpdatePriorityFromScheduler,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||
import invariant from 'shared/invariant';
|
||||
|
@ -113,6 +114,7 @@ import {
|
|||
InputDiscreteLanePriority,
|
||||
TransitionShortLanePriority,
|
||||
TransitionLongLanePriority,
|
||||
DefaultLanePriority,
|
||||
NoLanes,
|
||||
NoLane,
|
||||
SyncLane,
|
||||
|
@ -130,6 +132,8 @@ import {
|
|||
hasUpdatePriority,
|
||||
getNextLanes,
|
||||
returnNextLanesPriority,
|
||||
setCurrentUpdateLanePriority,
|
||||
getCurrentUpdateLanePriority,
|
||||
markStarvedLanesAsExpired,
|
||||
getLanesToRetrySynchronouslyOnError,
|
||||
markRootUpdated,
|
||||
|
@ -394,7 +398,6 @@ export function requestUpdateLane(
|
|||
currentEventWipLanes = workInProgressRootIncludedLanes;
|
||||
}
|
||||
|
||||
let lane;
|
||||
if (suspenseConfig !== null) {
|
||||
// Use the size of the timeout as a heuristic to prioritize shorter
|
||||
// transitions over longer ones.
|
||||
|
@ -412,16 +415,24 @@ export function requestUpdateLane(
|
|||
: NoLanes;
|
||||
}
|
||||
|
||||
lane = findTransitionLane(
|
||||
return findTransitionLane(
|
||||
transitionLanePriority,
|
||||
currentEventWipLanes,
|
||||
currentEventPendingLanes,
|
||||
);
|
||||
} else {
|
||||
// TODO: If we're not inside `runWithPriority`, this returns the priority
|
||||
// of the currently running task. That's probably not what we want.
|
||||
}
|
||||
|
||||
// TODO: Remove this dependency on the Scheduler priority.
|
||||
// To do that, we're replacing it with an update lane priority.
|
||||
const schedulerPriority = getCurrentPriorityLevel();
|
||||
|
||||
// The old behavior was using the priority level of the Scheduler.
|
||||
// This couples React to the Scheduler internals, so we're replacing it
|
||||
// with the currentUpdateLanePriority above. As an example of how this
|
||||
// could be problematic, if we're not inside `Scheduler.runWithPriority`,
|
||||
// then we'll get the priority of the current running Scheduler task,
|
||||
// which is probably not what we want.
|
||||
let lane;
|
||||
if (
|
||||
// TODO: Temporary. We're removing the concept of discrete updates.
|
||||
(executionContext & DiscreteEventContext) !== NoContext &&
|
||||
|
@ -429,10 +440,32 @@ export function requestUpdateLane(
|
|||
) {
|
||||
lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes);
|
||||
} else {
|
||||
const lanePriority = schedulerPriorityToLanePriority(schedulerPriority);
|
||||
lane = findUpdateLane(lanePriority, currentEventWipLanes);
|
||||
const schedulerLanePriority = schedulerPriorityToLanePriority(
|
||||
schedulerPriority,
|
||||
);
|
||||
|
||||
if (decoupleUpdatePriorityFromScheduler) {
|
||||
// In the new strategy, we will track the current update lane priority
|
||||
// inside React and use that priority to select a lane for this update.
|
||||
// For now, we're just logging when they're different so we can assess.
|
||||
const currentUpdateLanePriority = getCurrentUpdateLanePriority();
|
||||
|
||||
if (
|
||||
schedulerLanePriority !== currentUpdateLanePriority &&
|
||||
currentUpdateLanePriority !== NoLanePriority
|
||||
) {
|
||||
if (__DEV__) {
|
||||
console.error(
|
||||
'Expected current scheduler lane priority %s to match current update lane priority %s',
|
||||
schedulerLanePriority,
|
||||
currentUpdateLanePriority,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes);
|
||||
}
|
||||
|
||||
return lane;
|
||||
}
|
||||
|
@ -1068,7 +1101,13 @@ export function flushDiscreteUpdates() {
|
|||
|
||||
export function deferredUpdates<A>(fn: () => A): A {
|
||||
// TODO: Remove in favor of Scheduler.next
|
||||
const previousLanePriority = getCurrentUpdateLanePriority();
|
||||
try {
|
||||
setCurrentUpdateLanePriority(DefaultLanePriority);
|
||||
return runWithPriority(NormalSchedulerPriority, fn);
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
}
|
||||
}
|
||||
|
||||
function flushPendingDiscreteUpdates() {
|
||||
|
@ -1123,13 +1162,16 @@ 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
|
||||
|
@ -1166,13 +1208,16 @@ 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);
|
||||
}
|
||||
} 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
|
||||
|
@ -1184,9 +1229,12 @@ export function flushSync<A, R>(fn: A => R, a: A): R {
|
|||
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
|
||||
|
@ -1867,6 +1915,9 @@ function commitRootImpl(root, renderPriorityLevel) {
|
|||
}
|
||||
|
||||
if (firstEffect !== null) {
|
||||
const previousLanePriority = getCurrentUpdateLanePriority();
|
||||
setCurrentUpdateLanePriority(SyncLanePriority);
|
||||
|
||||
const prevExecutionContext = executionContext;
|
||||
executionContext |= CommitContext;
|
||||
const prevInteractions = pushInteractions(root);
|
||||
|
@ -1987,6 +2038,9 @@ function commitRootImpl(root, renderPriorityLevel) {
|
|||
popInteractions(((prevInteractions: any): Set<Interaction>));
|
||||
}
|
||||
executionContext = prevExecutionContext;
|
||||
|
||||
// Reset the priority to the previous non-sync value.
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
} else {
|
||||
// No effects.
|
||||
root.current = finishedWork;
|
||||
|
@ -2249,7 +2303,15 @@ export function flushPassiveEffects() {
|
|||
? NormalSchedulerPriority
|
||||
: pendingPassiveEffectsRenderPriority;
|
||||
pendingPassiveEffectsRenderPriority = NoSchedulerPriority;
|
||||
const previousLanePriority = getCurrentUpdateLanePriority();
|
||||
try {
|
||||
setCurrentUpdateLanePriority(
|
||||
schedulerPriorityToLanePriority(priorityLevel),
|
||||
);
|
||||
return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
enableSchedulerTracing,
|
||||
warnAboutUnmockedScheduler,
|
||||
deferRenderPhaseUpdateToNextBatch,
|
||||
decoupleUpdatePriorityFromScheduler,
|
||||
enableDebugTracing,
|
||||
} from 'shared/ReactFeatureFlags';
|
||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||
|
@ -124,6 +125,7 @@ import {
|
|||
InputDiscreteLanePriority,
|
||||
TransitionShortLanePriority,
|
||||
TransitionLongLanePriority,
|
||||
DefaultLanePriority,
|
||||
NoLanes,
|
||||
NoLane,
|
||||
SyncLane,
|
||||
|
@ -141,6 +143,8 @@ import {
|
|||
hasUpdatePriority,
|
||||
getNextLanes,
|
||||
returnNextLanesPriority,
|
||||
setCurrentUpdateLanePriority,
|
||||
getCurrentUpdateLanePriority,
|
||||
markStarvedLanesAsExpired,
|
||||
getLanesToRetrySynchronouslyOnError,
|
||||
markRootUpdated,
|
||||
|
@ -405,7 +409,6 @@ export function requestUpdateLane(
|
|||
currentEventWipLanes = workInProgressRootIncludedLanes;
|
||||
}
|
||||
|
||||
let lane;
|
||||
if (suspenseConfig !== null) {
|
||||
// Use the size of the timeout as a heuristic to prioritize shorter
|
||||
// transitions over longer ones.
|
||||
|
@ -423,16 +426,24 @@ export function requestUpdateLane(
|
|||
: NoLanes;
|
||||
}
|
||||
|
||||
lane = findTransitionLane(
|
||||
return findTransitionLane(
|
||||
transitionLanePriority,
|
||||
currentEventWipLanes,
|
||||
currentEventPendingLanes,
|
||||
);
|
||||
} else {
|
||||
// TODO: If we're not inside `runWithPriority`, this returns the priority
|
||||
// of the currently running task. That's probably not what we want.
|
||||
}
|
||||
|
||||
// TODO: Remove this dependency on the Scheduler priority.
|
||||
// To do that, we're replacing it with an update lane priority.
|
||||
const schedulerPriority = getCurrentPriorityLevel();
|
||||
|
||||
// The old behavior was using the priority level of the Scheduler.
|
||||
// This couples React to the Scheduler internals, so we're replacing it
|
||||
// with the currentUpdateLanePriority above. As an example of how this
|
||||
// could be problematic, if we're not inside `Scheduler.runWithPriority`,
|
||||
// then we'll get the priority of the current running Scheduler task,
|
||||
// which is probably not what we want.
|
||||
let lane;
|
||||
if (
|
||||
// TODO: Temporary. We're removing the concept of discrete updates.
|
||||
(executionContext & DiscreteEventContext) !== NoContext &&
|
||||
|
@ -440,10 +451,32 @@ export function requestUpdateLane(
|
|||
) {
|
||||
lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes);
|
||||
} else {
|
||||
const lanePriority = schedulerPriorityToLanePriority(schedulerPriority);
|
||||
lane = findUpdateLane(lanePriority, currentEventWipLanes);
|
||||
const schedulerLanePriority = schedulerPriorityToLanePriority(
|
||||
schedulerPriority,
|
||||
);
|
||||
|
||||
if (decoupleUpdatePriorityFromScheduler) {
|
||||
// In the new strategy, we will track the current update lane priority
|
||||
// inside React and use that priority to select a lane for this update.
|
||||
// For now, we're just logging when they're different so we can assess.
|
||||
const currentUpdateLanePriority = getCurrentUpdateLanePriority();
|
||||
|
||||
if (
|
||||
schedulerLanePriority !== currentUpdateLanePriority &&
|
||||
currentUpdateLanePriority !== NoLanePriority
|
||||
) {
|
||||
if (__DEV__) {
|
||||
console.error(
|
||||
'Expected current scheduler lane priority %s to match current update lane priority %s',
|
||||
schedulerLanePriority,
|
||||
currentUpdateLanePriority,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes);
|
||||
}
|
||||
|
||||
return lane;
|
||||
}
|
||||
|
@ -1079,7 +1112,13 @@ export function flushDiscreteUpdates() {
|
|||
|
||||
export function deferredUpdates<A>(fn: () => A): A {
|
||||
// TODO: Remove in favor of Scheduler.next
|
||||
const previousLanePriority = getCurrentUpdateLanePriority();
|
||||
try {
|
||||
setCurrentUpdateLanePriority(DefaultLanePriority);
|
||||
return runWithPriority(NormalSchedulerPriority, fn);
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
}
|
||||
}
|
||||
|
||||
function flushPendingDiscreteUpdates() {
|
||||
|
@ -1134,13 +1173,16 @@ 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
|
||||
|
@ -1177,13 +1219,16 @@ 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);
|
||||
}
|
||||
} 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
|
||||
|
@ -1195,9 +1240,12 @@ export function flushSync<A, R>(fn: A => R, a: A): R {
|
|||
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
|
||||
|
@ -1915,6 +1963,9 @@ function commitRootImpl(root, renderPriorityLevel) {
|
|||
}
|
||||
|
||||
if (firstEffect !== null) {
|
||||
const previousLanePriority = getCurrentUpdateLanePriority();
|
||||
setCurrentUpdateLanePriority(SyncLanePriority);
|
||||
|
||||
const prevExecutionContext = executionContext;
|
||||
executionContext |= CommitContext;
|
||||
const prevInteractions = pushInteractions(root);
|
||||
|
@ -2035,6 +2086,9 @@ function commitRootImpl(root, renderPriorityLevel) {
|
|||
popInteractions(((prevInteractions: any): Set<Interaction>));
|
||||
}
|
||||
executionContext = prevExecutionContext;
|
||||
|
||||
// Reset the priority to the previous non-sync value.
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
} else {
|
||||
// No effects.
|
||||
root.current = finishedWork;
|
||||
|
@ -2321,7 +2375,15 @@ export function flushPassiveEffects() {
|
|||
? NormalSchedulerPriority
|
||||
: pendingPassiveEffectsRenderPriority;
|
||||
pendingPassiveEffectsRenderPriority = NoSchedulerPriority;
|
||||
const previousLanePriority = getCurrentUpdateLanePriority();
|
||||
try {
|
||||
setCurrentUpdateLanePriority(
|
||||
schedulerPriorityToLanePriority(priorityLevel),
|
||||
);
|
||||
return runWithPriority(priorityLevel, flushPassiveEffectsImpl);
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,11 @@ import * as Scheduler from 'scheduler';
|
|||
import {__interactionsRef} from 'scheduler/tracing';
|
||||
import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
|
||||
import invariant from 'shared/invariant';
|
||||
import {
|
||||
SyncLanePriority,
|
||||
getCurrentUpdateLanePriority,
|
||||
setCurrentUpdateLanePriority,
|
||||
} from './ReactFiberLane';
|
||||
|
||||
const {
|
||||
unstable_runWithPriority: Scheduler_runWithPriority,
|
||||
|
@ -171,9 +176,11 @@ 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];
|
||||
|
@ -195,6 +202,7 @@ function flushSyncCallbackQueueImpl() {
|
|||
);
|
||||
throw error;
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
isFlushingSyncQueue = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,11 @@ import * as Scheduler from 'scheduler';
|
|||
import {__interactionsRef} from 'scheduler/tracing';
|
||||
import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
|
||||
import invariant from 'shared/invariant';
|
||||
import {
|
||||
SyncLanePriority,
|
||||
getCurrentUpdateLanePriority,
|
||||
setCurrentUpdateLanePriority,
|
||||
} from './ReactFiberLane';
|
||||
|
||||
const {
|
||||
unstable_runWithPriority: Scheduler_runWithPriority,
|
||||
|
@ -171,9 +176,11 @@ 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];
|
||||
|
@ -195,6 +202,7 @@ function flushSyncCallbackQueueImpl() {
|
|||
);
|
||||
throw error;
|
||||
} finally {
|
||||
setCurrentUpdateLanePriority(previousLanePriority);
|
||||
isFlushingSyncQueue = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -516,11 +516,16 @@ describe('ReactIncrementalUpdates', () => {
|
|||
Scheduler.unstable_yieldValue('Committed: ' + log);
|
||||
if (log === 'B') {
|
||||
// Right after B commits, schedule additional updates.
|
||||
// TODO: Double wrapping is temporary while we remove Scheduler runWithPriority.
|
||||
ReactNoop.unstable_runWithPriority(
|
||||
Scheduler.unstable_UserBlockingPriority,
|
||||
() =>
|
||||
Scheduler.unstable_runWithPriority(
|
||||
Scheduler.unstable_UserBlockingPriority,
|
||||
() => {
|
||||
pushToLog('C');
|
||||
},
|
||||
),
|
||||
);
|
||||
setLog(prevLog => prevLog + 'D');
|
||||
}
|
||||
|
@ -538,11 +543,17 @@ describe('ReactIncrementalUpdates', () => {
|
|||
|
||||
await ReactNoop.act(async () => {
|
||||
pushToLog('A');
|
||||
|
||||
// TODO: Double wrapping is temporary while we remove Scheduler runWithPriority.
|
||||
ReactNoop.unstable_runWithPriority(
|
||||
Scheduler.unstable_UserBlockingPriority,
|
||||
() =>
|
||||
Scheduler.unstable_runWithPriority(
|
||||
Scheduler.unstable_UserBlockingPriority,
|
||||
() => {
|
||||
pushToLog('B');
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
expect(Scheduler).toHaveYielded([
|
||||
|
@ -574,11 +585,16 @@ describe('ReactIncrementalUpdates', () => {
|
|||
Scheduler.unstable_yieldValue('Committed: ' + this.state.log);
|
||||
if (this.state.log === 'B') {
|
||||
// Right after B commits, schedule additional updates.
|
||||
// TODO: Double wrapping is temporary while we remove Scheduler runWithPriority.
|
||||
ReactNoop.unstable_runWithPriority(
|
||||
Scheduler.unstable_UserBlockingPriority,
|
||||
() =>
|
||||
Scheduler.unstable_runWithPriority(
|
||||
Scheduler.unstable_UserBlockingPriority,
|
||||
() => {
|
||||
this.pushToLog('C');
|
||||
},
|
||||
),
|
||||
);
|
||||
this.pushToLog('D');
|
||||
}
|
||||
|
@ -598,11 +614,16 @@ describe('ReactIncrementalUpdates', () => {
|
|||
|
||||
await ReactNoop.act(async () => {
|
||||
pushToLog('A');
|
||||
// TODO: Double wrapping is temporary while we remove Scheduler runWithPriority.
|
||||
ReactNoop.unstable_runWithPriority(
|
||||
Scheduler.unstable_UserBlockingPriority,
|
||||
() =>
|
||||
Scheduler.unstable_runWithPriority(
|
||||
Scheduler.unstable_UserBlockingPriority,
|
||||
() => {
|
||||
pushToLog('B');
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
expect(Scheduler).toHaveYielded([
|
||||
|
|
|
@ -232,9 +232,14 @@ describe('ReactDOMTracing', () => {
|
|||
Scheduler.unstable_yieldValue('Child:update');
|
||||
} else {
|
||||
Scheduler.unstable_yieldValue('Child:mount');
|
||||
// TODO: Double wrapping is temporary while we remove Scheduler runWithPriority.
|
||||
ReactDOM.unstable_runWithPriority(
|
||||
Scheduler.unstable_IdlePriority,
|
||||
() =>
|
||||
Scheduler.unstable_runWithPriority(
|
||||
Scheduler.unstable_IdlePriority,
|
||||
() => setDidMount(true),
|
||||
),
|
||||
);
|
||||
}
|
||||
}, [didMount]);
|
||||
|
|
|
@ -120,3 +120,6 @@ export const enableLegacyFBSupport = false;
|
|||
// interleaved event. Remove this flag once we have migrated to the
|
||||
// new behavior.
|
||||
export const deferRenderPhaseUpdateToNextBatch = true;
|
||||
|
||||
// Replacement for runWithPriority in React internals.
|
||||
export const decoupleUpdatePriorityFromScheduler = false;
|
||||
|
|
|
@ -46,6 +46,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
|
|||
|
||||
export const enableNewReconciler = false;
|
||||
export const deferRenderPhaseUpdateToNextBatch = true;
|
||||
export const decoupleUpdatePriorityFromScheduler = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
|
@ -45,6 +45,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
|
|||
|
||||
export const enableNewReconciler = false;
|
||||
export const deferRenderPhaseUpdateToNextBatch = true;
|
||||
export const decoupleUpdatePriorityFromScheduler = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
|
@ -45,6 +45,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
|
|||
|
||||
export const enableNewReconciler = false;
|
||||
export const deferRenderPhaseUpdateToNextBatch = true;
|
||||
export const decoupleUpdatePriorityFromScheduler = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
|
@ -45,6 +45,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
|
|||
|
||||
export const enableNewReconciler = false;
|
||||
export const deferRenderPhaseUpdateToNextBatch = true;
|
||||
export const decoupleUpdatePriorityFromScheduler = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
|
@ -45,6 +45,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
|
|||
|
||||
export const enableNewReconciler = false;
|
||||
export const deferRenderPhaseUpdateToNextBatch = true;
|
||||
export const decoupleUpdatePriorityFromScheduler = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
|
@ -45,6 +45,7 @@ export const enableFilterEmptyStringAttributesDOM = false;
|
|||
|
||||
export const enableNewReconciler = false;
|
||||
export const deferRenderPhaseUpdateToNextBatch = true;
|
||||
export const decoupleUpdatePriorityFromScheduler = false;
|
||||
|
||||
// Flow magic to verify the exports of this file match the original version.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
|
@ -18,6 +18,7 @@ export const disableInputAttributeSyncing = __VARIANT__;
|
|||
export const enableFilterEmptyStringAttributesDOM = __VARIANT__;
|
||||
export const enableLegacyFBSupport = __VARIANT__;
|
||||
export const enableDebugTracing = !__VARIANT__;
|
||||
export const decoupleUpdatePriorityFromScheduler = __VARIANT__;
|
||||
|
||||
// This only has an effect in the new reconciler. But also, the new reconciler
|
||||
// is only enabled when __VARIANT__ is true. So this is set to the opposite of
|
||||
|
|
|
@ -75,6 +75,7 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
|
|||
// don't have to add another test dimension. The build system will compile this
|
||||
// to the correct value.
|
||||
export const enableNewReconciler = __VARIANT__;
|
||||
export const decoupleUpdatePriorityFromScheduler = __VARIANT__;
|
||||
|
||||
// TODO: This does not currently exist in the new reconciler fork.
|
||||
export const enableDebugTracing = !__VARIANT__;
|
||||
|
|
Loading…
Reference in New Issue