@@ -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 = Done ;
339337 nextUnitOfWork = createWorkInProgress (
340338 earliestExpirationRoot . current ,
341339 earliestExpirationTime ,
342340 ) ;
343341 }
342+
343+ earliestExpirationRoot . completedAt = Done ;
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 === Done ) {
367367 // There's no work in this tree.
368368 return Done ;
369369 }
370-
371- if ( completedAt !== Done ) {
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 !== Done &&
387- workInProgress . expirationTime <= expirationTime )
388- ) {
389- // We have more work. Restart the completed tree.
390- root . completedAt = Done ;
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 Done, 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 Done ;
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 Done ;
408376 }
409-
410377 return expirationTime ;
411378 }
412379
@@ -816,16 +783,12 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
816783 workInProgress = returnFiber ;
817784 continue ;
818785 } else {
786+ // We've reached the root. Mark it as complete.
819787 const root = workInProgress . stateNode ;
820- // We've reached the root. Mark the root as complete. Depending on how
821- // much time we have left, we'll either commit it now or in the
822- // next frame.
823- if ( isRootBlocked ( root , nextRenderExpirationTime ) ) {
824- // The root is blocked from committing. Mark it as complete so we
825- // know we can commit it later without starting new work.
826- root . completedAt = nextRenderExpirationTime ;
827- } else {
828- // The root is not blocked, so we can commit it now.
788+ root . completedAt = nextRenderExpirationTime ;
789+ // If the root isn't blocked, it's ready to commit. If it is blocked,
790+ // we'll come back to it later.
791+ if ( ! root . isBlocked ) {
829792 pendingCommit = workInProgress ;
830793 }
831794 processCompletionCallbacks ( root , nextRenderExpirationTime ) ;
@@ -1508,25 +1471,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15081471 }
15091472 }
15101473
1511- function scheduleRoot ( root : FiberRoot , expirationTime : ExpirationTime ) {
1512- if ( expirationTime === Done ) {
1513- return ;
1514- }
1515-
1516- if ( ! root . isScheduled ) {
1517- root . isScheduled = true ;
1518- if ( lastScheduledRoot ) {
1519- // Schedule ourselves to the end.
1520- lastScheduledRoot . nextScheduledRoot = root ;
1521- lastScheduledRoot = root ;
1522- } else {
1523- // We're the only work scheduled.
1524- nextScheduledRoot = root ;
1525- lastScheduledRoot = root ;
1526- }
1527- }
1528- }
1529-
15301474 function scheduleUpdate (
15311475 fiber : Fiber ,
15321476 partialState : mixed ,
@@ -1548,6 +1492,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15481492 isReplace,
15491493 isForced,
15501494 nextCallback : null ,
1495+ isTopLevelUnmount : false ,
15511496 next : null ,
15521497 } ;
15531498 insertUpdateIntoFiber ( fiber , update , currentTime ) ;
@@ -1593,35 +1538,45 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
15931538 }
15941539
15951540 let node = fiber ;
1596- let shouldContinue = true ;
1597- while ( node !== null && shouldContinue ) {
1598- // Walk the parent path to the root and update each node's expiration
1599- // time. Once we reach a node whose expiration matches (and whose
1600- // alternate's expiration matches) we can exit safely knowing that the
1601- // rest of the path is correct.
1602- shouldContinue = false ;
1541+ while ( node !== null ) {
16031542 if (
16041543 node . expirationTime === Done ||
16051544 node . expirationTime > expirationTime
16061545 ) {
1607- // Expiration time did not match. Update and keep going.
1608- shouldContinue = true ;
16091546 node . expirationTime = expirationTime ;
16101547 }
16111548 if ( node . alternate !== null ) {
16121549 if (
16131550 node . alternate . expirationTime === Done ||
16141551 node . alternate . expirationTime > expirationTime
16151552 ) {
1616- // Expiration time did not match. Update and keep going.
1617- shouldContinue = true ;
16181553 node . alternate . expirationTime = expirationTime ;
16191554 }
16201555 }
16211556 if ( node . return === null ) {
16221557 if ( node . tag === HostRoot ) {
16231558 const root : FiberRoot = ( node . stateNode : any ) ;
1624- scheduleRoot ( root , expirationTime ) ;
1559+
1560+ // Add the root to the work schedule.
1561+ if ( expirationTime !== Done ) {
1562+ root . isBlocked = false ;
1563+ if ( ! root . isScheduled ) {
1564+ root . isScheduled = true ;
1565+ if ( lastScheduledRoot ) {
1566+ // Schedule ourselves to the end.
1567+ lastScheduledRoot . nextScheduledRoot = root ;
1568+ lastScheduledRoot = root ;
1569+ } else {
1570+ // We're the only work scheduled.
1571+ nextScheduledRoot = root ;
1572+ lastScheduledRoot = root ;
1573+ }
1574+ }
1575+ }
1576+
1577+ // If we're not current performing work, we need to either start
1578+ // working now (if the update is synchronous) or schedule a callback
1579+ // to perform work later.
16251580 if ( ! isPerformingWork ) {
16261581 const priorityLevel = expirationTimeToPriorityLevel (
16271582 mostRecentCurrentTime ,
@@ -1771,6 +1726,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
17711726 'Cannot commit while already performing work.' ,
17721727 ) ;
17731728 root . forceExpire = expirationTime ;
1729+ root . isBlocked = false ;
17741730 try {
17751731 performWork ( TaskPriority , null ) ;
17761732 } finally {
0 commit comments