diff --git a/src/renderers/dom/fiber/ReactDOMFiberEntry.js b/src/renderers/dom/fiber/ReactDOMFiberEntry.js index 18b33854e11a5..4a9d238ec0ec8 100644 --- a/src/renderers/dom/fiber/ReactDOMFiberEntry.js +++ b/src/renderers/dom/fiber/ReactDOMFiberEntry.js @@ -447,11 +447,7 @@ var DOMRenderer = ReactFiberReconciler({ } }, - now() { - // TODO: Use performance.now to enable expiration - // return 0; - return now(); - }, + now, canHydrateInstance( instance: Instance | TextInstance, diff --git a/src/renderers/shared/fiber/ReactFiberExpirationTime.js b/src/renderers/shared/fiber/ReactFiberExpirationTime.js index dd62030d3b380..cba7592ab531e 100644 --- a/src/renderers/shared/fiber/ReactFiberExpirationTime.js +++ b/src/renderers/shared/fiber/ReactFiberExpirationTime.js @@ -28,11 +28,13 @@ const invariant = require('fbjs/lib/invariant'); export type ExpirationTime = number; const Done = 0; -exports.Done = Done; +const Sync = 1; +const Task = 2; +const Never = Infinity; -const MAGIC_NUMBER_OFFSET = 2; +const MAGIC_NUMBER_OFFSET = 10; -const Never = Infinity; +exports.Done = Done; exports.Never = Infinity; // 1 unit of expiration time represents 10ms. @@ -63,11 +65,9 @@ function priorityToExpirationTime( case NoWork: return Done; case SynchronousPriority: - // Return a number lower than the current time, but higher than Done. - return MAGIC_NUMBER_OFFSET - 1; + return Sync; case TaskPriority: - // Return the current time, so that this work completes in this batch. - return currentTime; + return Task; case HighPriority: // Should complete within ~100ms. 120ms max. return msToExpirationTime(ceiling(100, 20)); @@ -95,16 +95,19 @@ function expirationTimeToPriorityLevel( expirationTime: ExpirationTime, ): PriorityLevel { // First check for magic values - if (expirationTime === Done) { - return NoWork; - } - if (expirationTime === Never) { - return OffscreenPriority; - } - if (expirationTime < currentTime) { - return SynchronousPriority; + switch (expirationTime) { + case Done: + return NoWork; + case Sync: + return SynchronousPriority; + case Task: + return TaskPriority; + case Never: + return OffscreenPriority; + default: + break; } - if (expirationTime === currentTime) { + if (expirationTime <= currentTime) { return TaskPriority; } // Keep this value in sync with priorityToExpirationTime. diff --git a/src/renderers/shared/fiber/ReactFiberScheduler.js b/src/renderers/shared/fiber/ReactFiberScheduler.js index 5175b1781b4f8..b7c590afc562c 100644 --- a/src/renderers/shared/fiber/ReactFiberScheduler.js +++ b/src/renderers/shared/fiber/ReactFiberScheduler.js @@ -992,7 +992,7 @@ module.exports = function( // Read the current time from the host environment. const currentTime = recalculateCurrentTime(); - const minExpirationTime = priorityToExpirationTime( + const minExpirationTime = getExpirationTimeForPriority( currentTime, minPriorityLevel, ); @@ -1447,30 +1447,36 @@ module.exports = function( const root: FiberRoot = (node.stateNode: any); scheduleRoot(root, expirationTime); if (!isPerformingWork) { - if (expirationTime < mostRecentCurrentTime) { - // This update is synchronous. Perform it now. - if (isUnbatchingUpdates) { - // We're inside unbatchedUpdates, which is inside either - // batchedUpdates or a lifecycle. We should only flush - // synchronous work, not task work. - performWork(SynchronousPriority, null); - } else { - // Flush both synchronous and task work. - performWork(TaskPriority, null); - } - } else if (expirationTime === mostRecentCurrentTime) { - invariant( - isBatchingUpdates, - 'Task updates can only be scheduled as a nested update or ' + - 'inside batchedUpdates. This error is likely caused by a ' + - 'bug in React. Please file an issue.', - ); - } else { - // This update is async. Schedule a callback. - if (!isCallbackScheduled) { - scheduleDeferredCallback(performDeferredWork); - isCallbackScheduled = true; - } + const priorityLevel = expirationTimeToPriorityLevel( + mostRecentCurrentTime, + expirationTime, + ); + switch (priorityLevel) { + case SynchronousPriority: + if (isUnbatchingUpdates) { + // We're inside unbatchedUpdates, which is inside either + // batchedUpdates or a lifecycle. We should only flush + // synchronous work, not task work. + performWork(SynchronousPriority, null); + } else { + // Flush both synchronous and task work. + performWork(TaskPriority, null); + } + break; + case TaskPriority: + invariant( + isBatchingUpdates, + 'Task updates can only be scheduled as a nested update or ' + + 'inside batchedUpdates. This error is likely caused by a ' + + 'bug in React. Please file an issue.', + ); + break; + default: + // This update is async. Schedule a callback. + if (!isCallbackScheduled) { + scheduleDeferredCallback(performDeferredWork); + isCallbackScheduled = true; + } } } } else { @@ -1533,11 +1539,11 @@ module.exports = function( } function scheduleErrorRecovery(fiber: Fiber) { - scheduleUpdateImpl( - fiber, - priorityToExpirationTime(mostRecentCurrentTime, TaskPriority), - true, + const taskTime = getExpirationTimeForPriority( + mostRecentCurrentTime, + TaskPriority, ); + scheduleUpdateImpl(fiber, taskTime, true); } function recalculateCurrentTime(): ExpirationTime {