Use EventPriority to track update priority (#21082)

Instead of LanePriority. Internally, EventPriority is just a lane, so
this skips an extra conversion. Since EventPriority is a "public" (to
the host config) type, I was also able to remove some deep imports
of the Lane module.

This gets us most of the way to deleting the LanePriority entirely.
This commit is contained in:
Andrew Clark
2021-03-25 09:21:41 -07:00
committed by GitHub
parent 6a589ad711
commit 03ede83d2e
25 changed files with 484 additions and 479 deletions
@@ -17,11 +17,7 @@ let ReactFeatureFlags;
let Suspense;
let SuspenseList;
let act;
// Copied from ReactFiberLanes. Don't do this!
// This is hard coded directly to avoid needing to import, and
// we'll remove this as we replace runWithPriority with React APIs.
export const IdleLanePriority = 2;
let IdleEventPriority;
function dispatchMouseEvent(to, from) {
if (!to) {
@@ -89,6 +85,8 @@ describe('ReactDOMServerPartialHydration', () => {
Scheduler = require('scheduler');
Suspense = React.Suspense;
SuspenseList = React.SuspenseList;
IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;
});
// Note: This is based on a similar component we use in www. We can delete
@@ -628,7 +626,7 @@ describe('ReactDOMServerPartialHydration', () => {
expect(span.textContent).toBe('Hello');
// Schedule an update at idle priority
ReactDOM.unstable_runWithPriority(IdleLanePriority, () => {
ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {
root.render(<App text="Hi" className="hi" />);
});
@@ -19,10 +19,7 @@ let Scheduler;
let Suspense;
let act;
// Copied from ReactFiberLanes. Don't do this!
// This is hard coded directly to avoid needing to import, and
// we'll remove this as we replace runWithPriority with React APIs.
export const IdleLanePriority = 2;
let IdleEventPriority;
function dispatchMouseHoverEvent(to, from) {
if (!to) {
@@ -101,7 +98,7 @@ function dispatchClickEvent(target) {
// and there's no native DOM event that maps to idle priority, so this is a
// temporary workaround. Need something like ReactDOM.unstable_IdleUpdates.
function TODO_scheduleIdleDOMSchedulerTask(fn) {
ReactDOM.unstable_runWithPriority(IdleLanePriority, () => {
ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {
const prevEvent = window.event;
window.event = {type: 'message'};
try {
@@ -125,6 +122,8 @@ describe('ReactDOMServerSelectiveHydration', () => {
act = ReactTestUtils.unstable_concurrentAct;
Scheduler = require('scheduler');
Suspense = React.Suspense;
IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;
});
// @gate experimental
+5 -3
View File
@@ -35,9 +35,11 @@ import {
attemptDiscreteHydration,
attemptContinuousHydration,
attemptHydrationAtCurrentPriority,
runWithPriority,
getCurrentUpdateLanePriority,
} from 'react-reconciler/src/ReactFiberReconciler';
import {
runWithPriority,
getCurrentUpdatePriority,
} from 'react-reconciler/src/ReactEventPriorities';
import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal';
import {canUseDOM} from 'shared/ExecutionEnvironment';
import ReactVersion from 'shared/ReactVersion';
@@ -74,7 +76,7 @@ setAttemptSynchronousHydration(attemptSynchronousHydration);
setAttemptDiscreteHydration(attemptDiscreteHydration);
setAttemptContinuousHydration(attemptContinuousHydration);
setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
setGetCurrentUpdatePriority(getCurrentUpdateLanePriority);
setGetCurrentUpdatePriority(getCurrentUpdatePriority);
setAttemptHydrationAtPriority(runWithPriority);
let didWarnAboutUnstableCreatePortal = false;
+5 -24
View File
@@ -44,16 +44,6 @@ import {
discreteUpdates,
} from './ReactDOMUpdateBatching';
import {
InputContinuousLanePriority as InputContinuousLanePriority_old,
getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_old,
setCurrentUpdateLanePriority as setCurrentUpdateLanePriority_old,
} from 'react-reconciler/src/ReactFiberLane.old';
import {
InputContinuousLanePriority as InputContinuousLanePriority_new,
getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_new,
setCurrentUpdateLanePriority as setCurrentUpdateLanePriority_new,
} from 'react-reconciler/src/ReactFiberLane.new';
import {getCurrentPriorityLevel as getCurrentPriorityLevel_old} from 'react-reconciler/src/SchedulerWithReactIntegration.old';
import {
getCurrentPriorityLevel as getCurrentPriorityLevel_new,
@@ -68,19 +58,10 @@ import {
ContinuousEventPriority,
DefaultEventPriority,
IdleEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
} from 'react-reconciler/src/ReactEventPriorities';
// TODO: These should use the opaque EventPriority type instead of LanePriority.
// Then internally we can use a Lane.
const InputContinuousLanePriority = enableNewReconciler
? InputContinuousLanePriority_new
: InputContinuousLanePriority_old;
const getCurrentUpdateLanePriority = enableNewReconciler
? getCurrentUpdateLanePriority_new
: getCurrentUpdateLanePriority_old;
const setCurrentUpdateLanePriority = enableNewReconciler
? setCurrentUpdateLanePriority_new
: setCurrentUpdateLanePriority_old;
const getCurrentPriorityLevel = enableNewReconciler
? getCurrentPriorityLevel_new
: getCurrentPriorityLevel_old;
@@ -167,12 +148,12 @@ function dispatchContinuousEvent(
container,
nativeEvent,
) {
const previousPriority = getCurrentUpdateLanePriority();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(InputContinuousLanePriority);
setCurrentUpdatePriority(ContinuousEventPriority);
dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);
} finally {
setCurrentUpdateLanePriority(previousPriority);
setCurrentUpdatePriority(previousPriority);
}
}
+18 -10
View File
@@ -12,7 +12,7 @@ import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig';
import type {DOMEventName} from '../events/DOMEventNames';
import type {EventSystemFlags} from './EventSystemFlags';
import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
import type {LanePriority} from 'react-reconciler/src/ReactFiberLane.old';
import type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';
import {enableSelectiveHydration} from 'shared/ReactFeatureFlags';
import {
@@ -30,6 +30,7 @@ import {
getClosestInstanceFromNode,
} from '../client/ReactDOMComponentTree';
import {HostRoot, SuspenseComponent} from 'react-reconciler/src/ReactWorkTags';
import {isHigherEventPriority} from 'react-reconciler/src/ReactEventPriorities';
let attemptSynchronousHydration: (fiber: Object) => void;
@@ -57,16 +58,16 @@ export function setAttemptHydrationAtCurrentPriority(
attemptHydrationAtCurrentPriority = fn;
}
let getCurrentUpdatePriority: () => LanePriority;
let getCurrentUpdatePriority: () => EventPriority;
export function setGetCurrentUpdatePriority(fn: () => LanePriority) {
export function setGetCurrentUpdatePriority(fn: () => EventPriority) {
getCurrentUpdatePriority = fn;
}
let attemptHydrationAtPriority: <T>(priority: LanePriority, fn: () => T) => T;
let attemptHydrationAtPriority: <T>(priority: EventPriority, fn: () => T) => T;
export function setAttemptHydrationAtPriority(
fn: <T>(priority: LanePriority, fn: () => T) => T,
fn: <T>(priority: EventPriority, fn: () => T) => T,
) {
attemptHydrationAtPriority = fn;
}
@@ -109,7 +110,7 @@ const queuedPointerCaptures: Map<number, QueuedReplayableEvent> = new Map();
type QueuedHydrationTarget = {|
blockedOn: null | Container | SuspenseInstance,
target: Node,
lanePriority: LanePriority,
priority: EventPriority,
|};
const queuedExplicitHydrationTargets: Array<QueuedHydrationTarget> = [];
@@ -390,7 +391,7 @@ function attemptExplicitHydrationTarget(
// We're blocked on hydrating this boundary.
// Increase its priority.
queuedTarget.blockedOn = instance;
attemptHydrationAtPriority(queuedTarget.lanePriority, () => {
attemptHydrationAtPriority(queuedTarget.priority, () => {
attemptHydrationAtCurrentPriority(nearestMounted);
});
@@ -412,16 +413,23 @@ function attemptExplicitHydrationTarget(
export function queueExplicitHydrationTarget(target: Node): void {
if (enableSelectiveHydration) {
const updateLanePriority = getCurrentUpdatePriority();
// TODO: This will read the priority if it's dispatched by the React
// event system but not native events. Should read window.event.type, like
// we do for updates (getCurrentEventPriority).
const updatePriority = getCurrentUpdatePriority();
const queuedTarget: QueuedHydrationTarget = {
blockedOn: null,
target: target,
lanePriority: updateLanePriority,
priority: updatePriority,
};
let i = 0;
for (; i < queuedExplicitHydrationTargets.length; i++) {
// Stop once we hit the first target with lower priority than
if (
updateLanePriority <= queuedExplicitHydrationTargets[i].lanePriority
!isHigherEventPriority(
updatePriority,
queuedExplicitHydrationTargets[i].priority,
)
) {
break;
}
+49 -12
View File
@@ -14,6 +14,10 @@ import {
ContinuousEventPriority as ContinuousEventPriority_old,
DefaultEventPriority as DefaultEventPriority_old,
IdleEventPriority as IdleEventPriority_old,
getCurrentUpdatePriority as getCurrentUpdatePriority_old,
setCurrentUpdatePriority as setCurrentUpdatePriority_old,
runWithPriority as runWithPriority_old,
isHigherEventPriority as isHigherEventPriority_old,
} from './ReactEventPriorities.old';
import {
@@ -21,17 +25,50 @@ import {
ContinuousEventPriority as ContinuousEventPriority_new,
DefaultEventPriority as DefaultEventPriority_new,
IdleEventPriority as IdleEventPriority_new,
getCurrentUpdatePriority as getCurrentUpdatePriority_new,
setCurrentUpdatePriority as setCurrentUpdatePriority_new,
runWithPriority as runWithPriority_new,
isHigherEventPriority as isHigherEventPriority_new,
} from './ReactEventPriorities.new';
export const DiscreteEventPriority = enableNewReconciler
? DiscreteEventPriority_new
: DiscreteEventPriority_old;
export const ContinuousEventPriority = enableNewReconciler
? ContinuousEventPriority_new
: ContinuousEventPriority_old;
export const DefaultEventPriority = enableNewReconciler
? DefaultEventPriority_new
: DefaultEventPriority_old;
export const IdleEventPriority = enableNewReconciler
? IdleEventPriority_new
: IdleEventPriority_old;
export opaque type EventPriority = number;
export const DiscreteEventPriority: EventPriority = enableNewReconciler
? (DiscreteEventPriority_new: any)
: (DiscreteEventPriority_old: any);
export const ContinuousEventPriority: EventPriority = enableNewReconciler
? (ContinuousEventPriority_new: any)
: (ContinuousEventPriority_old: any);
export const DefaultEventPriority: EventPriority = enableNewReconciler
? (DefaultEventPriority_new: any)
: (DefaultEventPriority_old: any);
export const IdleEventPriority: EventPriority = enableNewReconciler
? (IdleEventPriority_new: any)
: (IdleEventPriority_old: any);
export function runWithPriority<T>(priority: EventPriority, fn: () => T): T {
return enableNewReconciler
? runWithPriority_new((priority: any), fn)
: runWithPriority_old((priority: any), fn);
}
export function getCurrentUpdatePriority(): EventPriority {
return enableNewReconciler
? (getCurrentUpdatePriority_new(): any)
: (getCurrentUpdatePriority_old(): any);
}
export function setCurrentUpdatePriority(priority: EventPriority) {
return enableNewReconciler
? setCurrentUpdatePriority_new((priority: any))
: setCurrentUpdatePriority_old((priority: any));
}
export function isHigherEventPriority(
a: EventPriority,
b: EventPriority,
): boolean {
return enableNewReconciler
? isHigherEventPriority_new((a: any), (b: any))
: isHigherEventPriority_old((a: any), (b: any));
}
@@ -7,9 +7,69 @@
* @flow
*/
export {
SyncLane as DiscreteEventPriority,
InputContinuousLane as ContinuousEventPriority,
DefaultLane as DefaultEventPriority,
IdleLane as IdleEventPriority,
import type {Lane, Lanes} from './ReactFiberLane.new';
import {
NoLane,
SyncLane,
InputContinuousLane,
DefaultLane,
IdleLane,
getHighestPriorityLane,
includesNonIdleWork,
} from './ReactFiberLane.new';
export opaque type EventPriority = Lane;
export const DiscreteEventPriority: EventPriority = SyncLane;
export const ContinuousEventPriority: EventPriority = InputContinuousLane;
export const DefaultEventPriority: EventPriority = DefaultLane;
export const IdleEventPriority: EventPriority = IdleLane;
let currentUpdatePriority: EventPriority = NoLane;
export function getCurrentUpdatePriority(): EventPriority {
return currentUpdatePriority;
}
export function setCurrentUpdatePriority(newPriority: EventPriority) {
currentUpdatePriority = newPriority;
}
export function runWithPriority<T>(priority: EventPriority, fn: () => T): T {
const previousPriority = currentUpdatePriority;
try {
currentUpdatePriority = priority;
return fn();
} finally {
currentUpdatePriority = previousPriority;
}
}
export function higherEventPriority(
a: EventPriority,
b: EventPriority,
): EventPriority {
return a !== 0 && a < b ? a : b;
}
export function isHigherEventPriority(
a: EventPriority,
b: EventPriority,
): boolean {
return a !== 0 && a < b;
}
export function lanesToEventPriority(lanes: Lanes): EventPriority {
const lane = getHighestPriorityLane(lanes);
if (!isHigherEventPriority(DiscreteEventPriority, lane)) {
return DiscreteEventPriority;
}
if (!isHigherEventPriority(ContinuousEventPriority, lane)) {
return ContinuousEventPriority;
}
if (includesNonIdleWork(lane)) {
return DefaultEventPriority;
}
return IdleEventPriority;
}
@@ -7,9 +7,69 @@
* @flow
*/
export {
SyncLane as DiscreteEventPriority,
InputContinuousLane as ContinuousEventPriority,
DefaultLane as DefaultEventPriority,
IdleLane as IdleEventPriority,
import type {Lane, Lanes} from './ReactFiberLane.old';
import {
NoLane,
SyncLane,
InputContinuousLane,
DefaultLane,
IdleLane,
getHighestPriorityLane,
includesNonIdleWork,
} from './ReactFiberLane.old';
export opaque type EventPriority = Lane;
export const DiscreteEventPriority: EventPriority = SyncLane;
export const ContinuousEventPriority: EventPriority = InputContinuousLane;
export const DefaultEventPriority: EventPriority = DefaultLane;
export const IdleEventPriority: EventPriority = IdleLane;
let currentUpdatePriority: EventPriority = NoLane;
export function getCurrentUpdatePriority(): EventPriority {
return currentUpdatePriority;
}
export function setCurrentUpdatePriority(newPriority: EventPriority) {
currentUpdatePriority = newPriority;
}
export function runWithPriority<T>(priority: EventPriority, fn: () => T): T {
const previousPriority = currentUpdatePriority;
try {
currentUpdatePriority = priority;
return fn();
} finally {
currentUpdatePriority = previousPriority;
}
}
export function higherEventPriority(
a: EventPriority,
b: EventPriority,
): EventPriority {
return a !== 0 && a < b ? a : b;
}
export function isHigherEventPriority(
a: EventPriority,
b: EventPriority,
): boolean {
return a !== 0 && a < b;
}
export function lanesToEventPriority(lanes: Lanes): EventPriority {
const lane = getHighestPriorityLane(lanes);
if (!isHigherEventPriority(DiscreteEventPriority, lane)) {
return DiscreteEventPriority;
}
if (!isHigherEventPriority(ContinuousEventPriority, lane)) {
return ContinuousEventPriority;
}
if (includesNonIdleWork(lane)) {
return DefaultEventPriority;
}
return IdleEventPriority;
}
@@ -17,7 +17,7 @@ import type {
} from './ReactFiberHostConfig';
import type {Fiber} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {LanePriority, Lanes} from './ReactFiberLane.new';
import type {Lanes} from './ReactFiberLane.new';
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
import type {UpdateQueue} from './ReactUpdateQueue.new';
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.new';
@@ -1067,7 +1067,6 @@ function commitUnmount(
finishedRoot: FiberRoot,
current: Fiber,
nearestMountedAncestor: Fiber,
renderPriorityLevel: LanePriority,
): void {
onCommitUnmount(current);
@@ -1127,12 +1126,7 @@ function commitUnmount(
// We are also not using this parent because
// the portal will get pushed immediately.
if (supportsMutation) {
unmountHostComponents(
finishedRoot,
current,
nearestMountedAncestor,
renderPriorityLevel,
);
unmountHostComponents(finishedRoot, current, nearestMountedAncestor);
} else if (supportsPersistence) {
emptyPortalContainer(current);
}
@@ -1163,7 +1157,6 @@ function commitNestedUnmounts(
finishedRoot: FiberRoot,
root: Fiber,
nearestMountedAncestor: Fiber,
renderPriorityLevel: LanePriority,
): void {
// While we're inside a removed host node we don't want to call
// removeChild on the inner nodes because they're removed by the top
@@ -1172,12 +1165,7 @@ function commitNestedUnmounts(
// we do an inner loop while we're still inside the host node.
let node: Fiber = root;
while (true) {
commitUnmount(
finishedRoot,
node,
nearestMountedAncestor,
renderPriorityLevel,
);
commitUnmount(finishedRoot, node, nearestMountedAncestor);
// Visit children because they may contain more composite or host nodes.
// Skip portals because commitUnmount() currently visits them recursively.
if (
@@ -1532,7 +1520,6 @@ function unmountHostComponents(
finishedRoot: FiberRoot,
current: Fiber,
nearestMountedAncestor: Fiber,
renderPriorityLevel: LanePriority,
): void {
// We only have the top Fiber that was deleted but we need to recurse down its
// children to find all the terminal nodes.
@@ -1576,12 +1563,7 @@ function unmountHostComponents(
}
if (node.tag === HostComponent || node.tag === HostText) {
commitNestedUnmounts(
finishedRoot,
node,
nearestMountedAncestor,
renderPriorityLevel,
);
commitNestedUnmounts(finishedRoot, node, nearestMountedAncestor);
// After all the children have unmounted, it is now safe to remove the
// node from the tree.
if (currentParentIsContainer) {
@@ -1634,12 +1616,7 @@ function unmountHostComponents(
continue;
}
} else {
commitUnmount(
finishedRoot,
node,
nearestMountedAncestor,
renderPriorityLevel,
);
commitUnmount(finishedRoot, node, nearestMountedAncestor);
// Visit children because we may find more host components below.
if (node.child !== null) {
node.child.return = node;
@@ -1670,25 +1647,14 @@ function commitDeletion(
finishedRoot: FiberRoot,
current: Fiber,
nearestMountedAncestor: Fiber,
renderPriorityLevel: LanePriority,
): void {
if (supportsMutation) {
// Recursively delete all host nodes from the parent.
// Detach refs and call componentWillUnmount() on the whole subtree.
unmountHostComponents(
finishedRoot,
current,
nearestMountedAncestor,
renderPriorityLevel,
);
unmountHostComponents(finishedRoot, current, nearestMountedAncestor);
} else {
// Detach refs and call componentWillUnmount() on the whole subtree.
commitNestedUnmounts(
finishedRoot,
current,
nearestMountedAncestor,
renderPriorityLevel,
);
commitNestedUnmounts(finishedRoot, current, nearestMountedAncestor);
}
detachFiberMutation(current);
@@ -2009,19 +1975,12 @@ function commitResetTextContent(current: Fiber) {
resetTextContent(current.stateNode);
}
export function commitMutationEffects(
root: FiberRoot,
renderPriorityLevel: LanePriority,
firstChild: Fiber,
) {
export function commitMutationEffects(root: FiberRoot, firstChild: Fiber) {
nextEffect = firstChild;
commitMutationEffects_begin(root, renderPriorityLevel);
commitMutationEffects_begin(root);
}
function commitMutationEffects_begin(
root: FiberRoot,
renderPriorityLevel: LanePriority,
) {
function commitMutationEffects_begin(root: FiberRoot) {
while (nextEffect !== null) {
const fiber = nextEffect;
@@ -2038,7 +1997,6 @@ function commitMutationEffects_begin(
root,
childToDelete,
fiber,
renderPriorityLevel,
);
if (hasCaughtError()) {
const error = clearCaughtError();
@@ -2046,7 +2004,7 @@ function commitMutationEffects_begin(
}
} else {
try {
commitDeletion(root, childToDelete, fiber, renderPriorityLevel);
commitDeletion(root, childToDelete, fiber);
} catch (error) {
captureCommitPhaseError(childToDelete, fiber, error);
}
@@ -2059,15 +2017,12 @@ function commitMutationEffects_begin(
ensureCorrectReturnPointer(child, fiber);
nextEffect = child;
} else {
commitMutationEffects_complete(root, renderPriorityLevel);
commitMutationEffects_complete(root);
}
}
}
function commitMutationEffects_complete(
root: FiberRoot,
renderPriorityLevel: LanePriority,
) {
function commitMutationEffects_complete(root: FiberRoot) {
while (nextEffect !== null) {
const fiber = nextEffect;
if (__DEV__) {
@@ -2078,7 +2033,6 @@ function commitMutationEffects_complete(
null,
fiber,
root,
renderPriorityLevel,
);
if (hasCaughtError()) {
const error = clearCaughtError();
@@ -2087,7 +2041,7 @@ function commitMutationEffects_complete(
resetCurrentDebugFiberInDEV();
} else {
try {
commitMutationEffectsOnFiber(fiber, root, renderPriorityLevel);
commitMutationEffectsOnFiber(fiber, root);
} catch (error) {
captureCommitPhaseError(fiber, fiber.return, error);
}
@@ -2104,11 +2058,7 @@ function commitMutationEffects_complete(
}
}
function commitMutationEffectsOnFiber(
finishedWork: Fiber,
root: FiberRoot,
renderPriorityLevel: LanePriority,
) {
function commitMutationEffectsOnFiber(finishedWork: Fiber, root: FiberRoot) {
const flags = finishedWork.flags;
if (flags & ContentReset) {
@@ -17,7 +17,7 @@ import type {
} from './ReactFiberHostConfig';
import type {Fiber} from './ReactInternalTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {LanePriority, Lanes} from './ReactFiberLane.old';
import type {Lanes} from './ReactFiberLane.old';
import type {SuspenseState} from './ReactFiberSuspenseComponent.old';
import type {UpdateQueue} from './ReactUpdateQueue.old';
import type {FunctionComponentUpdateQueue} from './ReactFiberHooks.old';
@@ -1067,7 +1067,6 @@ function commitUnmount(
finishedRoot: FiberRoot,
current: Fiber,
nearestMountedAncestor: Fiber,
renderPriorityLevel: LanePriority,
): void {
onCommitUnmount(current);
@@ -1127,12 +1126,7 @@ function commitUnmount(
// We are also not using this parent because
// the portal will get pushed immediately.
if (supportsMutation) {
unmountHostComponents(
finishedRoot,
current,
nearestMountedAncestor,
renderPriorityLevel,
);
unmountHostComponents(finishedRoot, current, nearestMountedAncestor);
} else if (supportsPersistence) {
emptyPortalContainer(current);
}
@@ -1163,7 +1157,6 @@ function commitNestedUnmounts(
finishedRoot: FiberRoot,
root: Fiber,
nearestMountedAncestor: Fiber,
renderPriorityLevel: LanePriority,
): void {
// While we're inside a removed host node we don't want to call
// removeChild on the inner nodes because they're removed by the top
@@ -1172,12 +1165,7 @@ function commitNestedUnmounts(
// we do an inner loop while we're still inside the host node.
let node: Fiber = root;
while (true) {
commitUnmount(
finishedRoot,
node,
nearestMountedAncestor,
renderPriorityLevel,
);
commitUnmount(finishedRoot, node, nearestMountedAncestor);
// Visit children because they may contain more composite or host nodes.
// Skip portals because commitUnmount() currently visits them recursively.
if (
@@ -1532,7 +1520,6 @@ function unmountHostComponents(
finishedRoot: FiberRoot,
current: Fiber,
nearestMountedAncestor: Fiber,
renderPriorityLevel: LanePriority,
): void {
// We only have the top Fiber that was deleted but we need to recurse down its
// children to find all the terminal nodes.
@@ -1576,12 +1563,7 @@ function unmountHostComponents(
}
if (node.tag === HostComponent || node.tag === HostText) {
commitNestedUnmounts(
finishedRoot,
node,
nearestMountedAncestor,
renderPriorityLevel,
);
commitNestedUnmounts(finishedRoot, node, nearestMountedAncestor);
// After all the children have unmounted, it is now safe to remove the
// node from the tree.
if (currentParentIsContainer) {
@@ -1634,12 +1616,7 @@ function unmountHostComponents(
continue;
}
} else {
commitUnmount(
finishedRoot,
node,
nearestMountedAncestor,
renderPriorityLevel,
);
commitUnmount(finishedRoot, node, nearestMountedAncestor);
// Visit children because we may find more host components below.
if (node.child !== null) {
node.child.return = node;
@@ -1670,25 +1647,14 @@ function commitDeletion(
finishedRoot: FiberRoot,
current: Fiber,
nearestMountedAncestor: Fiber,
renderPriorityLevel: LanePriority,
): void {
if (supportsMutation) {
// Recursively delete all host nodes from the parent.
// Detach refs and call componentWillUnmount() on the whole subtree.
unmountHostComponents(
finishedRoot,
current,
nearestMountedAncestor,
renderPriorityLevel,
);
unmountHostComponents(finishedRoot, current, nearestMountedAncestor);
} else {
// Detach refs and call componentWillUnmount() on the whole subtree.
commitNestedUnmounts(
finishedRoot,
current,
nearestMountedAncestor,
renderPriorityLevel,
);
commitNestedUnmounts(finishedRoot, current, nearestMountedAncestor);
}
detachFiberMutation(current);
@@ -2009,19 +1975,12 @@ function commitResetTextContent(current: Fiber) {
resetTextContent(current.stateNode);
}
export function commitMutationEffects(
root: FiberRoot,
renderPriorityLevel: LanePriority,
firstChild: Fiber,
) {
export function commitMutationEffects(root: FiberRoot, firstChild: Fiber) {
nextEffect = firstChild;
commitMutationEffects_begin(root, renderPriorityLevel);
commitMutationEffects_begin(root);
}
function commitMutationEffects_begin(
root: FiberRoot,
renderPriorityLevel: LanePriority,
) {
function commitMutationEffects_begin(root: FiberRoot) {
while (nextEffect !== null) {
const fiber = nextEffect;
@@ -2038,7 +1997,6 @@ function commitMutationEffects_begin(
root,
childToDelete,
fiber,
renderPriorityLevel,
);
if (hasCaughtError()) {
const error = clearCaughtError();
@@ -2046,7 +2004,7 @@ function commitMutationEffects_begin(
}
} else {
try {
commitDeletion(root, childToDelete, fiber, renderPriorityLevel);
commitDeletion(root, childToDelete, fiber);
} catch (error) {
captureCommitPhaseError(childToDelete, fiber, error);
}
@@ -2059,15 +2017,12 @@ function commitMutationEffects_begin(
ensureCorrectReturnPointer(child, fiber);
nextEffect = child;
} else {
commitMutationEffects_complete(root, renderPriorityLevel);
commitMutationEffects_complete(root);
}
}
}
function commitMutationEffects_complete(
root: FiberRoot,
renderPriorityLevel: LanePriority,
) {
function commitMutationEffects_complete(root: FiberRoot) {
while (nextEffect !== null) {
const fiber = nextEffect;
if (__DEV__) {
@@ -2078,7 +2033,6 @@ function commitMutationEffects_complete(
null,
fiber,
root,
renderPriorityLevel,
);
if (hasCaughtError()) {
const error = clearCaughtError();
@@ -2087,7 +2041,7 @@ function commitMutationEffects_complete(
resetCurrentDebugFiberInDEV();
} else {
try {
commitMutationEffectsOnFiber(fiber, root, renderPriorityLevel);
commitMutationEffectsOnFiber(fiber, root);
} catch (error) {
captureCommitPhaseError(fiber, fiber.return, error);
}
@@ -2104,11 +2058,7 @@ function commitMutationEffects_complete(
}
}
function commitMutationEffectsOnFiber(
finishedWork: Fiber,
root: FiberRoot,
renderPriorityLevel: LanePriority,
) {
function commitMutationEffectsOnFiber(finishedWork: Fiber, root: FiberRoot) {
const flags = finishedWork.flags;
if (flags & ContentReset) {
@@ -11,14 +11,21 @@ import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
import type {Fiber, FiberRoot} from './ReactInternalTypes';
import type {ReactNodeList} from 'shared/ReactTypes';
import type {LanePriority} from './ReactFiberLane.new';
import type {EventPriority} from './ReactEventPriorities.new';
import {DidCapture} from './ReactFiberFlags';
import {
lanePriorityToSchedulerPriority,
NoLanePriority,
} from './ReactFiberLane.new';
import {NormalPriority} from './SchedulerWithReactIntegration.new';
DiscreteEventPriority,
ContinuousEventPriority,
DefaultEventPriority,
IdleEventPriority,
} from './ReactEventPriorities.new';
import {
ImmediatePriority as ImmediateSchedulerPriority,
UserBlockingPriority as UserBlockingSchedulerPriority,
NormalPriority as NormalSchedulerPriority,
IdlePriority as IdleSchedulerPriority,
} from './SchedulerWithReactIntegration.new';
declare var __REACT_DEVTOOLS_GLOBAL_HOOK__: Object | void;
@@ -84,15 +91,29 @@ export function onScheduleRoot(root: FiberRoot, children: ReactNodeList) {
}
}
export function onCommitRoot(root: FiberRoot, priorityLevel: LanePriority) {
export function onCommitRoot(root: FiberRoot, eventPriority: EventPriority) {
if (injectedHook && typeof injectedHook.onCommitFiberRoot === 'function') {
try {
const didError = (root.current.flags & DidCapture) === DidCapture;
if (enableProfilerTimer) {
const schedulerPriority =
priorityLevel === NoLanePriority
? NormalPriority
: lanePriorityToSchedulerPriority(priorityLevel);
let schedulerPriority;
switch (eventPriority) {
case DiscreteEventPriority:
schedulerPriority = ImmediateSchedulerPriority;
break;
case ContinuousEventPriority:
schedulerPriority = UserBlockingSchedulerPriority;
break;
case DefaultEventPriority:
schedulerPriority = NormalSchedulerPriority;
break;
case IdleEventPriority:
schedulerPriority = IdleSchedulerPriority;
break;
default:
schedulerPriority = NormalSchedulerPriority;
break;
}
injectedHook.onCommitFiberRoot(
rendererID,
root,
@@ -11,14 +11,21 @@ import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
import type {Fiber, FiberRoot} from './ReactInternalTypes';
import type {ReactNodeList} from 'shared/ReactTypes';
import type {LanePriority} from './ReactFiberLane.old';
import type {EventPriority} from './ReactEventPriorities.old';
import {DidCapture} from './ReactFiberFlags';
import {
lanePriorityToSchedulerPriority,
NoLanePriority,
} from './ReactFiberLane.old';
import {NormalPriority} from './SchedulerWithReactIntegration.old';
DiscreteEventPriority,
ContinuousEventPriority,
DefaultEventPriority,
IdleEventPriority,
} from './ReactEventPriorities.old';
import {
ImmediatePriority as ImmediateSchedulerPriority,
UserBlockingPriority as UserBlockingSchedulerPriority,
NormalPriority as NormalSchedulerPriority,
IdlePriority as IdleSchedulerPriority,
} from './SchedulerWithReactIntegration.old';
declare var __REACT_DEVTOOLS_GLOBAL_HOOK__: Object | void;
@@ -84,15 +91,29 @@ export function onScheduleRoot(root: FiberRoot, children: ReactNodeList) {
}
}
export function onCommitRoot(root: FiberRoot, priorityLevel: LanePriority) {
export function onCommitRoot(root: FiberRoot, eventPriority: EventPriority) {
if (injectedHook && typeof injectedHook.onCommitFiberRoot === 'function') {
try {
const didError = (root.current.flags & DidCapture) === DidCapture;
if (enableProfilerTimer) {
const schedulerPriority =
priorityLevel === NoLanePriority
? NormalPriority
: lanePriorityToSchedulerPriority(priorityLevel);
let schedulerPriority;
switch (eventPriority) {
case DiscreteEventPriority:
schedulerPriority = ImmediateSchedulerPriority;
break;
case ContinuousEventPriority:
schedulerPriority = UserBlockingSchedulerPriority;
break;
case DefaultEventPriority:
schedulerPriority = NormalSchedulerPriority;
break;
case IdleEventPriority:
schedulerPriority = IdleSchedulerPriority;
break;
default:
schedulerPriority = NormalSchedulerPriority;
break;
}
injectedHook.onCommitFiberRoot(
rendererID,
root,
@@ -41,7 +41,6 @@ import {
import {
NoLane,
NoLanes,
InputContinuousLanePriority,
isSubsetOfLanes,
mergeLanes,
removeLanes,
@@ -49,11 +48,14 @@ import {
isTransitionLane,
markRootEntangled,
markRootMutableRead,
getCurrentUpdateLanePriority,
setCurrentUpdateLanePriority,
higherLanePriority,
DefaultLanePriority,
} from './ReactFiberLane.new';
import {
DefaultEventPriority,
ContinuousEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
higherEventPriority,
} from './ReactEventPriorities.new';
import {readContext, checkIfContextChanged} from './ReactFiberNewContext.new';
import {HostRoot, CacheComponent} from './ReactWorkTags';
import {
@@ -1705,9 +1707,9 @@ function rerenderDeferredValue<T>(value: T): T {
}
function startTransition(setPending, callback) {
const previousLanePriority = getCurrentUpdateLanePriority();
setCurrentUpdateLanePriority(
higherLanePriority(previousLanePriority, InputContinuousLanePriority),
const previousPriority = getCurrentUpdatePriority();
setCurrentUpdatePriority(
higherEventPriority(previousPriority, ContinuousEventPriority),
);
setPending(true);
@@ -1715,7 +1717,7 @@ function startTransition(setPending, callback) {
// TODO: Can remove this. Was only necessary because we used to give
// different behavior to transitions without a config object. Now they are
// all treated the same.
setCurrentUpdateLanePriority(DefaultLanePriority);
setCurrentUpdatePriority(DefaultEventPriority);
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
@@ -1723,7 +1725,7 @@ function startTransition(setPending, callback) {
setPending(false);
callback();
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
ReactCurrentBatchConfig.transition = prevTransition;
}
}
@@ -41,7 +41,6 @@ import {
import {
NoLane,
NoLanes,
InputContinuousLanePriority,
isSubsetOfLanes,
mergeLanes,
removeLanes,
@@ -49,11 +48,14 @@ import {
isTransitionLane,
markRootEntangled,
markRootMutableRead,
getCurrentUpdateLanePriority,
setCurrentUpdateLanePriority,
higherLanePriority,
DefaultLanePriority,
} from './ReactFiberLane.old';
import {
DefaultEventPriority,
ContinuousEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
higherEventPriority,
} from './ReactEventPriorities.old';
import {readContext, checkIfContextChanged} from './ReactFiberNewContext.old';
import {HostRoot, CacheComponent} from './ReactWorkTags';
import {
@@ -1705,9 +1707,9 @@ function rerenderDeferredValue<T>(value: T): T {
}
function startTransition(setPending, callback) {
const previousLanePriority = getCurrentUpdateLanePriority();
setCurrentUpdateLanePriority(
higherLanePriority(previousLanePriority, InputContinuousLanePriority),
const previousPriority = getCurrentUpdatePriority();
setCurrentUpdatePriority(
higherEventPriority(previousPriority, ContinuousEventPriority),
);
setPending(true);
@@ -1715,7 +1717,7 @@ function startTransition(setPending, callback) {
// TODO: Can remove this. Was only necessary because we used to give
// different behavior to transitions without a config object. Now they are
// all treated the same.
setCurrentUpdateLanePriority(DefaultLanePriority);
setCurrentUpdatePriority(DefaultEventPriority);
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
@@ -1723,7 +1725,7 @@ function startTransition(setPending, callback) {
setPending(false);
callback();
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
ReactCurrentBatchConfig.transition = prevTransition;
}
}
@@ -73,8 +73,8 @@ export const NoLanePriority: LanePriority = 0;
export const TotalLanes = 31;
export const NoLanes: Lanes = /* */ 0b000000000000000000000000000000;
export const NoLane: Lane = /* */ 0b000000000000000000000000000000;
export const NoLanes: Lanes = /* */ 0b0000000000000000000000000000000;
export const NoLane: Lane = /* */ 0b0000000000000000000000000000000;
export const SyncLane: Lane = /* */ 0b0000000000000000000000000000001;
@@ -168,19 +168,9 @@ export function getLabelsForLanes(lanes: Lanes): Array<string> | void {
export const NoTimestamp = -1;
let currentUpdateLanePriority: LanePriority = NoLanePriority;
let nextTransitionLane: Lane = TransitionLane1;
let nextRetryLane: Lane = RetryLane1;
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;
@@ -532,35 +522,6 @@ export function isTransitionLane(lane: Lane) {
return (lane & TransitionLanes) !== 0;
}
// To ensure consistency across multiple updates in the same event, this should
// be a pure function, so that it always returns the same lane for given inputs.
export function findUpdateLane(lanePriority: LanePriority): Lane {
switch (lanePriority) {
case NoLanePriority:
break;
case SyncLanePriority:
return SyncLane;
case InputContinuousLanePriority:
return InputContinuousLane;
case DefaultLanePriority:
return DefaultLane;
case TransitionPriority: // Should be handled by findTransitionLane instead
case RetryLanePriority: // Should be handled by findRetryLane instead
break;
case IdleLanePriority:
return IdleLane;
default:
// The remaining priorities are not valid for updates
break;
}
invariant(
false,
'Invalid update priority: %s. This is a bug in React.',
lanePriority,
);
}
export function claimNextTransitionLane(): Lane {
// Cycle through the lanes, assigning each new transition to the next lane.
// In most cases, this means every transition gets its own lane, until we
@@ -582,7 +543,7 @@ export function claimNextRetryLane(): Lane {
return lane;
}
function getHighestPriorityLane(lanes: Lanes) {
export function getHighestPriorityLane(lanes: Lanes): Lane {
return lanes & -lanes;
}
@@ -73,8 +73,8 @@ export const NoLanePriority: LanePriority = 0;
export const TotalLanes = 31;
export const NoLanes: Lanes = /* */ 0b000000000000000000000000000000;
export const NoLane: Lane = /* */ 0b000000000000000000000000000000;
export const NoLanes: Lanes = /* */ 0b0000000000000000000000000000000;
export const NoLane: Lane = /* */ 0b0000000000000000000000000000000;
export const SyncLane: Lane = /* */ 0b0000000000000000000000000000001;
@@ -168,19 +168,9 @@ export function getLabelsForLanes(lanes: Lanes): Array<string> | void {
export const NoTimestamp = -1;
let currentUpdateLanePriority: LanePriority = NoLanePriority;
let nextTransitionLane: Lane = TransitionLane1;
let nextRetryLane: Lane = RetryLane1;
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;
@@ -532,35 +522,6 @@ export function isTransitionLane(lane: Lane) {
return (lane & TransitionLanes) !== 0;
}
// To ensure consistency across multiple updates in the same event, this should
// be a pure function, so that it always returns the same lane for given inputs.
export function findUpdateLane(lanePriority: LanePriority): Lane {
switch (lanePriority) {
case NoLanePriority:
break;
case SyncLanePriority:
return SyncLane;
case InputContinuousLanePriority:
return InputContinuousLane;
case DefaultLanePriority:
return DefaultLane;
case TransitionPriority: // Should be handled by findTransitionLane instead
case RetryLanePriority: // Should be handled by findRetryLane instead
break;
case IdleLanePriority:
return IdleLane;
default:
// The remaining priorities are not valid for updates
break;
}
invariant(
false,
'Invalid update priority: %s. This is a bug in React.',
lanePriority,
);
}
export function claimNextTransitionLane(): Lane {
// Cycle through the lanes, assigning each new transition to the next lane.
// In most cases, this means every transition gets its own lane, until we
@@ -582,7 +543,7 @@ export function claimNextRetryLane(): Lane {
return lane;
}
function getHighestPriorityLane(lanes: Lanes) {
export function getHighestPriorityLane(lanes: Lanes): Lane {
return lanes & -lanes;
}
+5 -5
View File
@@ -51,7 +51,7 @@ import {
observeVisibleRects as observeVisibleRects_old,
registerMutableSourceForHydration as registerMutableSourceForHydration_old,
runWithPriority as runWithPriority_old,
getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_old,
getCurrentUpdatePriority as getCurrentUpdatePriority_old,
} from './ReactFiberReconciler.old';
import {
@@ -91,7 +91,7 @@ import {
observeVisibleRects as observeVisibleRects_new,
registerMutableSourceForHydration as registerMutableSourceForHydration_new,
runWithPriority as runWithPriority_new,
getCurrentUpdateLanePriority as getCurrentUpdateLanePriority_new,
getCurrentUpdatePriority as getCurrentUpdatePriority_new,
} from './ReactFiberReconciler.new';
export const createContainer = enableNewReconciler
@@ -143,9 +143,9 @@ export const attemptContinuousHydration = enableNewReconciler
export const attemptHydrationAtCurrentPriority = enableNewReconciler
? attemptHydrationAtCurrentPriority_new
: attemptHydrationAtCurrentPriority_old;
export const getCurrentUpdateLanePriority = enableNewReconciler
? getCurrentUpdateLanePriority_new
: getCurrentUpdateLanePriority_old;
export const getCurrentUpdatePriority = enableNewReconciler
? getCurrentUpdatePriority_new
: getCurrentUpdatePriority_old;
export const findHostInstance = enableNewReconciler
? findHostInstance_new
: findHostInstance_old;
@@ -18,7 +18,7 @@ import type {
} from './ReactFiberHostConfig';
import type {RendererInspectionConfig} from './ReactFiberHostConfig';
import type {ReactNodeList} from 'shared/ReactTypes';
import type {Lane, LanePriority} from './ReactFiberLane.new';
import type {Lane} from './ReactFiberLane.new';
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
import {
@@ -82,9 +82,11 @@ import {
NoTimestamp,
getHighestPriorityPendingLanes,
higherPriorityLane,
getCurrentUpdateLanePriority,
setCurrentUpdateLanePriority,
} from './ReactFiberLane.new';
import {
getCurrentUpdatePriority,
runWithPriority,
} from './ReactEventPriorities.new';
import {
scheduleRefresh,
scheduleRoot,
@@ -442,17 +444,7 @@ export function attemptHydrationAtCurrentPriority(fiber: Fiber): void {
markRetryLaneIfNotHydrated(fiber, lane);
}
export function runWithPriority<T>(priority: LanePriority, fn: () => T) {
const previousPriority = getCurrentUpdateLanePriority();
try {
setCurrentUpdateLanePriority(priority);
return fn();
} finally {
setCurrentUpdateLanePriority(previousPriority);
}
}
export {getCurrentUpdateLanePriority};
export {getCurrentUpdatePriority, runWithPriority};
export {findHostInstance};
@@ -18,7 +18,7 @@ import type {
} from './ReactFiberHostConfig';
import type {RendererInspectionConfig} from './ReactFiberHostConfig';
import type {ReactNodeList} from 'shared/ReactTypes';
import type {Lane, LanePriority} from './ReactFiberLane.old';
import type {Lane} from './ReactFiberLane.old';
import type {SuspenseState} from './ReactFiberSuspenseComponent.old';
import {
@@ -82,9 +82,11 @@ import {
NoTimestamp,
getHighestPriorityPendingLanes,
higherPriorityLane,
getCurrentUpdateLanePriority,
setCurrentUpdateLanePriority,
} from './ReactFiberLane.old';
import {
getCurrentUpdatePriority,
runWithPriority,
} from './ReactEventPriorities.old';
import {
scheduleRefresh,
scheduleRoot,
@@ -442,17 +444,7 @@ export function attemptHydrationAtCurrentPriority(fiber: Fiber): void {
markRetryLaneIfNotHydrated(fiber, lane);
}
export function runWithPriority<T>(priority: LanePriority, fn: () => T) {
const previousPriority = getCurrentUpdateLanePriority();
try {
setCurrentUpdateLanePriority(priority);
return fn();
} finally {
setCurrentUpdateLanePriority(previousPriority);
}
}
export {getCurrentUpdateLanePriority};
export {getCurrentUpdatePriority, runWithPriority};
export {findHostInstance};
@@ -9,7 +9,7 @@
import type {Thenable, Wakeable} from 'shared/ReactTypes';
import type {Fiber, FiberRoot} from './ReactInternalTypes';
import type {Lanes, Lane, LanePriority} from './ReactFiberLane.new';
import type {Lanes, Lane} from './ReactFiberLane.new';
import type {Interaction} from 'scheduler/src/Tracing';
import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
import type {StackCursor} from './ReactFiberStack.new';
@@ -132,12 +132,10 @@ import {
import {
NoLanePriority,
SyncLanePriority,
DefaultLanePriority,
NoLanes,
NoLane,
SyncLane,
NoTimestamp,
findUpdateLane,
claimNextTransitionLane,
claimNextRetryLane,
includesSomeLane,
@@ -150,8 +148,6 @@ import {
includesOnlyTransitions,
getNextLanes,
returnNextLanesPriority,
setCurrentUpdateLanePriority,
getCurrentUpdateLanePriority,
markStarvedLanesAsExpired,
getLanesToRetrySynchronouslyOnError,
getMostRecentEventTime,
@@ -162,6 +158,14 @@ import {
markRootFinished,
lanePriorityToSchedulerPriority,
} from './ReactFiberLane.new';
import {
DiscreteEventPriority,
DefaultEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
higherEventPriority,
lanesToEventPriority,
} from './ReactEventPriorities.new';
import {requestCurrentTransition, NoTransition} from './ReactFiberTransition';
import {beginWork as originalBeginWork} from './ReactFiberBeginWork.new';
import {completeWork} from './ReactFiberCompleteWork.new';
@@ -320,7 +324,6 @@ let rootCommittingMutationOrLayoutEffects: FiberRoot | null = null;
let rootDoesHavePassiveEffects: boolean = false;
let rootWithPendingPassiveEffects: FiberRoot | null = null;
let pendingPassiveEffectsRenderPriority: LanePriority = NoLanePriority;
let pendingPassiveEffectsLanes: Lanes = NoLanes;
let pendingPassiveProfilerEffects: Array<Fiber> = [];
@@ -423,9 +426,13 @@ export function requestUpdateLane(fiber: Fiber): Lane {
// Updates originating inside certain React methods, like flushSync, have
// their priority set by tracking it with a context variable.
const updateLanePriority = getCurrentUpdateLanePriority();
if (updateLanePriority !== NoLanePriority) {
return findUpdateLane(updateLanePriority);
//
// The opaque type returned by the host config is internally a lane, so we can
// use that directly.
// TODO: Move this type conversion to the event priority module.
const updateLane: Lane = (getCurrentUpdatePriority(): any);
if (updateLane !== NoLane) {
return updateLane;
}
// This update originated outside React. Ask the host environement for an
@@ -433,7 +440,8 @@ export function requestUpdateLane(fiber: Fiber): Lane {
//
// The opaque type returned by the host config is internally a lane, so we can
// use that directly.
const eventLane = getCurrentEventPriority();
// TODO: Move this type conversion to the event priority module.
const eventLane: Lane = (getCurrentEventPriority(): any);
return eventLane;
}
@@ -1056,12 +1064,12 @@ export function flushDiscreteUpdates() {
}
export function deferredUpdates<A>(fn: () => A): A {
const previousLanePriority = getCurrentUpdateLanePriority();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(DefaultLanePriority);
setCurrentUpdatePriority(DefaultEventPriority);
return fn();
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
}
}
@@ -1102,12 +1110,12 @@ export function discreteUpdates<A, B, C, D, R>(
c: C,
d: D,
): R {
const previousLanePriority = getCurrentUpdateLanePriority();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(SyncLanePriority);
setCurrentUpdatePriority(DiscreteEventPriority);
return fn(a, b, c, d);
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
if (executionContext === NoContext) {
// Flush the immediate callbacks that were scheduled during this batch
resetRenderTimer();
@@ -1146,16 +1154,16 @@ export function flushSync<A, R>(fn: A => R, a: A): R {
}
executionContext |= BatchedContext;
const previousLanePriority = getCurrentUpdateLanePriority();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(SyncLanePriority);
setCurrentUpdatePriority(DiscreteEventPriority);
if (fn) {
return fn(a);
} else {
return (undefined: $FlowFixMe);
}
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
executionContext = prevExecutionContext;
// Flush the immediate callbacks that were scheduled during this batch.
// Note that this will happen even if batchedUpdates is higher up
@@ -1167,12 +1175,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();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(SyncLanePriority);
setCurrentUpdatePriority(DiscreteEventPriority);
fn();
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
executionContext = prevExecutionContext;
if (executionContext === NoContext) {
@@ -1663,12 +1671,14 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
}
function commitRoot(root) {
const previousUpdateLanePriority = getCurrentUpdateLanePriority();
// TODO: This no longer makes any sense. We already wrap the mutation and
// layout phases. Should be able to remove.
const previousUpdateLanePriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(SyncLanePriority);
setCurrentUpdatePriority(DiscreteEventPriority);
commitRootImpl(root, previousUpdateLanePriority);
} finally {
setCurrentUpdateLanePriority(previousUpdateLanePriority);
setCurrentUpdatePriority(previousUpdateLanePriority);
}
return null;
@@ -1780,8 +1790,8 @@ function commitRootImpl(root, renderPriorityLevel) {
NoFlags;
if (subtreeHasEffects || rootHasEffect) {
const previousLanePriority = getCurrentUpdateLanePriority();
setCurrentUpdateLanePriority(SyncLanePriority);
const previousPriority = getCurrentUpdatePriority();
setCurrentUpdatePriority(DiscreteEventPriority);
const prevExecutionContext = executionContext;
executionContext |= CommitContext;
@@ -1815,7 +1825,7 @@ function commitRootImpl(root, renderPriorityLevel) {
}
// The next phase is the mutation phase, where we mutate the host tree.
commitMutationEffects(root, renderPriorityLevel, finishedWork);
commitMutationEffects(root, finishedWork);
if (shouldFireAfterActiveInstanceBlur) {
afterActiveInstanceBlur();
@@ -1863,10 +1873,8 @@ function commitRootImpl(root, renderPriorityLevel) {
}
executionContext = prevExecutionContext;
if (previousLanePriority != null) {
// Reset the priority to the previous non-sync value.
setCurrentUpdateLanePriority(previousLanePriority);
}
// Reset the priority to the previous non-sync value.
setCurrentUpdatePriority(previousPriority);
} else {
// No effects.
root.current = finishedWork;
@@ -1886,10 +1894,6 @@ function commitRootImpl(root, renderPriorityLevel) {
rootDoesHavePassiveEffects = false;
rootWithPendingPassiveEffects = root;
pendingPassiveEffectsLanes = lanes;
pendingPassiveEffectsRenderPriority =
renderPriorityLevel === NoLanePriority
? DefaultLanePriority
: renderPriorityLevel;
}
// Read this again, since an effect might have updated it
@@ -2003,18 +2007,17 @@ function commitRootImpl(root, renderPriorityLevel) {
export function flushPassiveEffects(): boolean {
// Returns whether passive effects were flushed.
if (pendingPassiveEffectsRenderPriority !== NoLanePriority) {
const priorityLevel =
pendingPassiveEffectsRenderPriority > DefaultLanePriority
? DefaultLanePriority
: pendingPassiveEffectsRenderPriority;
pendingPassiveEffectsRenderPriority = NoLanePriority;
const previousLanePriority = getCurrentUpdateLanePriority();
if (pendingPassiveEffectsLanes !== NoLanes) {
const priority = higherEventPriority(
DefaultEventPriority,
lanesToEventPriority(pendingPassiveEffectsLanes),
);
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(priorityLevel);
setCurrentUpdatePriority(priority);
return flushPassiveEffectsImpl();
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
}
}
return false;
@@ -9,7 +9,7 @@
import type {Thenable, Wakeable} from 'shared/ReactTypes';
import type {Fiber, FiberRoot} from './ReactInternalTypes';
import type {Lanes, Lane, LanePriority} from './ReactFiberLane.old';
import type {Lanes, Lane} from './ReactFiberLane.old';
import type {Interaction} from 'scheduler/src/Tracing';
import type {SuspenseState} from './ReactFiberSuspenseComponent.old';
import type {StackCursor} from './ReactFiberStack.old';
@@ -132,12 +132,10 @@ import {
import {
NoLanePriority,
SyncLanePriority,
DefaultLanePriority,
NoLanes,
NoLane,
SyncLane,
NoTimestamp,
findUpdateLane,
claimNextTransitionLane,
claimNextRetryLane,
includesSomeLane,
@@ -150,8 +148,6 @@ import {
includesOnlyTransitions,
getNextLanes,
returnNextLanesPriority,
setCurrentUpdateLanePriority,
getCurrentUpdateLanePriority,
markStarvedLanesAsExpired,
getLanesToRetrySynchronouslyOnError,
getMostRecentEventTime,
@@ -162,6 +158,14 @@ import {
markRootFinished,
lanePriorityToSchedulerPriority,
} from './ReactFiberLane.old';
import {
DiscreteEventPriority,
DefaultEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
higherEventPriority,
lanesToEventPriority,
} from './ReactEventPriorities.old';
import {requestCurrentTransition, NoTransition} from './ReactFiberTransition';
import {beginWork as originalBeginWork} from './ReactFiberBeginWork.old';
import {completeWork} from './ReactFiberCompleteWork.old';
@@ -320,7 +324,6 @@ let rootCommittingMutationOrLayoutEffects: FiberRoot | null = null;
let rootDoesHavePassiveEffects: boolean = false;
let rootWithPendingPassiveEffects: FiberRoot | null = null;
let pendingPassiveEffectsRenderPriority: LanePriority = NoLanePriority;
let pendingPassiveEffectsLanes: Lanes = NoLanes;
let pendingPassiveProfilerEffects: Array<Fiber> = [];
@@ -423,9 +426,13 @@ export function requestUpdateLane(fiber: Fiber): Lane {
// Updates originating inside certain React methods, like flushSync, have
// their priority set by tracking it with a context variable.
const updateLanePriority = getCurrentUpdateLanePriority();
if (updateLanePriority !== NoLanePriority) {
return findUpdateLane(updateLanePriority);
//
// The opaque type returned by the host config is internally a lane, so we can
// use that directly.
// TODO: Move this type conversion to the event priority module.
const updateLane: Lane = (getCurrentUpdatePriority(): any);
if (updateLane !== NoLane) {
return updateLane;
}
// This update originated outside React. Ask the host environement for an
@@ -433,7 +440,8 @@ export function requestUpdateLane(fiber: Fiber): Lane {
//
// The opaque type returned by the host config is internally a lane, so we can
// use that directly.
const eventLane = getCurrentEventPriority();
// TODO: Move this type conversion to the event priority module.
const eventLane: Lane = (getCurrentEventPriority(): any);
return eventLane;
}
@@ -1056,12 +1064,12 @@ export function flushDiscreteUpdates() {
}
export function deferredUpdates<A>(fn: () => A): A {
const previousLanePriority = getCurrentUpdateLanePriority();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(DefaultLanePriority);
setCurrentUpdatePriority(DefaultEventPriority);
return fn();
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
}
}
@@ -1102,12 +1110,12 @@ export function discreteUpdates<A, B, C, D, R>(
c: C,
d: D,
): R {
const previousLanePriority = getCurrentUpdateLanePriority();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(SyncLanePriority);
setCurrentUpdatePriority(DiscreteEventPriority);
return fn(a, b, c, d);
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
if (executionContext === NoContext) {
// Flush the immediate callbacks that were scheduled during this batch
resetRenderTimer();
@@ -1146,16 +1154,16 @@ export function flushSync<A, R>(fn: A => R, a: A): R {
}
executionContext |= BatchedContext;
const previousLanePriority = getCurrentUpdateLanePriority();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(SyncLanePriority);
setCurrentUpdatePriority(DiscreteEventPriority);
if (fn) {
return fn(a);
} else {
return (undefined: $FlowFixMe);
}
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
executionContext = prevExecutionContext;
// Flush the immediate callbacks that were scheduled during this batch.
// Note that this will happen even if batchedUpdates is higher up
@@ -1167,12 +1175,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();
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(SyncLanePriority);
setCurrentUpdatePriority(DiscreteEventPriority);
fn();
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
executionContext = prevExecutionContext;
if (executionContext === NoContext) {
@@ -1663,12 +1671,14 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
}
function commitRoot(root) {
const previousUpdateLanePriority = getCurrentUpdateLanePriority();
// TODO: This no longer makes any sense. We already wrap the mutation and
// layout phases. Should be able to remove.
const previousUpdateLanePriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(SyncLanePriority);
setCurrentUpdatePriority(DiscreteEventPriority);
commitRootImpl(root, previousUpdateLanePriority);
} finally {
setCurrentUpdateLanePriority(previousUpdateLanePriority);
setCurrentUpdatePriority(previousUpdateLanePriority);
}
return null;
@@ -1780,8 +1790,8 @@ function commitRootImpl(root, renderPriorityLevel) {
NoFlags;
if (subtreeHasEffects || rootHasEffect) {
const previousLanePriority = getCurrentUpdateLanePriority();
setCurrentUpdateLanePriority(SyncLanePriority);
const previousPriority = getCurrentUpdatePriority();
setCurrentUpdatePriority(DiscreteEventPriority);
const prevExecutionContext = executionContext;
executionContext |= CommitContext;
@@ -1815,7 +1825,7 @@ function commitRootImpl(root, renderPriorityLevel) {
}
// The next phase is the mutation phase, where we mutate the host tree.
commitMutationEffects(root, renderPriorityLevel, finishedWork);
commitMutationEffects(root, finishedWork);
if (shouldFireAfterActiveInstanceBlur) {
afterActiveInstanceBlur();
@@ -1863,10 +1873,8 @@ function commitRootImpl(root, renderPriorityLevel) {
}
executionContext = prevExecutionContext;
if (previousLanePriority != null) {
// Reset the priority to the previous non-sync value.
setCurrentUpdateLanePriority(previousLanePriority);
}
// Reset the priority to the previous non-sync value.
setCurrentUpdatePriority(previousPriority);
} else {
// No effects.
root.current = finishedWork;
@@ -1886,10 +1894,6 @@ function commitRootImpl(root, renderPriorityLevel) {
rootDoesHavePassiveEffects = false;
rootWithPendingPassiveEffects = root;
pendingPassiveEffectsLanes = lanes;
pendingPassiveEffectsRenderPriority =
renderPriorityLevel === NoLanePriority
? DefaultLanePriority
: renderPriorityLevel;
}
// Read this again, since an effect might have updated it
@@ -2003,18 +2007,17 @@ function commitRootImpl(root, renderPriorityLevel) {
export function flushPassiveEffects(): boolean {
// Returns whether passive effects were flushed.
if (pendingPassiveEffectsRenderPriority !== NoLanePriority) {
const priorityLevel =
pendingPassiveEffectsRenderPriority > DefaultLanePriority
? DefaultLanePriority
: pendingPassiveEffectsRenderPriority;
pendingPassiveEffectsRenderPriority = NoLanePriority;
const previousLanePriority = getCurrentUpdateLanePriority();
if (pendingPassiveEffectsLanes !== NoLanes) {
const priority = higherEventPriority(
DefaultEventPriority,
lanesToEventPriority(pendingPassiveEffectsLanes),
);
const previousPriority = getCurrentUpdatePriority();
try {
setCurrentUpdateLanePriority(priorityLevel);
setCurrentUpdatePriority(priority);
return flushPassiveEffectsImpl();
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousPriority);
}
}
return false;
@@ -16,10 +16,10 @@ import {__interactionsRef} from 'scheduler/tracing';
import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
import invariant from 'shared/invariant';
import {
SyncLanePriority,
getCurrentUpdateLanePriority,
setCurrentUpdateLanePriority,
} from './ReactFiberLane.new';
DiscreteEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
} from './ReactEventPriorities.new';
const {
unstable_scheduleCallback: Scheduler_scheduleCallback,
@@ -147,11 +147,13 @@ export function flushSyncCallbackQueue() {
// Prevent re-entrancy.
isFlushingSyncQueue = true;
let i = 0;
const previousLanePriority = getCurrentUpdateLanePriority();
const previousUpdatePriority = getCurrentUpdatePriority();
try {
const isSync = true;
const queue = syncQueue;
setCurrentUpdateLanePriority(SyncLanePriority);
// TODO: Is this necessary anymore? The only user code that runs in this
// queue is in the render or commit phases.
setCurrentUpdatePriority(DiscreteEventPriority);
for (; i < queue.length; i++) {
let callback = queue[i];
do {
@@ -171,7 +173,7 @@ export function flushSyncCallbackQueue() {
);
throw error;
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousUpdatePriority);
isFlushingSyncQueue = false;
}
}
@@ -16,10 +16,10 @@ import {__interactionsRef} from 'scheduler/tracing';
import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
import invariant from 'shared/invariant';
import {
SyncLanePriority,
getCurrentUpdateLanePriority,
setCurrentUpdateLanePriority,
} from './ReactFiberLane.old';
DiscreteEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
} from './ReactEventPriorities.old';
const {
unstable_scheduleCallback: Scheduler_scheduleCallback,
@@ -147,11 +147,13 @@ export function flushSyncCallbackQueue() {
// Prevent re-entrancy.
isFlushingSyncQueue = true;
let i = 0;
const previousLanePriority = getCurrentUpdateLanePriority();
const previousUpdatePriority = getCurrentUpdatePriority();
try {
const isSync = true;
const queue = syncQueue;
setCurrentUpdateLanePriority(SyncLanePriority);
// TODO: Is this necessary anymore? The only user code that runs in this
// queue is in the render or commit phases.
setCurrentUpdatePriority(DiscreteEventPriority);
for (; i < queue.length; i++) {
let callback = queue[i];
do {
@@ -171,7 +173,7 @@ export function flushSyncCallbackQueue() {
);
throw error;
} finally {
setCurrentUpdateLanePriority(previousLanePriority);
setCurrentUpdatePriority(previousUpdatePriority);
isFlushingSyncQueue = false;
}
}
@@ -13,11 +13,7 @@
let React;
let ReactNoop;
let Scheduler;
// Copied from ReactFiberLanes. Don't do this!
// This is hard coded directly to avoid needing to import, and
// we'll remove this as we replace runWithPriority with React APIs.
const InputContinuousLanePriority = 10;
let ContinuousEventPriority;
describe('ReactIncrementalUpdates', () => {
beforeEach(() => {
@@ -26,6 +22,8 @@ describe('ReactIncrementalUpdates', () => {
React = require('react');
ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler');
ContinuousEventPriority = require('react-reconciler/constants')
.ContinuousEventPriority;
});
function span(prop) {
@@ -544,7 +542,7 @@ describe('ReactIncrementalUpdates', () => {
Scheduler.unstable_yieldValue('Committed: ' + log);
if (log === 'B') {
// Right after B commits, schedule additional updates.
ReactNoop.unstable_runWithPriority(InputContinuousLanePriority, () =>
ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () =>
pushToLog('C'),
);
setLog(prevLog => prevLog + 'D');
@@ -564,7 +562,7 @@ describe('ReactIncrementalUpdates', () => {
await ReactNoop.act(async () => {
pushToLog('A');
ReactNoop.unstable_runWithPriority(InputContinuousLanePriority, () =>
ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () =>
pushToLog('B'),
);
});
@@ -597,7 +595,7 @@ describe('ReactIncrementalUpdates', () => {
Scheduler.unstable_yieldValue('Committed: ' + this.state.log);
if (this.state.log === 'B') {
// Right after B commits, schedule additional updates.
ReactNoop.unstable_runWithPriority(InputContinuousLanePriority, () =>
ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () =>
this.pushToLog('C'),
);
this.pushToLog('D');
@@ -618,7 +616,7 @@ describe('ReactIncrementalUpdates', () => {
await ReactNoop.act(async () => {
pushToLog('A');
ReactNoop.unstable_runWithPriority(InputContinuousLanePriority, () =>
ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () =>
pushToLog('B'),
);
});
@@ -23,12 +23,8 @@ let onWorkCanceled;
let onWorkScheduled;
let onWorkStarted;
let onWorkStopped;
// Copied from ReactFiberLanes. Don't do this!
// This is hard coded directly to avoid needing to import, and
// we'll remove this as we replace runWithPriority with React APIs.
const IdleLanePriority = 2;
const InputContinuousPriority = 10;
let IdleEventPriority;
let ContinuousEventPriority;
function loadModules() {
ReactFeatureFlags = require('shared/ReactFeatureFlags');
@@ -44,6 +40,10 @@ function loadModules() {
SchedulerTracing = require('scheduler/tracing');
TestUtils = require('react-dom/test-utils');
IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;
ContinuousEventPriority = require('react-reconciler/constants')
.ContinuousEventPriority;
act = TestUtils.unstable_concurrentAct;
onInteractionScheduledWorkCompleted = jest.fn();
@@ -246,7 +246,7 @@ describe('ReactDOMTracing', () => {
Scheduler.unstable_yieldValue('Child:update');
} else {
Scheduler.unstable_yieldValue('Child:mount');
ReactDOM.unstable_runWithPriority(IdleLanePriority, () =>
ReactDOM.unstable_runWithPriority(IdleEventPriority, () =>
setDidMount(true),
);
}
@@ -499,7 +499,7 @@ describe('ReactDOMTracing', () => {
let interaction = null;
SchedulerTracing.unstable_trace('update', 0, () => {
interaction = Array.from(SchedulerTracing.unstable_getCurrent())[0];
ReactDOM.unstable_runWithPriority(InputContinuousPriority, () =>
ReactDOM.unstable_runWithPriority(ContinuousEventPriority, () =>
scheduleUpdateWithHidden(),
);
});
@@ -606,7 +606,7 @@ describe('ReactDOMTracing', () => {
// Schedule an unrelated low priority update that shouldn't be included
// in the previous interaction. This is meant to ensure that we don't
// rely on the whole tree completing to cover up bugs.
ReactDOM.unstable_runWithPriority(IdleLanePriority, () => {
ReactDOM.unstable_runWithPriority(IdleEventPriority, () => {
root.render(<App />);
});