Move context handling back into Begin and Complete phases
As per discussion, this is better because then this code only runs for the class type of work. We will still need to fix bailouts for deep setState calls.
Dan Abramov committed
Nov 14, 2016 at 16:19 UTC
56e1c126c5c29339f8bad4164f8ee510b79a6ea4
3 files changed
+25
-23
src/renderers/shared/fiber/ReactFiberBeginWork.js
+16
@@ -27,6 +27,9 @@ var {
27
var ReactTypeOfWork = require('ReactTypeOfWork');
28
var {
29
getMaskedContext,
30
+ isContextProvider,
31
+ pushContextProvider,
32
+ resetContext,
33
} = require('ReactFiberContext');
34
var {
35
IndeterminateComponent,
@@ -195,6 +198,10 @@ module.exports = function<T, P, I, TI, C>(
198
ReactCurrentOwner.current = workInProgress;
199
const nextChildren = instance.render();
200
reconcileChildren(current, workInProgress, nextChildren);
201
+ // Put context on the stack because we will work on children
202
+ if (isContextProvider(workInProgress)) {
203
+ pushContextProvider(workInProgress);
204
+ }
205
return workInProgress.child;
206
}
207
@@ -352,6 +359,10 @@ module.exports = function<T, P, I, TI, C>(
359
360
cloneChildFibers(current, workInProgress);
361
markChildAsProgressed(current, workInProgress, priorityLevel);
362
+ // Put context on the stack because we will work on children
363
+ if (isContextProvider(workInProgress)) {
364
+ pushContextProvider(workInProgress);
365
+ }
366
return workInProgress.child;
367
}
368
@@ -362,6 +373,11 @@ module.exports = function<T, P, I, TI, C>(
373
}
374
375
function beginWork(current : ?Fiber, workInProgress : Fiber, priorityLevel : PriorityLevel) : ?Fiber {
376
+ if (!workInProgress.return) {
377
+ // Don't start new work with context on the stack.
378
+ resetContext();
379
+ }
380
+
381
if (workInProgress.pendingWorkPriority === NoWork ||
382
workInProgress.pendingWorkPriority > priorityLevel) {
383
return bailoutOnLowPriority(current, workInProgress);
src/renderers/shared/fiber/ReactFiberCompleteWork.js
+8
@@ -18,6 +18,10 @@ import type { HostConfig } from 'ReactFiberReconciler';
18
import type { ReifiedYield } from 'ReactReifiedYield';
19
20
var { reconcileChildFibers } = require('ReactChildFiber');
21
+var {
22
+ isContextProvider,
23
+ popContextProvider,
24
+} = require('ReactFiberContext');
25
var ReactTypeOfWork = require('ReactTypeOfWork');
26
var ReactTypeOfSideEffect = require('ReactTypeOfSideEffect');
27
var {
@@ -125,6 +129,10 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
129
return null;
130
case ClassComponent:
131
transferOutput(workInProgress.child, workInProgress);
132
+ // We are leaving this subtree, so pop context if any.
133
+ if (isContextProvider(workInProgress)) {
134
+ popContextProvider();
135
+ }
136
// Don't use the state queue to compute the memoized state. We already
137
// merged it and assigned it to the instance. Transfer it from there.
138
// Also need to transfer the props, because pendingProps will be null
src/renderers/shared/fiber/ReactFiberScheduler.js
+1
-23
@@ -24,13 +24,6 @@ var ReactCurrentOwner = require('ReactCurrentOwner');
24
25
var { cloneFiber } = require('ReactFiber');
26
27
-var {
28
- isContextProvider,
29
- pushContextProvider,
30
- popContextProvider,
31
- resetContext,
32
-} = require('ReactFiberContext');
33
-
27
var {
28
NoWork,
29
SynchronousPriority,
@@ -274,11 +267,6 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
267
const current = workInProgress.alternate;
268
const next = completeWork(current, workInProgress);
269
277
- // We are leaving this subtree, so pop context if any.
278
- if (isContextProvider(workInProgress)) {
279
- popContextProvider();
280
- }
281
-
270
resetWorkPriority(workInProgress);
271
272
// The work is now done. We don't need this anymore. This flags
@@ -357,11 +345,6 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
345
}
346
347
function performUnitOfWork(workInProgress : Fiber) : ?Fiber {
360
- if (!workInProgress.return) {
361
- // Don't start new work with context on the stack.
362
- resetContext();
363
- }
364
-
348
// The current, flushed, state of this fiber is the alternate.
349
// Ideally nothing should rely on this, but relying on it here
350
// means that we don't need an additional field on the work in
@@ -377,12 +360,7 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
360
ReactFiberInstrumentation.debugTool.onDidBeginWork(workInProgress);
361
}
362
380
- if (next) {
381
- // There is work deeper in the tree, so push the context if it exists.
382
- if (isContextProvider(workInProgress)) {
383
- pushContextProvider(workInProgress);
384
- }
385
- } else {
363
+ if (!next) {
364
if (__DEV__ && ReactFiberInstrumentation.debugTool) {
365
ReactFiberInstrumentation.debugTool.onWillCompleteWork(workInProgress);
366
}