@@ -52,7 +52,6 @@ var {ReactCurrentOwner} = require('ReactGlobalSharedState');
5252var getComponentName = require ( 'getComponentName' ) ;
5353
5454var { createWorkInProgress} = require ( 'ReactFiber' ) ;
55- var { isRootBlocked} = require ( 'ReactFiberRoot' ) ;
5655var { onCommitRoot} = require ( 'ReactFiberDevToolsHook' ) ;
5756
5857var {
@@ -335,12 +334,15 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
335334 'is likely caused by a bug in React. Please file an issue.' ,
336335 ) ;
337336 } else {
338- earliestExpirationRoot . completedAt = NoWork ;
339337 nextUnitOfWork = createWorkInProgress (
340338 earliestExpirationRoot . current ,
341339 earliestExpirationTime ,
342340 ) ;
343341 }
342+
343+ earliestExpirationRoot . completedAt = NoWork ;
344+ earliestExpirationRoot . isBlocked = false ;
345+
344346 if ( earliestExpirationRoot !== nextRenderedTree ) {
345347 // We've switched trees. Reset the nested update counter.
346348 nestedUpdateCount = 0 ;
@@ -360,53 +362,18 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
360362 // TODO: Find a better name for this function. It also schedules completion
361363 // callbacks, if a root is blocked.
362364 function shouldWorkOnRoot ( root : FiberRoot ) : ExpirationTime {
363- const completedAt = root . completedAt ;
364365 const expirationTime = root . current . expirationTime ;
365-
366366 if ( expirationTime === NoWork ) {
367367 // There's no work in this tree.
368368 return NoWork ;
369369 }
370-
371- if ( completedAt !== NoWork ) {
372- // The root completed but was blocked from committing.
373- if ( expirationTime < completedAt ) {
374- // We have work that expires earlier than the completed root.
375- return expirationTime ;
376- }
377-
378- // If the expiration time of the pending work is equal to the time at
379- // which we completed the work-in-progress, it's possible additional
380- // work was scheduled that happens to fall within the same expiration
381- // bucket. We need to check the work-in-progress fiber.
382- if ( expirationTime === completedAt ) {
383- const workInProgress = root . current . alternate ;
384- if (
385- workInProgress !== null &&
386- ( workInProgress . expirationTime !== NoWork &&
387- workInProgress . expirationTime <= expirationTime )
388- ) {
389- // We have more work. Restart the completed tree.
390- root . completedAt = NoWork ;
391- return expirationTime ;
392- }
393- }
394-
395- // There have been no higher priority updates since we completed the root.
396- // If it's still blocked, return NoWork, as if it has no more work. If it's
397- // no longer blocked, return the time at which it completed so that we
398- // can commit it.
399- if ( isRootBlocked ( root , completedAt ) ) {
400- // We usually process completion callbacks right after a root is
401- // completed. But this root already completed, and it's possible that
402- // we received new completion callbacks since then.
403- processCompletionCallbacks ( root , completedAt ) ;
404- return NoWork ;
405- }
406-
407- return completedAt ;
370+ if ( root . isBlocked ) {
371+ // We usually process completion callbacks right after a root is
372+ // completed. But this root already completed, and it's possible that
373+ // we received new completion callbacks since then.
374+ processCompletionCallbacks ( root , root . completedAt ) ;
375+ return NoWork ;
408376 }
409-
410377 return expirationTime ;
411378 }
412379
@@ -817,16 +784,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
817784 workInProgress = returnFiber ;
818785 continue ;
819786 } else {
787+ // We've reached the root. Mark it as complete.
820788 const root = workInProgress . stateNode ;
821- // We've reached the root. Mark the root as complete. Depending on how
822- // much time we have left, we'll either commit it now or in the
823- // next frame.
824- if ( isRootBlocked ( root , nextRenderExpirationTime ) ) {
825- // The root is blocked from committing. Mark it as complete so we
826- // know we can commit it later without starting new work.
827- root . completedAt = nextRenderExpirationTime ;
828- } else {
829- // The root is not blocked, so we can commit it now.
789+ root . completedAt = nextRenderExpirationTime ;
790+ // If the root isn't blocked, it's ready to commit. If it is blocked,
791+ // we'll come back to it later.
792+ if ( ! root . isBlocked ) {
830793 pendingCommit = workInProgress ;
831794 }
832795 processCompletionCallbacks ( root , nextRenderExpirationTime ) ;
@@ -1509,25 +1472,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15091472 }
15101473 }
15111474
1512- function scheduleRoot ( root : FiberRoot , expirationTime : ExpirationTime ) {
1513- if ( expirationTime === NoWork ) {
1514- return ;
1515- }
1516-
1517- if ( ! root . isScheduled ) {
1518- root . isScheduled = true ;
1519- if ( lastScheduledRoot ) {
1520- // Schedule ourselves to the end.
1521- lastScheduledRoot . nextScheduledRoot = root ;
1522- lastScheduledRoot = root ;
1523- } else {
1524- // We're the only work scheduled.
1525- nextScheduledRoot = root ;
1526- lastScheduledRoot = root ;
1527- }
1528- }
1529- }
1530-
15311475 function scheduleUpdate (
15321476 fiber : Fiber ,
15331477 partialState : mixed ,
@@ -1549,6 +1493,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15491493 isReplace,
15501494 isForced,
15511495 nextCallback : null ,
1496+ isTopLevelUnmount : false ,
15521497 next : null ,
15531498 } ;
15541499 insertUpdateIntoFiber ( fiber , update , currentTime ) ;
@@ -1594,35 +1539,45 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15941539 }
15951540
15961541 let node = fiber ;
1597- let shouldContinue = true ;
1598- while ( node !== null && shouldContinue ) {
1599- // Walk the parent path to the root and update each node's expiration
1600- // time. Once we reach a node whose expiration matches (and whose
1601- // alternate's expiration matches) we can exit safely knowing that the
1602- // rest of the path is correct.
1603- shouldContinue = false ;
1542+ while ( node !== null ) {
16041543 if (
16051544 node . expirationTime === NoWork ||
16061545 node . expirationTime > expirationTime
16071546 ) {
1608- // Expiration time did not match. Update and keep going.
1609- shouldContinue = true ;
16101547 node . expirationTime = expirationTime ;
16111548 }
16121549 if ( node . alternate !== null ) {
16131550 if (
16141551 node . alternate . expirationTime === NoWork ||
16151552 node . alternate . expirationTime > expirationTime
16161553 ) {
1617- // Expiration time did not match. Update and keep going.
1618- shouldContinue = true ;
16191554 node . alternate . expirationTime = expirationTime ;
16201555 }
16211556 }
16221557 if ( node . return === null ) {
16231558 if ( node . tag === HostRoot ) {
16241559 const root : FiberRoot = ( node . stateNode : any ) ;
1625- scheduleRoot ( root , expirationTime ) ;
1560+
1561+ // Add the root to the work schedule.
1562+ if ( expirationTime !== NoWork ) {
1563+ root . isBlocked = false ;
1564+ if ( ! root . isScheduled ) {
1565+ root . isScheduled = true ;
1566+ if ( lastScheduledRoot ) {
1567+ // Schedule ourselves to the end.
1568+ lastScheduledRoot . nextScheduledRoot = root ;
1569+ lastScheduledRoot = root ;
1570+ } else {
1571+ // We're the only work scheduled.
1572+ nextScheduledRoot = root ;
1573+ lastScheduledRoot = root ;
1574+ }
1575+ }
1576+ }
1577+
1578+ // If we're not current performing work, we need to either start
1579+ // working now (if the update is synchronous) or schedule a callback
1580+ // to perform work later.
16261581 if ( ! isPerformingWork ) {
16271582 const priorityLevel = expirationTimeToPriorityLevel (
16281583 mostRecentCurrentTime ,
@@ -1774,6 +1729,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
17741729 'Cannot commit while already performing work.' ,
17751730 ) ;
17761731 root . forceExpire = expirationTime ;
1732+ root . isBlocked = false ;
17771733 try {
17781734 performWork ( TaskPriority , null ) ;
17791735 } finally {
0 commit comments