@@ -328,6 +328,21 @@ let globalMostRecentFallbackTime: number = 0;
328
328
const FALLBACK_THROTTLE_MS: number = 500;
329
329
const DEFAULT_TIMEOUT_MS: number = 5000;
330
330
331
+ // The absolute time for when we should start giving up on rendering
332
+ // more and prefer CPU suspense heuristics instead.
333
+ let workInProgressRootRenderTargetTime: number = Infinity;
334
+ // How long a render is supposed to take before we start following CPU
335
+ // suspense heuristics and opt out of rendering more content.
336
+ const RENDER_TIMEOUT_MS = 500;
337
+
338
+ function resetRenderTimer() {
339
+ workInProgressRootRenderTargetTime = now ( ) + RENDER_TIMEOUT_MS ;
340
+ }
341
+
342
+ export function getRenderTargetTime(): number {
343
+ return workInProgressRootRenderTargetTime ;
344
+ }
345
+
331
346
let hasUncaughtError = false;
332
347
let firstUncaughtError = null;
333
348
let legacyErrorBoundariesThatAlreadyFailed: Set< mixed > | null = null;
@@ -603,6 +618,7 @@ export function scheduleUpdateOnFiber(
603
618
// scheduleCallbackForFiber to preserve the ability to schedule a callback
604
619
// without immediately flushing it. We only do this for user-initiated
605
620
// updates, to preserve historical behavior of legacy mode.
621
+ resetRenderTimer ( ) ;
606
622
flushSyncCallbackQueue ( ) ;
607
623
}
608
624
}
@@ -1111,6 +1127,7 @@ export function flushRoot(root: FiberRoot, lanes: Lanes) {
1111
1127
markRootExpired ( root , lanes ) ;
1112
1128
ensureRootIsScheduled ( root , now ( ) ) ;
1113
1129
if ( ( executionContext & ( RenderContext | CommitContext ) ) === NoContext ) {
1130
+ resetRenderTimer ( ) ;
1114
1131
flushSyncCallbackQueue ( ) ;
1115
1132
}
1116
1133
}
@@ -1185,6 +1202,7 @@ export function batchedUpdates<A, R>(fn: A => R, a: A): R {
1185
1202
executionContext = prevExecutionContext ;
1186
1203
if ( executionContext === NoContext ) {
1187
1204
// Flush the immediate callbacks that were scheduled during this batch
1205
+ resetRenderTimer ( ) ;
1188
1206
flushSyncCallbackQueue ( ) ;
1189
1207
}
1190
1208
}
@@ -1199,6 +1217,7 @@ export function batchedEventUpdates<A, R>(fn: A => R, a: A): R {
1199
1217
executionContext = prevExecutionContext ;
1200
1218
if ( executionContext === NoContext ) {
1201
1219
// Flush the immediate callbacks that were scheduled during this batch
1220
+ resetRenderTimer ( ) ;
1202
1221
flushSyncCallbackQueue ( ) ;
1203
1222
}
1204
1223
}
@@ -1227,6 +1246,7 @@ export function discreteUpdates<A, B, C, D, R>(
1227
1246
executionContext = prevExecutionContext ;
1228
1247
if ( executionContext === NoContext ) {
1229
1248
// Flush the immediate callbacks that were scheduled during this batch
1249
+ resetRenderTimer ( ) ;
1230
1250
flushSyncCallbackQueue ( ) ;
1231
1251
}
1232
1252
}
@@ -1240,6 +1260,7 @@ export function discreteUpdates<A, B, C, D, R>(
1240
1260
executionContext = prevExecutionContext ;
1241
1261
if ( executionContext === NoContext ) {
1242
1262
// Flush the immediate callbacks that were scheduled during this batch
1263
+ resetRenderTimer ( ) ;
1243
1264
flushSyncCallbackQueue ( ) ;
1244
1265
}
1245
1266
}
@@ -1256,6 +1277,7 @@ export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
1256
1277
executionContext = prevExecutionContext ;
1257
1278
if ( executionContext === NoContext ) {
1258
1279
// Flush the immediate callbacks that were scheduled during this batch
1280
+ resetRenderTimer ( ) ;
1259
1281
flushSyncCallbackQueue ( ) ;
1260
1282
}
1261
1283
}
@@ -1323,6 +1345,7 @@ export function flushControlled(fn: () => mixed): void {
1323
1345
executionContext = prevExecutionContext ;
1324
1346
if ( executionContext === NoContext ) {
1325
1347
// Flush the immediate callbacks that were scheduled during this batch
1348
+ resetRenderTimer ( ) ;
1326
1349
flushSyncCallbackQueue ( ) ;
1327
1350
}
1328
1351
}
@@ -1333,6 +1356,7 @@ export function flushControlled(fn: () => mixed): void {
1333
1356
executionContext = prevExecutionContext ;
1334
1357
if ( executionContext === NoContext ) {
1335
1358
// Flush the immediate callbacks that were scheduled during this batch
1359
+ resetRenderTimer ( ) ;
1336
1360
flushSyncCallbackQueue ( ) ;
1337
1361
}
1338
1362
}
@@ -1651,6 +1675,7 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) {
1651
1675
// If the root or lanes have changed, throw out the existing stack
1652
1676
// and prepare a fresh one. Otherwise we'll continue where we left off.
1653
1677
if ( workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes ) {
1678
+ resetRenderTimer ( ) ;
1654
1679
prepareFreshStack ( root , lanes ) ;
1655
1680
startWorkOnPendingInteractions ( root , lanes ) ;
1656
1681
}
0 commit comments