@@ -398,33 +398,10 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
398
398
// no longer blocked, return the time at which it completed so that we
399
399
// can commit it.
400
400
if ( isRootBlocked ( root , completedAt ) ) {
401
- // Process pending completion callbacks so that they are called at
402
- // the end of the current batch.
403
- const completionCallbacks = root . completionCallbacks ;
404
- if ( completionCallbacks !== null ) {
405
- processUpdateQueue (
406
- completionCallbacks ,
407
- null ,
408
- null ,
409
- null ,
410
- completedAt ,
411
- ) ;
412
- const callbackList = completionCallbacks . callbackList ;
413
- if ( callbackList !== null ) {
414
- // Add new callbacks to list of completion callbacks
415
- if ( rootCompletionCallbackList === null ) {
416
- rootCompletionCallbackList = callbackList ;
417
- } else {
418
- for ( let i = 0 ; i < callbackList . length ; i ++ ) {
419
- rootCompletionCallbackList . push ( callbackList [ i ] ) ;
420
- }
421
- }
422
- completionCallbacks . callbackList = null ;
423
- if ( completionCallbacks . first === null ) {
424
- root . completionCallbacks = null ;
425
- }
426
- }
427
- }
401
+ // We usually process completion callbacks right after a root is
402
+ // completed. But this root already completed, and it's possible that
403
+ // we received new completion callbacks since then.
404
+ processCompletionCallbacks ( root , completedAt ) ;
428
405
return Done ;
429
406
}
430
407
@@ -434,6 +411,33 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
434
411
return expirationTime ;
435
412
}
436
413
414
+ function processCompletionCallbacks (
415
+ root : FiberRoot ,
416
+ completedAt : ExpirationTime ,
417
+ ) {
418
+ // Process pending completion callbacks so that they are called at
419
+ // the end of the current batch.
420
+ const completionCallbacks = root . completionCallbacks ;
421
+ if ( completionCallbacks !== null ) {
422
+ processUpdateQueue ( completionCallbacks , null , null , null , completedAt ) ;
423
+ const callbackList = completionCallbacks . callbackList ;
424
+ if ( callbackList !== null ) {
425
+ // Add new callbacks to list of completion callbacks
426
+ if ( rootCompletionCallbackList === null ) {
427
+ rootCompletionCallbackList = callbackList ;
428
+ } else {
429
+ for ( let i = 0 ; i < callbackList . length ; i ++ ) {
430
+ rootCompletionCallbackList . push ( callbackList [ i ] ) ;
431
+ }
432
+ }
433
+ completionCallbacks . callbackList = null ;
434
+ if ( completionCallbacks . first === null ) {
435
+ root . completionCallbacks = null ;
436
+ }
437
+ }
438
+ }
439
+ }
440
+
437
441
function commitAllHostEffects ( ) {
438
442
while ( nextEffect !== null ) {
439
443
if ( __DEV__ ) {
@@ -819,6 +823,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
819
823
// The root is not blocked, so we can commit it now.
820
824
pendingCommit = workInProgress ;
821
825
}
826
+ processCompletionCallbacks ( root , nextRenderExpirationTime ) ;
822
827
return null ;
823
828
}
824
829
}
@@ -1601,12 +1606,9 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
1601
1606
}
1602
1607
break ;
1603
1608
case TaskPriority :
1604
- invariant (
1605
- isBatchingUpdates ,
1606
- 'Task updates can only be scheduled as a nested update or ' +
1607
- 'inside batchedUpdates. This error is likely caused by a ' +
1608
- 'bug in React. Please file an issue.' ,
1609
- ) ;
1609
+ if ( ! isPerformingWork && ! isBatchingUpdates ) {
1610
+ performWork ( TaskPriority , null ) ;
1611
+ }
1610
1612
break ;
1611
1613
default :
1612
1614
// This update is async. Schedule a callback.
0 commit comments