Skip to content

Commit 8a471e1

Browse files
committed
Get next expiration time from FiberRoot
Given a FiberRoot, we should be able to determine the next expiration time that needs to be worked on, taking into account the levels that are pending, suspended, pinged, and so on. This removes the `expirationTime` argument from `scheduleCallbackForRoot`, and renames it to `ensureRootIsScheduled` to reflect the new signature. The expiration time is instead read from the root using a new function, `getNextExpirationTimeToWorkOn`. The next step will be to remove the `expirationTime` argument from `renderRoot`, too.
1 parent 100945b commit 8a471e1

File tree

2 files changed

+177
-87
lines changed

2 files changed

+177
-87
lines changed

packages/react-reconciler/src/ReactFiberRoot.js

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {TimeoutHandle, NoTimeout} from './ReactFiberHostConfig';
1414
import type {Thenable} from './ReactFiberWorkLoop';
1515
import type {Interaction} from 'scheduler/src/Tracing';
1616
import type {SuspenseHydrationCallbacks} from './ReactFiberSuspenseComponent';
17+
import type {ReactPriorityLevel} from './SchedulerWithReactIntegration';
1718

1819
import {noTimeout} from './ReactFiberHostConfig';
1920
import {createHostRootFiber} from './ReactFiber';
@@ -23,6 +24,7 @@ import {
2324
enableSuspenseCallback,
2425
} from 'shared/ReactFeatureFlags';
2526
import {unstable_getThreadID} from 'scheduler/tracing';
27+
import {NoPriority} from './SchedulerWithReactIntegration';
2628

2729
// TODO: This should be lifted into the renderer.
2830
export type Batch = {
@@ -69,6 +71,8 @@ type BaseFiberRootProperties = {|
6971
callbackNode: *,
7072
// Expiration of the callback associated with this root
7173
callbackExpirationTime: ExpirationTime,
74+
// Priority of the callback associated with this root
75+
callbackPriority: ReactPriorityLevel,
7276
// The earliest pending expiration time that exists in the tree
7377
firstPendingTime: ExpirationTime,
7478
// The latest pending expiration time that exists in the tree
@@ -78,7 +82,7 @@ type BaseFiberRootProperties = {|
7882
// The latest suspended expiration time that exists in the tree
7983
lastSuspendedTime: ExpirationTime,
8084
// The next known expiration time after the suspended range
81-
nextAfterSuspendedTime: ExpirationTime,
85+
nextKnownPendingLevel: ExpirationTime,
8286
// The latest time at which a suspended component pinged the root to
8387
// render again
8488
lastPingedTime: ExpirationTime,
@@ -124,12 +128,12 @@ function FiberRootNode(containerInfo, tag, hydrate) {
124128
this.hydrate = hydrate;
125129
this.firstBatch = null;
126130
this.callbackNode = null;
127-
this.callbackExpirationTime = NoWork;
131+
this.callbackPriority = NoPriority;
128132
this.firstPendingTime = NoWork;
129133
this.lastPendingTime = NoWork;
130134
this.firstSuspendedTime = NoWork;
131135
this.lastSuspendedTime = NoWork;
132-
this.nextAfterSuspendedTime = NoWork;
136+
this.nextKnownPendingLevel = NoWork;
133137
this.lastPingedTime = NoWork;
134138

135139
if (enableSchedulerTracing) {
@@ -193,21 +197,66 @@ export function markRootSuspendedAtTime(
193197
}
194198
}
195199

196-
export function markRootUnsuspendedAtTime(
200+
export function markRootUpdatedAtTime(
197201
root: FiberRoot,
198202
expirationTime: ExpirationTime,
199203
): void {
200-
if (expirationTime <= root.lastSuspendedTime) {
204+
// Update the range of pending times
205+
const firstPendingTime = root.firstPendingTime;
206+
if (expirationTime > firstPendingTime) {
207+
root.firstPendingTime = expirationTime;
208+
}
209+
const lastPendingTime = root.lastPendingTime;
210+
if (lastPendingTime === NoWork || expirationTime < lastPendingTime) {
211+
root.lastPendingTime = expirationTime;
212+
}
213+
214+
// Update the range of suspended times. Treat everything lower priority or
215+
// equal to this update as unsuspended.
216+
const firstSuspendedTime = root.firstSuspendedTime;
217+
if (firstSuspendedTime !== NoWork) {
218+
if (expirationTime >= firstSuspendedTime) {
219+
// The entire suspended range is now unsuspended.
220+
root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = NoWork;
221+
} else if (expirationTime >= root.lastSuspendedTime) {
222+
root.lastSuspendedTime = expirationTime + 1;
223+
}
224+
225+
// This is a pending level. Check if it's higher priority than the next
226+
// known pending level.
227+
if (expirationTime > root.nextKnownPendingLevel) {
228+
root.nextKnownPendingLevel = expirationTime;
229+
}
230+
}
231+
}
232+
233+
export function markRootFinishedAtTime(
234+
root: FiberRoot,
235+
finishedExpirationTime: ExpirationTime,
236+
remainingExpirationTime: ExpirationTime,
237+
): void {
238+
// Update the range of pending times
239+
root.firstPendingTime = remainingExpirationTime;
240+
if (remainingExpirationTime < root.lastPendingTime) {
241+
// This usually means we've finished all the work, but it can also happen
242+
// when something gets downprioritized during render, like a hidden tree.
243+
root.lastPendingTime = remainingExpirationTime;
244+
}
245+
246+
// Update the range of suspended times. Treat everything higher priority or
247+
// equal to this update as unsuspended.
248+
if (finishedExpirationTime <= root.lastSuspendedTime) {
201249
// The entire suspended range is now unsuspended.
202-
root.firstSuspendedTime = root.lastSuspendedTime = root.nextAfterSuspendedTime = NoWork;
203-
} else if (expirationTime <= root.firstSuspendedTime) {
250+
root.firstSuspendedTime = root.lastSuspendedTime = root.nextKnownPendingLevel = NoWork;
251+
} else if (finishedExpirationTime <= root.firstSuspendedTime) {
204252
// Part of the suspended range is now unsuspended. Narrow the range to
205253
// include everything between the unsuspended time (non-inclusive) and the
206254
// last suspended time.
207-
root.firstSuspendedTime = expirationTime - 1;
255+
root.firstSuspendedTime = finishedExpirationTime - 1;
208256
}
209257

210-
if (expirationTime <= root.lastPingedTime) {
258+
if (finishedExpirationTime <= root.lastPingedTime) {
259+
// Clear the pinged time
211260
root.lastPingedTime = NoWork;
212261
}
213262
}

0 commit comments

Comments
 (0)