@@ -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 {
@@ -336,12 +335,15 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
336335 'is likely caused by a bug in React. Please file an issue.' ,
337336 ) ;
338337 } else {
339- earliestExpirationRoot . completedAt = NoWork ;
340338 nextUnitOfWork = createWorkInProgress (
341339 earliestExpirationRoot . current ,
342340 earliestExpirationTime ,
343341 ) ;
344342 }
343+
344+ earliestExpirationRoot . completedAt = NoWork ;
345+ earliestExpirationRoot . isBlocked = false ;
346+
345347 if ( earliestExpirationRoot !== nextRenderedTree ) {
346348 // We've switched trees. Reset the nested update counter.
347349 nestedUpdateCount = 0 ;
@@ -361,53 +363,18 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
361363 // TODO: Find a better name for this function. It also schedules completion
362364 // callbacks, if a root is blocked.
363365 function shouldWorkOnRoot ( root : FiberRoot ) : ExpirationTime {
364- const completedAt = root . completedAt ;
365366 const expirationTime = root . current . expirationTime ;
366-
367367 if ( expirationTime === NoWork ) {
368368 // There's no work in this tree.
369369 return NoWork ;
370370 }
371-
372- if ( completedAt !== NoWork ) {
373- // The root completed but was blocked from committing.
374- if ( expirationTime < completedAt ) {
375- // We have work that expires earlier than the completed root.
376- return expirationTime ;
377- }
378-
379- // If the expiration time of the pending work is equal to the time at
380- // which we completed the work-in-progress, it's possible additional
381- // work was scheduled that happens to fall within the same expiration
382- // bucket. We need to check the work-in-progress fiber.
383- if ( expirationTime === completedAt ) {
384- const workInProgress = root . current . alternate ;
385- if (
386- workInProgress !== null &&
387- ( workInProgress . expirationTime !== NoWork &&
388- workInProgress . expirationTime <= expirationTime )
389- ) {
390- // We have more work. Restart the completed tree.
391- root . completedAt = NoWork ;
392- return expirationTime ;
393- }
394- }
395-
396- // There have been no higher priority updates since we completed the root.
397- // If it's still blocked, return NoWork, as if it has no more work. If it's
398- // no longer blocked, return the time at which it completed so that we
399- // can commit it.
400- if ( isRootBlocked ( root , completedAt ) ) {
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 ) ;
405- return NoWork ;
406- }
407-
408- return completedAt ;
371+ if ( root . isBlocked ) {
372+ // We usually process completion callbacks right after a root is
373+ // completed. But this root already completed, and it's possible that
374+ // we received new completion callbacks since then.
375+ processCompletionCallbacks ( root , root . completedAt ) ;
376+ return NoWork ;
409377 }
410-
411378 return expirationTime ;
412379 }
413380
@@ -818,16 +785,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
818785 workInProgress = returnFiber ;
819786 continue ;
820787 } else {
788+ // We've reached the root. Mark it as complete.
821789 const root = workInProgress . stateNode ;
822- // We've reached the root. Mark the root as complete. Depending on how
823- // much time we have left, we'll either commit it now or in the
824- // next frame.
825- if ( isRootBlocked ( root , nextRenderExpirationTime ) ) {
826- // The root is blocked from committing. Mark it as complete so we
827- // know we can commit it later without starting new work.
828- root . completedAt = nextRenderExpirationTime ;
829- } else {
830- // The root is not blocked, so we can commit it now.
790+ root . completedAt = nextRenderExpirationTime ;
791+ // If the root isn't blocked, it's ready to commit. If it is blocked,
792+ // we'll come back to it later.
793+ if ( ! root . isBlocked ) {
831794 pendingCommit = workInProgress ;
832795 }
833796 processCompletionCallbacks ( root , nextRenderExpirationTime ) ;
@@ -1510,25 +1473,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15101473 }
15111474 }
15121475
1513- function scheduleRoot ( root : FiberRoot , expirationTime : ExpirationTime ) {
1514- if ( expirationTime === NoWork ) {
1515- return ;
1516- }
1517-
1518- if ( ! root . isScheduled ) {
1519- root . isScheduled = true ;
1520- if ( lastScheduledRoot ) {
1521- // Schedule ourselves to the end.
1522- lastScheduledRoot . nextScheduledRoot = root ;
1523- lastScheduledRoot = root ;
1524- } else {
1525- // We're the only work scheduled.
1526- nextScheduledRoot = root ;
1527- lastScheduledRoot = root ;
1528- }
1529- }
1530- }
1531-
15321476 function scheduleUpdate (
15331477 fiber : Fiber ,
15341478 partialState : mixed ,
@@ -1550,6 +1494,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15501494 isReplace,
15511495 isForced,
15521496 nextCallback : null ,
1497+ isTopLevelUnmount : false ,
15531498 next : null ,
15541499 } ;
15551500 insertUpdateIntoFiber ( fiber , update , currentTime ) ;
@@ -1595,35 +1540,45 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15951540 }
15961541
15971542 let node = fiber ;
1598- let shouldContinue = true ;
1599- while ( node !== null && shouldContinue ) {
1600- // Walk the parent path to the root and update each node's expiration
1601- // time. Once we reach a node whose expiration matches (and whose
1602- // alternate's expiration matches) we can exit safely knowing that the
1603- // rest of the path is correct.
1604- shouldContinue = false ;
1543+ while ( node !== null ) {
16051544 if (
16061545 node . expirationTime === NoWork ||
16071546 node . expirationTime > expirationTime
16081547 ) {
1609- // Expiration time did not match. Update and keep going.
1610- shouldContinue = true ;
16111548 node . expirationTime = expirationTime ;
16121549 }
16131550 if ( node . alternate !== null ) {
16141551 if (
16151552 node . alternate . expirationTime === NoWork ||
16161553 node . alternate . expirationTime > expirationTime
16171554 ) {
1618- // Expiration time did not match. Update and keep going.
1619- shouldContinue = true ;
16201555 node . alternate . expirationTime = expirationTime ;
16211556 }
16221557 }
16231558 if ( node . return === null ) {
16241559 if ( node . tag === HostRoot ) {
16251560 const root : FiberRoot = ( node . stateNode : any ) ;
1626- scheduleRoot ( root , expirationTime ) ;
1561+
1562+ // Add the root to the work schedule.
1563+ if ( expirationTime !== NoWork ) {
1564+ root . isBlocked = false ;
1565+ if ( ! root . isScheduled ) {
1566+ root . isScheduled = true ;
1567+ if ( lastScheduledRoot ) {
1568+ // Schedule ourselves to the end.
1569+ lastScheduledRoot . nextScheduledRoot = root ;
1570+ lastScheduledRoot = root ;
1571+ } else {
1572+ // We're the only work scheduled.
1573+ nextScheduledRoot = root ;
1574+ lastScheduledRoot = root ;
1575+ }
1576+ }
1577+ }
1578+
1579+ // If we're not current performing work, we need to either start
1580+ // working now (if the update is synchronous) or schedule a callback
1581+ // to perform work later.
16271582 if ( ! isPerformingWork ) {
16281583 const priorityLevel = expirationTimeToPriorityLevel (
16291584 mostRecentCurrentTime ,
@@ -1775,6 +1730,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
17751730 'Cannot commit while already performing work.' ,
17761731 ) ;
17771732 root . forceExpire = expirationTime ;
1733+ root . isBlocked = false ;
17781734 try {
17791735 performWork ( TaskPriority , null ) ;
17801736 } finally {
0 commit comments