Drop childInProgress
I will try a slightly different but similar strategy.
Sebastian Markbage committed
Sep 1, 2016 at 20:50 UTC
49f0c952b5f796500fb25188e89be4099b0b740e
2 files changed
+47
-89
src/renderers/shared/fiber/ReactFiber.js
-9
@@ -89,7 +89,6 @@ export type Fiber = Instance & {
89
firstEffect: ?Fiber,
90
lastEffect: ?Fiber,
91
92
-
92
// This will be used to quickly determine if a subtree has no pending changes.
93
pendingWorkPriority: PriorityLevel,
94
@@ -98,10 +97,6 @@ export type Fiber = Instance & {
97
// memory if we need to.
98
alternate: ?Fiber,
99
101
- // Keeps track of the children that are currently being processed but have not
102
- // yet completed.
103
- childInProgress: ?Fiber,
104
-
100
// Conceptual aliases
101
// workInProgress : Fiber -> alternate The alternate used for reuse happens
102
// to be the same as work in progress.
@@ -140,8 +135,6 @@ var createFiber = function(tag : TypeOfWork, key : null | string) : Fiber {
135
136
pendingWorkPriority: NoWork,
137
143
- childInProgress: null,
144
-
138
alternate: null,
139
140
};
@@ -162,7 +155,6 @@ exports.cloneFiber = function(fiber : Fiber, priorityLevel : PriorityLevel) : Fi
155
if (alt) {
156
alt.stateNode = fiber.stateNode;
157
alt.child = fiber.child;
165
- alt.childInProgress = fiber.childInProgress;
158
alt.sibling = fiber.sibling;
159
alt.ref = fiber.ref;
160
alt.pendingProps = fiber.pendingProps;
@@ -185,7 +177,6 @@ exports.cloneFiber = function(fiber : Fiber, priorityLevel : PriorityLevel) : Fi
177
alt.type = fiber.type;
178
alt.stateNode = fiber.stateNode;
179
alt.child = fiber.child;
188
- alt.childInProgress = fiber.childInProgress;
180
alt.sibling = fiber.sibling;
181
alt.ref = fiber.ref;
182
// pendingProps is here for symmetry but is unnecessary in practice for now.
src/renderers/shared/fiber/ReactFiberBeginWork.js
+47
-80
@@ -40,34 +40,28 @@ var {
40
module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
41
42
function reconcileChildren(current, workInProgress, nextChildren) {
43
- // TODO: Children needs to be able to reconcile in place if we are
44
- // overriding progressed work.
45
- const priority = workInProgress.pendingWorkPriority;
46
- reconcileChildrenAtPriority(current, workInProgress, nextChildren, priority);
47
- }
48
-
49
- function reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel) {
50
- if (current && current.childInProgress) {
51
- workInProgress.childInProgress = reconcileChildFibersInPlace(
52
- workInProgress,
53
- current.childInProgress,
54
- nextChildren,
55
- priorityLevel
56
- );
57
- // This is now invalid because we reused nodes.
58
- current.childInProgress = null;
59
- } else if (workInProgress.childInProgress) {
60
- workInProgress.childInProgress = reconcileChildFibersInPlace(
43
+ const priorityLevel = workInProgress.pendingWorkPriority;
44
+ // At this point any memoization is no longer valid since we'll have changed
45
+ // the children.
46
+ workInProgress.memoizedProps = null;
47
+ if (current && current.child === workInProgress.child) {
48
+ // If the current child is the same as the work in progress, it means that
49
+ // we haven't yet started any work on these children. Therefore, we use
50
+ // the clone algorithm to create a copy of all the current children.
51
+ workInProgress.child = reconcileChildFibers(
52
workInProgress,
62
- workInProgress.childInProgress,
53
+ workInProgress.child,
54
nextChildren,
55
priorityLevel
56
);
57
} else {
67
- // TODO:
68
- workInProgress.childInProgress = reconcileChildFibers(
58
+ // If, on the other hand, we don't have a current fiber or if it is
59
+ // already using a clone, that means we've already begun some work on this
60
+ // tree and we can continue where we left off by reconciling against the
61
+ // existing children.
62
+ workInProgress.child = reconcileChildFibersInPlace(
63
workInProgress,
70
- current ? current.child : workInProgress.child,
64
+ workInProgress.child,
65
nextChildren,
66
priorityLevel
67
);
@@ -80,7 +74,7 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
74
75
var nextChildren = fn(props);
76
reconcileChildren(current, workInProgress, nextChildren);
83
- return workInProgress.childInProgress;
77
+ return workInProgress.child;
78
}
79
80
function updateClassComponent(current : ?Fiber, workInProgress : Fiber) {
@@ -97,13 +91,13 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
91
return bailoutOnCurrent(current, workInProgress);
92
}
93
}
100
- if (!workInProgress.childInProgress && workInProgress.memoizedProps) {
94
+ if (workInProgress.memoizedProps) {
95
// Reset the props, in case this is a ping-pong case rather than a
96
// completed update case. For the completed update case, the instance
97
// props will already be the memoizedProps.
98
instance.props = workInProgress.memoizedProps;
99
if (!instance.shouldComponentUpdate(props)) {
106
- return bailoutOnAlreadyFinishedWork(current, workInProgress);
100
+ // return bailoutOnAlreadyFinishedWork(current, workInProgress);
101
}
102
}
103
}
@@ -112,44 +106,20 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
106
var nextChildren = instance.render();
107
reconcileChildren(current, workInProgress, nextChildren);
108
115
- return workInProgress.childInProgress;
109
+ return workInProgress.child;
110
}
111
112
function updateHostComponent(current, workInProgress) {
119
- var nextChildren = workInProgress.pendingProps.children;
120
-
121
- let priority = workInProgress.pendingWorkPriority;
122
- if (workInProgress.pendingProps.hidden && priority !== OffscreenPriority) {
123
- // If this host component is hidden, we can reconcile its children at
124
- // the lowest priority and bail out from this particular pass. Unless, we're
125
- // currently reconciling the lowest priority.
126
- // If we have a child in progress already, we reconcile against that set
127
- // to retain any work within it. We'll recreate any component that was in
128
- // the current set and next set but not in the previous in progress set.
129
- // TODO: This attaches a node that hasn't completed rendering so it
130
- // becomes part of the render tree, even though it never completed. Its
131
- // `output` property is unpredictable because of it.
132
- reconcileChildrenAtPriority(current, workInProgress, nextChildren, OffscreenPriority);
133
- workInProgress.child = current ? current.child : null;
134
- let child = workInProgress.childInProgress;
135
- while (child) {
136
- const currentChild = child.alternate;
137
- if (currentChild) {
138
- child.child = currentChild.child;
139
- child.childInProgress = currentChild.childInProgress;
140
- child.memoizedProps = currentChild.memoizedProps;
141
- child.output = currentChild.output;
142
- }
143
- child.nextEffect = null;
144
- child.firstEffect = null;
145
- child.lastEffect = null;
146
-
147
- child = child.sibling;
148
- }
149
- return null;
113
+ if (workInProgress.pendingProps.hidden &&
114
+ workInProgress.pendingWorkPriority !== OffscreenPriority) {
115
+ // If this host component is hidden, we can bail out and ignore this.
116
+ // We'll rerender it later at the lower priority.
117
+ workInProgress.pendingWorkPriority = OffscreenPriority;
118
+ return bailoutOnLowPriority(current, workInProgress);
119
} else {
120
+ var nextChildren = workInProgress.pendingProps.children;
121
reconcileChildren(current, workInProgress, nextChildren);
152
- return workInProgress.childInProgress;
122
+ return workInProgress.child;
123
}
124
}
125
@@ -172,7 +142,7 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
142
}
143
}
144
reconcileChildren(current, workInProgress, value);
175
- return workInProgress.childInProgress;
145
+ return workInProgress.child;
146
}
147
148
function updateCoroutineComponent(current, workInProgress) {
@@ -240,7 +210,6 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
210
workInProgress.firstEffect = null;
211
workInProgress.lastEffect = null;
212
243
- workInProgress.childInProgress = null; // current.childInProgress;
213
workInProgress.child = current.child;
214
215
cloneChildFibers(workInProgress);
@@ -263,9 +232,6 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
232
workInProgress.lastEffect = null;
233
234
const child = workInProgress.child;
266
- if (workInProgress.childInProgress) {
267
- throw new Error('Child in progress means we cannot bail here.');
268
- }
235
if (child) {
236
// Ensure that the effects of reused work are preserved.
237
reuseChildrenEffects(workInProgress, child);
@@ -280,6 +246,15 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
246
return null;
247
}
248
249
+ function bailoutOnLowPriority(current, workInProgress) {
250
+ if (current) {
251
+ workInProgress.child = current.child;
252
+ workInProgress.memoizedProps = current.memoizedProps;
253
+ workInProgress.output = current.output;
254
+ }
255
+ return null;
256
+ }
257
+
258
function beginWork(current : ?Fiber, workInProgress : Fiber, priorityLevel) : ?Fiber {
259
if (!workInProgress.pendingProps) {
260
throw new Error('should have pending props here');
@@ -287,15 +262,7 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
262
263
if (workInProgress.pendingWorkPriority === NoWork ||
264
workInProgress.pendingWorkPriority > priorityLevel) {
290
-
291
- if (current) {
292
- workInProgress.child = current.child;
293
- workInProgress.childInProgress = current.childInProgress;
294
- workInProgress.memoizedProps = current.memoizedProps;
295
- workInProgress.output = current.output;
296
- }
297
-
298
- return null;
265
+ return bailoutOnLowPriority(current, workInProgress);
266
}
267
268
// The current, flushed, state of this fiber is the alternate.
@@ -306,7 +273,7 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
273
return bailoutOnCurrent(current, workInProgress);
274
}
275
309
- if (!workInProgress.childInProgress &&
276
+ if (workInProgress.memoizedProps &&
277
workInProgress.pendingProps === workInProgress.memoizedProps) {
278
return bailoutOnAlreadyFinishedWork(current, workInProgress);
279
}
@@ -322,10 +289,10 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
289
reconcileChildren(current, workInProgress, workInProgress.pendingProps);
290
// A yield component is just a placeholder, we can just run through the
291
// next one immediately.
325
- if (workInProgress.childInProgress) {
292
+ if (workInProgress.child) {
293
return beginWork(
327
- workInProgress.childInProgress.alternate,
328
- workInProgress.childInProgress
294
+ workInProgress.child.alternate,
295
+ workInProgress.child
296
);
297
}
298
return null;
@@ -342,13 +309,13 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
309
updateCoroutineComponent(current, workInProgress);
310
// This doesn't take arbitrary time so we could synchronously just begin
311
// eagerly do the work of workInProgress.child as an optimization.
345
- if (workInProgress.childInProgress) {
312
+ if (workInProgress.child) {
313
return beginWork(
347
- workInProgress.childInProgress.alternate,
348
- workInProgress.childInProgress
314
+ workInProgress.child.alternate,
315
+ workInProgress.child
316
);
317
}
351
- return workInProgress.childInProgress;
318
+ return workInProgress.child;
319
case YieldComponent:
320
// A yield component is just a placeholder, we can just run through the
321
// next one immediately.