@@ -14,6 +14,7 @@ import type {TimeoutHandle, NoTimeout} from './ReactFiberHostConfig';
14
14
import type { Thenable } from './ReactFiberWorkLoop' ;
15
15
import type { Interaction } from 'scheduler/src/Tracing' ;
16
16
import type { SuspenseHydrationCallbacks } from './ReactFiberSuspenseComponent' ;
17
+ import type { ReactPriorityLevel } from './SchedulerWithReactIntegration' ;
17
18
18
19
import { noTimeout } from './ReactFiberHostConfig' ;
19
20
import { createHostRootFiber } from './ReactFiber' ;
@@ -23,6 +24,7 @@ import {
23
24
enableSuspenseCallback ,
24
25
} from 'shared/ReactFeatureFlags' ;
25
26
import { unstable_getThreadID } from 'scheduler/tracing' ;
27
+ import { NoPriority } from './SchedulerWithReactIntegration' ;
26
28
27
29
// TODO: This should be lifted into the renderer.
28
30
export type Batch = {
@@ -69,12 +71,20 @@ type BaseFiberRootProperties = {|
69
71
callbackNode : * ,
70
72
// Expiration of the callback associated with this root
71
73
callbackExpirationTime : ExpirationTime ,
74
+ // Priority of the callback associated with this root
75
+ callbackPriority : ReactPriorityLevel ,
72
76
// The earliest pending expiration time that exists in the tree
73
77
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 ,
78
88
| } ;
79
89
80
90
// The following attributes are only used by interaction tracing builds.
@@ -117,10 +127,13 @@ function FiberRootNode(containerInfo, tag, hydrate) {
117
127
this . hydrate = hydrate ;
118
128
this . firstBatch = null ;
119
129
this . callbackNode = null ;
120
- this . callbackExpirationTime = NoWork ;
130
+ this . callbackPriority = NoPriority ;
121
131
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 ;
124
137
125
138
if ( enableSchedulerTracing ) {
126
139
this . interactionThreadID = unstable_getThreadID ( ) ;
@@ -151,3 +164,108 @@ export function createFiberRoot(
151
164
152
165
return root ;
153
166
}
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