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,