From 2c83514ed36848d88a5865e8eff0a92ee7bc77aa Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 28 Sep 2017 18:24:12 +0100 Subject: [PATCH] Decouple setting the current fiber and phase These are two distinct actions. This helps centralize setting the current fiber in the scheduler. I'm also removing a hack that's only useful in the corner case if you use unstable_renderSubtree() and top component has invalid child context type. This makes the code more straightforward. --- .../shared/fiber/ReactDebugCurrentFiber.js | 7 ++- .../shared/fiber/ReactFiberBeginWork.js | 10 ++-- .../shared/fiber/ReactFiberCompleteWork.js | 2 +- .../shared/fiber/ReactFiberContext.js | 52 ++++--------------- .../shared/fiber/ReactFiberReconciler.js | 2 +- .../shared/fiber/ReactFiberScheduler.js | 2 +- 6 files changed, 23 insertions(+), 52 deletions(-) diff --git a/src/renderers/shared/fiber/ReactDebugCurrentFiber.js b/src/renderers/shared/fiber/ReactDebugCurrentFiber.js index a34e1d14e5e2b..16a4096bd7282 100644 --- a/src/renderers/shared/fiber/ReactDebugCurrentFiber.js +++ b/src/renderers/shared/fiber/ReactDebugCurrentFiber.js @@ -55,9 +55,13 @@ function resetCurrentFiber() { ReactDebugCurrentFiber.phase = null; } -function setCurrentFiber(fiber: Fiber | null, phase: LifeCyclePhase | null) { +function setCurrentFiber(fiber: Fiber) { ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum; ReactDebugCurrentFiber.current = fiber; + ReactDebugCurrentFiber.phase = null; +} + +function setCurrentPhase(phase: LifeCyclePhase | null) { ReactDebugCurrentFiber.phase = phase; } @@ -66,6 +70,7 @@ var ReactDebugCurrentFiber = { phase: (null: LifeCyclePhase | null), resetCurrentFiber, setCurrentFiber, + setCurrentPhase, getCurrentFiberOwnerName, getCurrentFiberStackAddendum, }; diff --git a/src/renderers/shared/fiber/ReactFiberBeginWork.js b/src/renderers/shared/fiber/ReactFiberBeginWork.js index 9b945305d4b05..611ff57d52f5e 100644 --- a/src/renderers/shared/fiber/ReactFiberBeginWork.js +++ b/src/renderers/shared/fiber/ReactFiberBeginWork.js @@ -207,9 +207,9 @@ module.exports = function( if (__DEV__) { ReactCurrentOwner.current = workInProgress; - ReactDebugCurrentFiber.setCurrentFiber(workInProgress, 'render'); + ReactDebugCurrentFiber.setCurrentPhase('render'); nextChildren = fn(nextProps, context); - ReactDebugCurrentFiber.setCurrentFiber(workInProgress, null); + ReactDebugCurrentFiber.setCurrentPhase(null); } else { nextChildren = fn(nextProps, context); } @@ -281,9 +281,9 @@ module.exports = function( ReactCurrentOwner.current = workInProgress; let nextChildren; if (__DEV__) { - ReactDebugCurrentFiber.setCurrentFiber(workInProgress, 'render'); + ReactDebugCurrentFiber.setCurrentPhase('render'); nextChildren = instance.render(); - ReactDebugCurrentFiber.setCurrentFiber(workInProgress, null); + ReactDebugCurrentFiber.setCurrentPhase(null); } else { nextChildren = instance.render(); } @@ -726,7 +726,7 @@ module.exports = function( } if (__DEV__) { - ReactDebugCurrentFiber.setCurrentFiber(workInProgress, null); + ReactDebugCurrentFiber.setCurrentFiber(workInProgress); } switch (workInProgress.tag) { diff --git a/src/renderers/shared/fiber/ReactFiberCompleteWork.js b/src/renderers/shared/fiber/ReactFiberCompleteWork.js index 41393a19e22ef..28009a0466f8a 100644 --- a/src/renderers/shared/fiber/ReactFiberCompleteWork.js +++ b/src/renderers/shared/fiber/ReactFiberCompleteWork.js @@ -188,7 +188,7 @@ module.exports = function( renderPriority: PriorityLevel, ): Fiber | null { if (__DEV__) { - ReactDebugCurrentFiber.setCurrentFiber(workInProgress, null); + ReactDebugCurrentFiber.setCurrentFiber(workInProgress); } // Get the latest props. diff --git a/src/renderers/shared/fiber/ReactFiberContext.js b/src/renderers/shared/fiber/ReactFiberContext.js index 7f5a8bf8a2b4f..8c5bb96526177 100644 --- a/src/renderers/shared/fiber/ReactFiberContext.js +++ b/src/renderers/shared/fiber/ReactFiberContext.js @@ -89,13 +89,6 @@ exports.getMaskedContext = function( if (__DEV__) { const name = getComponentName(workInProgress) || 'Unknown'; - if (workInProgress !== ReactDebugCurrentFiber.current) { - warning( - false, - 'Expected the work in progress to match the currently processed fiber. ' + - 'This error is likely caused by a bug in React. Please file an issue.', - ); - } checkPropTypes( contextTypes, context, @@ -158,11 +151,7 @@ exports.pushTopLevelContextObject = function( push(didPerformWorkStackCursor, didChange, fiber); }; -function processChildContext( - fiber: Fiber, - parentContext: Object, - isReconciling: boolean, -): Object { +function processChildContext(fiber: Fiber, parentContext: Object): Object { const instance = fiber.stateNode; const childContextTypes = fiber.type.childContextTypes; @@ -189,19 +178,11 @@ function processChildContext( let childContext; if (__DEV__) { - // TODO: we only have to store the "previous" fiber and phase and restore them - // because this method can be called outside of reconciliation. We can remove this - // when we stop supporting unstable_renderSubtreeIntoContainer. - const previousCurrentFiber = ReactDebugCurrentFiber.current; - const previousCurrentPhase = ReactDebugCurrentFiber.phase; - ReactDebugCurrentFiber.setCurrentFiber(fiber, 'getChildContext'); + ReactDebugCurrentFiber.setCurrentPhase('getChildContext'); startPhaseTimer(fiber, 'getChildContext'); childContext = instance.getChildContext(); stopPhaseTimer(); - ReactDebugCurrentFiber.setCurrentFiber( - previousCurrentFiber, - previousCurrentPhase, - ); + ReactDebugCurrentFiber.setCurrentPhase(null); } else { childContext = instance.getChildContext(); } @@ -215,29 +196,18 @@ function processChildContext( } if (__DEV__) { const name = getComponentName(fiber) || 'Unknown'; - // We can only provide accurate element stacks if we pass work-in-progress tree - // during the begin or complete phase. However currently this function is also - // called from unstable_renderSubtree legacy implementation. In this case it unsafe to - // assume anything about the given fiber. We won't pass it down if we aren't sure. - // TODO: remove this hack when we delete unstable_renderSubtree in Fiber. - const workInProgress = isReconciling ? fiber : null; - // TODO: we only have to store the "previous" fiber and phase and restore them - // because this method can be called outside of reconciliation. We can remove this - // when we stop supporting unstable_renderSubtreeIntoContainer. - const previousCurrentFiber = ReactDebugCurrentFiber.current; - const previousCurrentPhase = ReactDebugCurrentFiber.phase; - ReactDebugCurrentFiber.setCurrentFiber(workInProgress, null); checkPropTypes( childContextTypes, childContext, 'child context', name, + // In practice, there is one case in which we won't get a stack. It's when + // somebody calls unstable_renderSubtreeIntoContainer() and we process + // context from the parent component instance. The stack will be missing + // because it's outside of the reconciliation, and so the pointer has not + // been set. This is rare and doesn't matter. We'll also remove that API. ReactDebugCurrentFiber.getCurrentFiberStackAddendum, ); - ReactDebugCurrentFiber.setCurrentFiber( - previousCurrentFiber, - previousCurrentPhase, - ); } return {...parentContext, ...childContext}; @@ -285,11 +255,7 @@ exports.invalidateContextProvider = function( // Merge parent and own context. // Skip this if we're not updating due to sCU. // This avoids unnecessarily recomputing memoized values. - const mergedContext = processChildContext( - workInProgress, - previousContext, - true, - ); + const mergedContext = processChildContext(workInProgress, previousContext); instance.__reactInternalMemoizedMergedChildContext = mergedContext; // Replace the old (or empty) context with the new one. diff --git a/src/renderers/shared/fiber/ReactFiberReconciler.js b/src/renderers/shared/fiber/ReactFiberReconciler.js index 8b9fa1d3df7e0..23738f3c40143 100644 --- a/src/renderers/shared/fiber/ReactFiberReconciler.js +++ b/src/renderers/shared/fiber/ReactFiberReconciler.js @@ -181,7 +181,7 @@ export type Reconciler = { getContextForSubtree._injectFiber(function(fiber: Fiber) { const parentContext = findCurrentUnmaskedContext(fiber); return isContextProvider(fiber) - ? processChildContext(fiber, parentContext, false) + ? processChildContext(fiber, parentContext) : parentContext; }); diff --git a/src/renderers/shared/fiber/ReactFiberScheduler.js b/src/renderers/shared/fiber/ReactFiberScheduler.js index dcaea4aa86092..29459fc85b8d8 100644 --- a/src/renderers/shared/fiber/ReactFiberScheduler.js +++ b/src/renderers/shared/fiber/ReactFiberScheduler.js @@ -317,7 +317,7 @@ module.exports = function( function commitAllHostEffects() { while (nextEffect !== null) { if (__DEV__) { - ReactDebugCurrentFiber.setCurrentFiber(nextEffect, null); + ReactDebugCurrentFiber.setCurrentFiber(nextEffect); recordEffect(); }