Separate EventPriority from Lane

This commit is contained in:
Tianyu Yao
2022-10-10 17:25:42 -07:00
parent aa9988e5e6
commit cfed71511a
8 changed files with 98 additions and 43 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ import {
isHigherEventPriority as isHigherEventPriority_new,
} from './ReactEventPriorities.new';
export opaque type EventPriority = number;
export type EventPriority = number;
export const DiscreteEventPriority: EventPriority = enableNewReconciler
? (DiscreteEventPriority_new: any)
@@ -19,14 +19,17 @@ import {
includesNonIdleWork,
} from './ReactFiberLane.new';
export opaque type EventPriority = Lane;
// TODO: Ideally this would be opaque but that doesn't work well with
// our reconciler fork infra, since these leak into non-reconciler packages.
export type EventPriority = number;
export const NoEventPriority: EventPriority = NoLane;
export const DiscreteEventPriority: EventPriority = SyncLane;
export const ContinuousEventPriority: EventPriority = InputContinuousLane;
export const DefaultEventPriority: EventPriority = DefaultLane;
export const ContinuousEventPriority: EventPriority = SyncLane | (2 << 1);
export const DefaultEventPriority: EventPriority = SyncLane | (1 << 1);
export const IdleEventPriority: EventPriority = IdleLane;
let currentUpdatePriority: EventPriority = NoLane;
let currentUpdatePriority: EventPriority = NoEventPriority;
export function getCurrentUpdatePriority(): EventPriority {
return currentUpdatePriority;
@@ -80,3 +83,13 @@ export function lanesToEventPriority(lanes: Lanes): EventPriority {
}
return IdleEventPriority;
}
export function laneToEventPriority(lane: Lane): EventPriority {
if (lane === DefaultLane) {
return DefaultEventPriority;
}
if (lane === InputContinuousLane) {
return ContinuousEventPriority;
}
return (lane: any);
}
@@ -19,14 +19,17 @@ import {
includesNonIdleWork,
} from './ReactFiberLane.old';
export opaque type EventPriority = Lane;
// TODO: Ideally this would be opaque but that doesn't work well with
// our reconciler fork infra, since these leak into non-reconciler packages.
export type EventPriority = number;
export const NoEventPriority: EventPriority = NoLane;
export const DiscreteEventPriority: EventPriority = SyncLane;
export const ContinuousEventPriority: EventPriority = InputContinuousLane;
export const DefaultEventPriority: EventPriority = DefaultLane;
export const ContinuousEventPriority: EventPriority = SyncLane | (2 << 1);
export const DefaultEventPriority: EventPriority = SyncLane | (1 << 1);
export const IdleEventPriority: EventPriority = IdleLane;
let currentUpdatePriority: EventPriority = NoLane;
let currentUpdatePriority: EventPriority = NoEventPriority;
export function getCurrentUpdatePriority(): EventPriority {
return currentUpdatePriority;
@@ -80,3 +83,13 @@ export function lanesToEventPriority(lanes: Lanes): EventPriority {
}
return IdleEventPriority;
}
export function laneToEventPriority(lane: Lane): EventPriority {
if (lane === DefaultLane) {
return DefaultEventPriority;
}
if (lane === InputContinuousLane) {
return ContinuousEventPriority;
}
return (lane: any);
}
@@ -20,12 +20,12 @@ import type {Container} from './ReactFiberHostConfig';
import {noTimeout, supportsHydration} from './ReactFiberHostConfig';
import {createHostRootFiber} from './ReactFiber.new';
import {
NoLane,
NoLanes,
NoTimestamp,
TotalLanes,
createLaneMap,
} from './ReactFiberLane.new';
import {NoEventPriority} from './ReactEventPriorities.new';
import {
enableSuspenseCallback,
enableCache,
@@ -61,7 +61,7 @@ function FiberRootNode(
this.context = null;
this.pendingContext = null;
this.callbackNode = null;
this.callbackPriority = NoLane;
this.callbackPriority = NoEventPriority;
this.eventTimes = createLaneMap(NoLanes);
this.expirationTimes = createLaneMap(NoTimestamp);
@@ -20,12 +20,12 @@ import type {Container} from './ReactFiberHostConfig';
import {noTimeout, supportsHydration} from './ReactFiberHostConfig';
import {createHostRootFiber} from './ReactFiber.old';
import {
NoLane,
NoLanes,
NoTimestamp,
TotalLanes,
createLaneMap,
} from './ReactFiberLane.old';
import {NoEventPriority} from './ReactEventPriorities.old';
import {
enableSuspenseCallback,
enableCache,
@@ -61,7 +61,7 @@ function FiberRootNode(
this.context = null;
this.pendingContext = null;
this.callbackNode = null;
this.callbackPriority = NoLane;
this.callbackPriority = NoEventPriority;
this.eventTimes = createLaneMap(NoLanes);
this.expirationTimes = createLaneMap(NoTimestamp);
@@ -163,16 +163,20 @@ import {
movePendingFibersToMemoized,
addTransitionToLanesMap,
getTransitionsForLanes,
InputContinuousLane,
DefaultLane,
} from './ReactFiberLane.new';
import {
DiscreteEventPriority,
ContinuousEventPriority,
DefaultEventPriority,
NoEventPriority,
IdleEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
lowerEventPriority,
lanesToEventPriority,
laneToEventPriority,
} from './ReactEventPriorities.new';
import {requestCurrentTransition, NoTransition} from './ReactFiberTransition';
import {beginWork as originalBeginWork} from './ReactFiberBeginWork.new';
@@ -648,22 +652,30 @@ 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.
//
// 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;
const updatePriority = getCurrentUpdatePriority();
if (updatePriority !== NoEventPriority) {
if (updatePriority === DefaultEventPriority) {
return DefaultLane;
}
if (updatePriority === ContinuousEventPriority) {
return InputContinuousLane;
}
return (updatePriority: any);
}
// This update originated outside React. Ask the host environment for an
// appropriate priority, based on the type of event.
//
// 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 eventLane: Lane = (getCurrentEventPriority(): any);
return eventLane;
const eventPriority = getCurrentEventPriority();
if (eventPriority === DefaultEventPriority) {
return DefaultLane;
}
if (eventPriority === ContinuousEventPriority) {
return InputContinuousLane;
}
return (eventPriority: any);
}
function requestRetryLane(fiber: Fiber) {
@@ -860,12 +872,14 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
cancelCallback(existingCallbackNode);
}
root.callbackNode = null;
root.callbackPriority = NoLane;
root.callbackPriority = NoEventPriority;
return;
}
// We use the highest priority lane to represent the priority of the callback.
const newCallbackPriority = getHighestPriorityLane(nextLanes);
const newCallbackPriority = laneToEventPriority(
getHighestPriorityLane(nextLanes),
);
// Check if there's an existing task. We may be able to reuse it.
const existingCallbackPriority = root.callbackPriority;
@@ -886,7 +900,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
// TODO: Temporary until we confirm this warning is not fired.
if (
existingCallbackNode == null &&
existingCallbackPriority !== SyncLane
existingCallbackPriority !== DiscreteEventPriority
) {
console.error(
'Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.',
@@ -904,7 +918,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
// Schedule a new callback.
let newCallbackNode;
if (newCallbackPriority === SyncLane) {
if (newCallbackPriority === DiscreteEventPriority) {
// Special case: Sync React callbacks are scheduled on a special
// internal queue
if (root.tag === LegacyRoot) {
@@ -2382,7 +2396,7 @@ function commitRootImpl(
// commitRoot never returns a continuation; it always finishes synchronously.
// So we can clear these now to allow a new callback to be scheduled.
root.callbackNode = null;
root.callbackPriority = NoLane;
root.callbackPriority = NoEventPriority;
// Check which lanes no longer have any work scheduled on them, and mark
// those as finished.
@@ -163,16 +163,20 @@ import {
movePendingFibersToMemoized,
addTransitionToLanesMap,
getTransitionsForLanes,
InputContinuousLane,
DefaultLane,
} from './ReactFiberLane.old';
import {
DiscreteEventPriority,
ContinuousEventPriority,
DefaultEventPriority,
NoEventPriority,
IdleEventPriority,
getCurrentUpdatePriority,
setCurrentUpdatePriority,
lowerEventPriority,
lanesToEventPriority,
laneToEventPriority,
} from './ReactEventPriorities.old';
import {requestCurrentTransition, NoTransition} from './ReactFiberTransition';
import {beginWork as originalBeginWork} from './ReactFiberBeginWork.old';
@@ -648,22 +652,30 @@ 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.
//
// 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;
const updatePriority = getCurrentUpdatePriority();
if (updatePriority !== NoEventPriority) {
if (updatePriority === DefaultEventPriority) {
return DefaultLane;
}
if (updatePriority === ContinuousEventPriority) {
return InputContinuousLane;
}
return (updatePriority: any);
}
// This update originated outside React. Ask the host environment for an
// appropriate priority, based on the type of event.
//
// 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 eventLane: Lane = (getCurrentEventPriority(): any);
return eventLane;
const eventPriority = getCurrentEventPriority();
if (eventPriority === DefaultEventPriority) {
return DefaultLane;
}
if (eventPriority === ContinuousEventPriority) {
return InputContinuousLane;
}
return (eventPriority: any);
}
function requestRetryLane(fiber: Fiber) {
@@ -860,12 +872,14 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
cancelCallback(existingCallbackNode);
}
root.callbackNode = null;
root.callbackPriority = NoLane;
root.callbackPriority = NoEventPriority;
return;
}
// We use the highest priority lane to represent the priority of the callback.
const newCallbackPriority = getHighestPriorityLane(nextLanes);
const newCallbackPriority = laneToEventPriority(
getHighestPriorityLane(nextLanes),
);
// Check if there's an existing task. We may be able to reuse it.
const existingCallbackPriority = root.callbackPriority;
@@ -886,7 +900,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
// TODO: Temporary until we confirm this warning is not fired.
if (
existingCallbackNode == null &&
existingCallbackPriority !== SyncLane
existingCallbackPriority !== DiscreteEventPriority
) {
console.error(
'Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.',
@@ -904,7 +918,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
// Schedule a new callback.
let newCallbackNode;
if (newCallbackPriority === SyncLane) {
if (newCallbackPriority === DiscreteEventPriority) {
// Special case: Sync React callbacks are scheduled on a special
// internal queue
if (root.tag === LegacyRoot) {
@@ -2382,7 +2396,7 @@ function commitRootImpl(
// commitRoot never returns a continuation; it always finishes synchronously.
// So we can clear these now to allow a new callback to be scheduled.
root.callbackNode = null;
root.callbackPriority = NoLane;
root.callbackPriority = NoEventPriority;
// Check which lanes no longer have any work scheduled on them, and mark
// those as finished.
+3 -2
View File
@@ -22,7 +22,8 @@ import type {
import type {WorkTag} from './ReactWorkTags';
import type {TypeOfMode} from './ReactTypeOfMode';
import type {Flags} from './ReactFiberFlags';
import type {Lane, Lanes, LaneMap} from './ReactFiberLane.old';
import type {Lanes, LaneMap} from './ReactFiberLane.old';
import type {EventPriority} from './ReactEventPriorities';
import type {RootTag} from './ReactRootTags';
import type {
Container,
@@ -239,7 +240,7 @@ type BaseFiberRootProperties = {
// Node returned by Scheduler.scheduleCallback. Represents the next rendering
// task that the root will work on.
callbackNode: any,
callbackPriority: Lane,
callbackPriority: EventPriority,
eventTimes: LaneMap<number>,
expirationTimes: LaneMap<number>,
hiddenUpdates: LaneMap<Array<ConcurrentUpdate> | null>,