@samitouri / QOS-React-2 / commits / 38a297d500

Always reset context before beginning new work

This consolidates the reset of context to one single place right before any new work is started. This place is burried in a bit of an awkward place but findNextUnitOfWork happens right before any new work starts. That way we're guaranteed to have an empty stack before we start anything new. The benefit of this is that we don't have to rely .return being null when entering beginWork but we also don't have to check it every time in the hot path.

Sebastian Markbage committed Dec 20, 2016 at 20:56 UTC 38a297d50035d86290a44d6e9bd8bc19f335013b
3 files changed +16 -11
src/renderers/shared/fiber/ReactFiberBeginWork.js
+1 -8
@@ -36,7 +36,6 @@ var {
36 hasContextChanged,
37 pushContextProvider,
38 pushTopLevelContextObject,
39 - resetContext,
39 } = require('ReactFiberContext');
40 var {
41 IndeterminateComponent,
@@ -80,7 +79,6 @@ module.exports = function<T, P, I, TI, C, CX>(
79 const {
80 pushHostContext,
81 pushHostContainer,
83 - resetHostContainer,
82 } = hostContext;
83
84 const {
@@ -437,6 +435,7 @@ module.exports = function<T, P, I, TI, C, CX>(
435 if (isHostComponent) {
436 pushHostContext(workInProgress);
437 } else {
438 + // TODO: Unify this switch with the other branches above.
439 switch (workInProgress.tag) {
440 case ClassComponent:
441 if (isContextProvider(workInProgress)) {
@@ -473,12 +472,6 @@ module.exports = function<T, P, I, TI, C, CX>(
472 }
473
474 function beginWork(current : ?Fiber, workInProgress : Fiber, priorityLevel : PriorityLevel) : ?Fiber {
476 - if (!workInProgress.return) {
477 - // Don't start new work with context on the stack.
478 - resetContext();
479 - resetHostContainer();
480 - }
481 -
475 if (workInProgress.pendingWorkPriority === NoWork ||
476 workInProgress.pendingWorkPriority > priorityLevel) {
477 return bailoutOnLowPriority(current, workInProgress);
src/renderers/shared/fiber/ReactFiberCompleteWork.js
+1
@@ -189,6 +189,7 @@ module.exports = function<T, P, I, TI, C, CX>(
189 return null;
190 }
191 case HostRoot: {
192 + // TODO: Pop the host container after #8607 lands.
193 workInProgress.memoizedProps = workInProgress.pendingProps;
194 const fiberRoot = (workInProgress.stateNode : FiberRoot);
195 if (fiberRoot.pendingContext) {
src/renderers/shared/fiber/ReactFiberScheduler.js
+14 -3
@@ -58,6 +58,7 @@ var {
58 } = require('ReactFiberUpdateQueue');
59
60 var {
61 + resetContext,
62 unwindContext,
63 } = require('ReactFiberContext');
64
@@ -153,6 +154,11 @@ module.exports = function<T, P, I, TI, C, CX>(config : HostConfig<T, P, I, TI, C
154 }
155 }
156
157 + function resetContextStack() {
158 + resetContext();
159 + resetHostContainer();
160 + }
161 +
162 // findNextUnitOfWork mutates the current priority context. It is reset after
163 // after the workLoop exits, so never call findNextUnitOfWork from outside
164 // the work loop.
@@ -193,6 +199,14 @@ module.exports = function<T, P, I, TI, C, CX>(config : HostConfig<T, P, I, TI, C
199 if (highestPriorityRoot) {
200 nextPriorityLevel = highestPriorityLevel;
201 priorityContext = nextPriorityLevel;
202 +
203 + // Before we start any new work, let's make sure that we have a fresh
204 + // stack to work from.
205 + // TODO: This call is burried a bit too deep. It would be nice to have
206 + // a single point which happens right before any new work and
207 + // unfortunately this is it.
208 + resetContextStack();
209 +
210 return cloneFiber(
211 highestPriorityRoot.current,
212 highestPriorityLevel
@@ -346,9 +360,6 @@ module.exports = function<T, P, I, TI, C, CX>(config : HostConfig<T, P, I, TI, C
360 }
361
362 resetAfterCommit();
349 - // We didn't pop the host root in the complete phase because we still needed
350 - // it for the commitUpdate() calls, but now we can reset host context.
351 - resetHostContainer();
363
364 // In the second pass we'll perform all life-cycles and ref callbacks.
365 // Life-cycles happen as a separate pass so that all placements, updates,