From 2a8211f3d1121ba989aedbf3bca182edc8aeec33 Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Thu, 25 Mar 2021 00:17:53 -0500 Subject: [PATCH] Use Lane to track root callback priority Instead of LanePriority. I'm removing all uses of LanePriority so I can delete it. --- .../src/ReactFiberLane.new.js | 42 +----------------- .../src/ReactFiberLane.old.js | 42 +----------------- .../src/ReactFiberRoot.new.js | 4 +- .../src/ReactFiberRoot.old.js | 4 +- .../src/ReactFiberWorkLoop.new.js | 43 +++++++++++++------ .../src/ReactFiberWorkLoop.old.js | 43 +++++++++++++------ .../src/ReactInternalTypes.js | 4 +- 7 files changed, 68 insertions(+), 114 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberLane.new.js b/packages/react-reconciler/src/ReactFiberLane.new.js index 227526858b22a..badfe48b0a2c7 100644 --- a/packages/react-reconciler/src/ReactFiberLane.new.js +++ b/packages/react-reconciler/src/ReactFiberLane.new.js @@ -7,7 +7,7 @@ * @flow */ -import type {FiberRoot, ReactPriorityLevel} from './ReactInternalTypes'; +import type {FiberRoot} from './ReactInternalTypes'; // TODO: Ideally these types would be opaque but that doesn't work well with // our reconciler fork infra, since these leak into non-reconciler packages. @@ -35,17 +35,8 @@ export type Lanes = number; export type Lane = number; export type LaneMap = Array; -import invariant from 'shared/invariant'; import {enableCache, enableSchedulingProfiler} from 'shared/ReactFeatureFlags'; -import { - ImmediatePriority as ImmediateSchedulerPriority, - UserBlockingPriority as UserBlockingSchedulerPriority, - NormalPriority as NormalSchedulerPriority, - IdlePriority as IdleSchedulerPriority, - NoPriority as NoSchedulerPriority, -} from './SchedulerWithReactIntegration.new'; - export const SyncLanePriority: LanePriority = 12; const InputContinuousHydrationLanePriority: LanePriority = 11; @@ -244,37 +235,6 @@ function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes { } } -export function lanePriorityToSchedulerPriority( - lanePriority: LanePriority, -): ReactPriorityLevel { - switch (lanePriority) { - case SyncLanePriority: - return ImmediateSchedulerPriority; - case InputContinuousHydrationLanePriority: - case InputContinuousLanePriority: - return UserBlockingSchedulerPriority; - case DefaultHydrationLanePriority: - case DefaultLanePriority: - case TransitionHydrationPriority: - case TransitionPriority: - case SelectiveHydrationLanePriority: - case RetryLanePriority: - return NormalSchedulerPriority; - case IdleHydrationLanePriority: - case IdleLanePriority: - case OffscreenLanePriority: - return IdleSchedulerPriority; - case NoLanePriority: - return NoSchedulerPriority; - default: - invariant( - false, - 'Invalid update priority: %s. This is a bug in React.', - lanePriority, - ); - } -} - export function getNextLanes(root: FiberRoot, wipLanes: Lanes): Lanes { // Early bailout if there's no pending work left. const pendingLanes = root.pendingLanes; diff --git a/packages/react-reconciler/src/ReactFiberLane.old.js b/packages/react-reconciler/src/ReactFiberLane.old.js index 2380acd634f15..badfe48b0a2c7 100644 --- a/packages/react-reconciler/src/ReactFiberLane.old.js +++ b/packages/react-reconciler/src/ReactFiberLane.old.js @@ -7,7 +7,7 @@ * @flow */ -import type {FiberRoot, ReactPriorityLevel} from './ReactInternalTypes'; +import type {FiberRoot} from './ReactInternalTypes'; // TODO: Ideally these types would be opaque but that doesn't work well with // our reconciler fork infra, since these leak into non-reconciler packages. @@ -35,17 +35,8 @@ export type Lanes = number; export type Lane = number; export type LaneMap = Array; -import invariant from 'shared/invariant'; import {enableCache, enableSchedulingProfiler} from 'shared/ReactFeatureFlags'; -import { - ImmediatePriority as ImmediateSchedulerPriority, - UserBlockingPriority as UserBlockingSchedulerPriority, - NormalPriority as NormalSchedulerPriority, - IdlePriority as IdleSchedulerPriority, - NoPriority as NoSchedulerPriority, -} from './SchedulerWithReactIntegration.old'; - export const SyncLanePriority: LanePriority = 12; const InputContinuousHydrationLanePriority: LanePriority = 11; @@ -244,37 +235,6 @@ function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes { } } -export function lanePriorityToSchedulerPriority( - lanePriority: LanePriority, -): ReactPriorityLevel { - switch (lanePriority) { - case SyncLanePriority: - return ImmediateSchedulerPriority; - case InputContinuousHydrationLanePriority: - case InputContinuousLanePriority: - return UserBlockingSchedulerPriority; - case DefaultHydrationLanePriority: - case DefaultLanePriority: - case TransitionHydrationPriority: - case TransitionPriority: - case SelectiveHydrationLanePriority: - case RetryLanePriority: - return NormalSchedulerPriority; - case IdleHydrationLanePriority: - case IdleLanePriority: - case OffscreenLanePriority: - return IdleSchedulerPriority; - case NoLanePriority: - return NoSchedulerPriority; - default: - invariant( - false, - 'Invalid update priority: %s. This is a bug in React.', - lanePriority, - ); - } -} - export function getNextLanes(root: FiberRoot, wipLanes: Lanes): Lanes { // Early bailout if there's no pending work left. const pendingLanes = root.pendingLanes; diff --git a/packages/react-reconciler/src/ReactFiberRoot.new.js b/packages/react-reconciler/src/ReactFiberRoot.new.js index dfc859a465218..1eb637891ebe6 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.new.js +++ b/packages/react-reconciler/src/ReactFiberRoot.new.js @@ -13,8 +13,8 @@ import type {RootTag} from './ReactRootTags'; import {noTimeout, supportsHydration} from './ReactFiberHostConfig'; import {createHostRootFiber} from './ReactFiber.new'; import { + NoLane, NoLanes, - NoLanePriority, NoTimestamp, createLaneMap, } from './ReactFiberLane.new'; @@ -41,7 +41,7 @@ function FiberRootNode(containerInfo, tag, hydrate) { this.pendingContext = null; this.hydrate = hydrate; this.callbackNode = null; - this.callbackPriority = NoLanePriority; + this.callbackPriority = NoLane; this.eventTimes = createLaneMap(NoLanes); this.expirationTimes = createLaneMap(NoTimestamp); diff --git a/packages/react-reconciler/src/ReactFiberRoot.old.js b/packages/react-reconciler/src/ReactFiberRoot.old.js index 138fb9c38a1a6..e44757248b427 100644 --- a/packages/react-reconciler/src/ReactFiberRoot.old.js +++ b/packages/react-reconciler/src/ReactFiberRoot.old.js @@ -13,8 +13,8 @@ import type {RootTag} from './ReactRootTags'; import {noTimeout, supportsHydration} from './ReactFiberHostConfig'; import {createHostRootFiber} from './ReactFiber.old'; import { + NoLane, NoLanes, - NoLanePriority, NoTimestamp, createLaneMap, } from './ReactFiberLane.old'; @@ -41,7 +41,7 @@ function FiberRootNode(containerInfo, tag, hydrate) { this.pendingContext = null; this.hydrate = hydrate; this.callbackNode = null; - this.callbackPriority = NoLanePriority; + this.callbackPriority = NoLane; this.eventTimes = createLaneMap(NoLanes); this.expirationTimes = createLaneMap(NoTimestamp); diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js index edfc46cece75a..b7ed519ea55dd 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js @@ -43,7 +43,9 @@ import { requestPaint, now, ImmediatePriority as ImmediateSchedulerPriority, + UserBlockingPriority as UserBlockingSchedulerPriority, NormalPriority as NormalSchedulerPriority, + IdlePriority as IdleSchedulerPriority, flushSyncCallbackQueue, scheduleSyncCallback, } from './SchedulerWithReactIntegration.new'; @@ -130,8 +132,6 @@ import { MountLayoutDev, } from './ReactFiberFlags'; import { - NoLanePriority, - SyncLanePriority, NoLanes, NoLane, SyncLane, @@ -147,7 +147,6 @@ import { includesOnlyRetries, includesOnlyTransitions, getNextLanes, - returnNextLanesPriority, markStarvedLanesAsExpired, getLanesToRetrySynchronouslyOnError, getMostRecentEventTime, @@ -156,12 +155,14 @@ import { markRootPinged, markRootExpired, markRootFinished, - lanePriorityToSchedulerPriority, areLanesExpired, + getHighestPriorityLane, } from './ReactFiberLane.new'; import { DiscreteEventPriority, + ContinuousEventPriority, DefaultEventPriority, + IdleEventPriority, getCurrentUpdatePriority, setCurrentUpdatePriority, higherEventPriority, @@ -653,8 +654,6 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes, ); - // This returns the priority level computed during the `getNextLanes` call. - const newCallbackPriority = returnNextLanesPriority(); if (nextLanes === NoLanes) { // Special case: There's nothing to work on. @@ -662,10 +661,13 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { cancelCallback(existingCallbackNode); } root.callbackNode = null; - root.callbackPriority = NoLanePriority; + root.callbackPriority = NoLane; return; } + // We use the highest priority lane to represent the priority of the callback. + const newCallbackPriority = getHighestPriorityLane(nextLanes); + // Check if there's an existing task. We may be able to reuse it. const existingCallbackPriority = root.callbackPriority; if (existingCallbackPriority === newCallbackPriority) { @@ -675,7 +677,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { // TODO: Temporary until we confirm this warning is not fired. if ( existingCallbackNode == null && - existingCallbackPriority !== SyncLanePriority + existingCallbackPriority !== SyncLane ) { console.error( 'Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.', @@ -693,7 +695,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { // Schedule a new callback. let newCallbackNode; - if (newCallbackPriority === SyncLanePriority) { + if (newCallbackPriority === SyncLane) { // Special case: Sync React callbacks are scheduled on a special // internal queue scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); @@ -706,9 +708,24 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { } newCallbackNode = null; } else { - const schedulerPriorityLevel = lanePriorityToSchedulerPriority( - newCallbackPriority, - ); + let schedulerPriorityLevel; + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediateSchedulerPriority; + break; + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingSchedulerPriority; + break; + case DefaultEventPriority: + schedulerPriorityLevel = NormalSchedulerPriority; + break; + case IdleEventPriority: + schedulerPriorityLevel = IdleSchedulerPriority; + break; + default: + schedulerPriorityLevel = NormalSchedulerPriority; + break; + } newCallbackNode = scheduleCallback( schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root), @@ -1744,7 +1761,7 @@ function commitRootImpl(root, renderPriorityLevel) { // 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 = NoLanePriority; + root.callbackPriority = NoLane; // Update the first and last pending times on this root. The new first // pending time is whatever is left on the root fiber. diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js index 542567182c4c9..d29bbdefba4cc 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js @@ -43,7 +43,9 @@ import { requestPaint, now, ImmediatePriority as ImmediateSchedulerPriority, + UserBlockingPriority as UserBlockingSchedulerPriority, NormalPriority as NormalSchedulerPriority, + IdlePriority as IdleSchedulerPriority, flushSyncCallbackQueue, scheduleSyncCallback, } from './SchedulerWithReactIntegration.old'; @@ -130,8 +132,6 @@ import { MountLayoutDev, } from './ReactFiberFlags'; import { - NoLanePriority, - SyncLanePriority, NoLanes, NoLane, SyncLane, @@ -147,7 +147,6 @@ import { includesOnlyRetries, includesOnlyTransitions, getNextLanes, - returnNextLanesPriority, markStarvedLanesAsExpired, getLanesToRetrySynchronouslyOnError, getMostRecentEventTime, @@ -156,12 +155,14 @@ import { markRootPinged, markRootExpired, markRootFinished, - lanePriorityToSchedulerPriority, areLanesExpired, + getHighestPriorityLane, } from './ReactFiberLane.old'; import { DiscreteEventPriority, + ContinuousEventPriority, DefaultEventPriority, + IdleEventPriority, getCurrentUpdatePriority, setCurrentUpdatePriority, higherEventPriority, @@ -653,8 +654,6 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes, ); - // This returns the priority level computed during the `getNextLanes` call. - const newCallbackPriority = returnNextLanesPriority(); if (nextLanes === NoLanes) { // Special case: There's nothing to work on. @@ -662,10 +661,13 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { cancelCallback(existingCallbackNode); } root.callbackNode = null; - root.callbackPriority = NoLanePriority; + root.callbackPriority = NoLane; return; } + // We use the highest priority lane to represent the priority of the callback. + const newCallbackPriority = getHighestPriorityLane(nextLanes); + // Check if there's an existing task. We may be able to reuse it. const existingCallbackPriority = root.callbackPriority; if (existingCallbackPriority === newCallbackPriority) { @@ -675,7 +677,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { // TODO: Temporary until we confirm this warning is not fired. if ( existingCallbackNode == null && - existingCallbackPriority !== SyncLanePriority + existingCallbackPriority !== SyncLane ) { console.error( 'Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.', @@ -693,7 +695,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { // Schedule a new callback. let newCallbackNode; - if (newCallbackPriority === SyncLanePriority) { + if (newCallbackPriority === SyncLane) { // Special case: Sync React callbacks are scheduled on a special // internal queue scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); @@ -706,9 +708,24 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { } newCallbackNode = null; } else { - const schedulerPriorityLevel = lanePriorityToSchedulerPriority( - newCallbackPriority, - ); + let schedulerPriorityLevel; + switch (lanesToEventPriority(nextLanes)) { + case DiscreteEventPriority: + schedulerPriorityLevel = ImmediateSchedulerPriority; + break; + case ContinuousEventPriority: + schedulerPriorityLevel = UserBlockingSchedulerPriority; + break; + case DefaultEventPriority: + schedulerPriorityLevel = NormalSchedulerPriority; + break; + case IdleEventPriority: + schedulerPriorityLevel = IdleSchedulerPriority; + break; + default: + schedulerPriorityLevel = NormalSchedulerPriority; + break; + } newCallbackNode = scheduleCallback( schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root), @@ -1744,7 +1761,7 @@ function commitRootImpl(root, renderPriorityLevel) { // 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 = NoLanePriority; + root.callbackPriority = NoLane; // Update the first and last pending times on this root. The new first // pending time is whatever is left on the root fiber. diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index 4e5a415f165f6..95aa2483eeec3 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -20,7 +20,7 @@ import type {SuspenseInstance} from './ReactFiberHostConfig'; import type {WorkTag} from './ReactWorkTags'; import type {TypeOfMode} from './ReactTypeOfMode'; import type {Flags} from './ReactFiberFlags'; -import type {Lane, LanePriority, Lanes, LaneMap} from './ReactFiberLane.old'; +import type {Lane, Lanes, LaneMap} from './ReactFiberLane.old'; import type {RootTag} from './ReactRootTags'; import type {TimeoutHandle, NoTimeout} from './ReactFiberHostConfig'; import type {Wakeable} from 'shared/ReactTypes'; @@ -223,7 +223,7 @@ type BaseFiberRootProperties = {| // Node returned by Scheduler.scheduleCallback. Represents the next rendering // task that the root will work on. callbackNode: *, - callbackPriority: LanePriority, + callbackPriority: Lane, eventTimes: LaneMap, expirationTimes: LaneMap,