@@ -14,6 +14,7 @@ import type {TimeoutHandle, NoTimeout} from './ReactFiberHostConfig';
1414import type { Thenable } from './ReactFiberWorkLoop' ;
1515import type { Interaction } from 'scheduler/src/Tracing' ;
1616import type { SuspenseHydrationCallbacks } from './ReactFiberSuspenseComponent' ;
17+ import type { ReactPriorityLevel } from './SchedulerWithReactIntegration' ;
1718
1819import { noTimeout } from './ReactFiberHostConfig' ;
1920import { createHostRootFiber } from './ReactFiber' ;
@@ -23,6 +24,7 @@ import {
2324 enableSuspenseCallback ,
2425} from 'shared/ReactFeatureFlags' ;
2526import { unstable_getThreadID } from 'scheduler/tracing' ;
27+ import { NoPriority } from './SchedulerWithReactIntegration' ;
2628
2729// TODO: This should be lifted into the renderer.
2830export type Batch = {
@@ -69,12 +71,20 @@ 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 ,
74- // The latest pending expiration time that exists in the tree
75- lastPendingTime : ExpirationTime ,
76- // The time at which a suspended component pinged the root to render again
77- pingTime : ExpirationTime ,
78+ // The earliest suspended expiration time that exists in the tree
79+ firstSuspendedTime : ExpirationTime ,
80+ // The latest suspended expiration time that exists in the tree
81+ lastSuspendedTime : ExpirationTime ,
82+ // The next known expiration time after the suspended range
83+ nextKnownPendingLevel : ExpirationTime ,
84+ // The latest time at which a suspended component pinged the root to
85+ // render again
86+ lastPingedTime : ExpirationTime ,
87+ lastExpiredTime : ExpirationTime ,
7888| } ;
7989
8090// The following attributes are only used by interaction tracing builds.
@@ -117,10 +127,13 @@ function FiberRootNode(containerInfo, tag, hydrate) {
117127 this . hydrate = hydrate ;
118128 this . firstBatch = null ;
119129 this . callbackNode = null ;
120- this . callbackExpirationTime = NoWork ;
130+ this . callbackPriority = NoPriority ;
121131 this . firstPendingTime = NoWork ;
122- this . lastPendingTime = NoWork ;
123- this . pingTime = NoWork ;
132+ this . firstSuspendedTime = NoWork ;
133+ this . lastSuspendedTime = NoWork ;
134+ this . nextKnownPendingLevel = NoWork ;
135+ this . lastPingedTime = NoWork ;
136+ this . lastExpiredTime = NoWork ;
124137
125138 if ( enableSchedulerTracing ) {
126139 this . interactionThreadID = unstable_getThreadID ( ) ;
@@ -151,3 +164,108 @@ export function createFiberRoot(
151164
152165 return root ;
153166}
167+
168+ export function isRootSuspendedAtTime (
169+ root : FiberRoot ,
170+ expirationTime : ExpirationTime ,
171+ ) : boolean {
172+ const firstSuspendedTime = root . firstSuspendedTime ;
173+ const lastSuspendedTime = root . lastSuspendedTime ;
174+ return (
175+ firstSuspendedTime !== NoWork &&
176+ ( firstSuspendedTime >= expirationTime &&
177+ lastSuspendedTime <= expirationTime )
178+ ) ;
179+ }
180+
181+ export function markRootSuspendedAtTime (
182+ root : FiberRoot ,
183+ expirationTime : ExpirationTime ,
184+ ) : void {
185+ const firstSuspendedTime = root . firstSuspendedTime ;
186+ const lastSuspendedTime = root . lastSuspendedTime ;
187+ if ( firstSuspendedTime < expirationTime ) {
188+ root . firstSuspendedTime = expirationTime ;
189+ }
190+ if ( lastSuspendedTime > expirationTime || firstSuspendedTime === NoWork ) {
191+ root . lastSuspendedTime = expirationTime ;
192+ }
193+
194+ if ( expirationTime <= root . lastPingedTime ) {
195+ root . lastPingedTime = NoWork ;
196+ }
197+
198+ if ( expirationTime <= root . lastExpiredTime ) {
199+ root . lastExpiredTime = NoWork ;
200+ }
201+ }
202+
203+ export function markRootUpdatedAtTime (
204+ root : FiberRoot ,
205+ expirationTime : ExpirationTime ,
206+ ) : void {
207+ // Update the range of pending times
208+ const firstPendingTime = root . firstPendingTime ;
209+ if ( expirationTime > firstPendingTime ) {
210+ root . firstPendingTime = expirationTime ;
211+ }
212+
213+ // Update the range of suspended times. Treat everything lower priority or
214+ // equal to this update as unsuspended.
215+ const firstSuspendedTime = root . firstSuspendedTime ;
216+ if ( firstSuspendedTime !== NoWork ) {
217+ if ( expirationTime >= firstSuspendedTime ) {
218+ // The entire suspended range is now unsuspended.
219+ root . firstSuspendedTime = root . lastSuspendedTime = root . nextKnownPendingLevel = NoWork ;
220+ } else if ( expirationTime >= root . lastSuspendedTime ) {
221+ root . lastSuspendedTime = expirationTime + 1 ;
222+ }
223+
224+ // This is a pending level. Check if it's higher priority than the next
225+ // known pending level.
226+ if ( expirationTime > root . nextKnownPendingLevel ) {
227+ root . nextKnownPendingLevel = expirationTime ;
228+ }
229+ }
230+ }
231+
232+ export function markRootFinishedAtTime (
233+ root : FiberRoot ,
234+ finishedExpirationTime : ExpirationTime ,
235+ remainingExpirationTime : ExpirationTime ,
236+ ) : void {
237+ // Update the range of pending times
238+ root. firstPendingTime = remainingExpirationTime ;
239+
240+ // Update the range of suspended times. Treat everything higher priority or
241+ // equal to this update as unsuspended.
242+ if ( finishedExpirationTime <= root . lastSuspendedTime ) {
243+ // The entire suspended range is now unsuspended.
244+ root . firstSuspendedTime = root . lastSuspendedTime = root . nextKnownPendingLevel = NoWork ;
245+ } else if ( finishedExpirationTime <= root . firstSuspendedTime ) {
246+ // Part of the suspended range is now unsuspended. Narrow the range to
247+ // include everything between the unsuspended time (non-inclusive) and the
248+ // last suspended time.
249+ root . firstSuspendedTime = finishedExpirationTime - 1 ;
250+ }
251+
252+ if ( finishedExpirationTime <= root . lastPingedTime ) {
253+ // Clear the pinged time
254+ root . lastPingedTime = NoWork ;
255+ }
256+
257+ if ( finishedExpirationTime <= root . lastExpiredTime ) {
258+ // Clear the expired time
259+ root . lastExpiredTime = NoWork ;
260+ }
261+ }
262+
263+ export function markRootExpiredAtTime (
264+ root : FiberRoot ,
265+ expirationTime : ExpirationTime ,
266+ ) : void {
267+ const lastExpiredTime = root . lastExpiredTime ;
268+ if ( lastExpiredTime === NoWork || lastExpiredTime > expirationTime ) {
269+ root . lastExpiredTime = expirationTime ;
270+ }
271+ }
0 commit comments