Drop Separate findPendingWork Phase
The findPendingWork phase is the same as just walking the tree the normal way effectively. It only makes things more complex to think about. We might possibly be able to write a few special branches to optimize it but for now it doesn't seem necessary.
Sebastian Markbage committed
Sep 1, 2016 at 20:49 UTC
b63cda6e852b55d0f4b7d0419da2068c8540bf34
7 files changed
+167
-229
src/renderers/shared/fiber/ReactChildFiber.js
+54
@@ -221,3 +221,57 @@ function ChildReconciler(shouldClone) {
221
exports.reconcileChildFibers = ChildReconciler(true);
222
223
exports.reconcileChildFibersInPlace = ChildReconciler(false);
224
+
225
+
226
+function cloneSiblings(current : Fiber, workInProgress : Fiber, returnFiber : Fiber) {
227
+ workInProgress.return = returnFiber;
228
+ while (current.sibling) {
229
+ current = current.sibling;
230
+ workInProgress = workInProgress.sibling = cloneFiber(
231
+ current,
232
+ current.pendingWorkPriority
233
+ );
234
+ workInProgress.return = returnFiber;
235
+ }
236
+ workInProgress.sibling = null;
237
+}
238
+
239
+exports.cloneChildFibers = function(workInProgress : Fiber) {
240
+ if (!workInProgress.child) {
241
+ return;
242
+ }
243
+ const current = workInProgress.alternate;
244
+ if (!current || workInProgress.child !== current.child) {
245
+ // If there is no alternate, then we don't need to clone the children.
246
+ // If the children of the alternate fiber is a different set, then we don't
247
+ // need to clone. We need to reset the return fiber though since we'll
248
+ // traverse down into them.
249
+ // TODO: I don't think it is actually possible for them to be anything but
250
+ // equal at this point because this fiber was just cloned. Can we skip this
251
+ // check? Similar question about the return fiber.
252
+ let child = workInProgress.child;
253
+ while (child) {
254
+ child.return = workInProgress;
255
+ child = child.sibling;
256
+ }
257
+ return;
258
+ }
259
+ // TODO: This used to reset the pending priority. Not sure if that is needed.
260
+ // workInProgress.pendingWorkPriority = current.pendingWorkPriority;
261
+
262
+ // TODO: The below priority used to be set to NoWork which would've
263
+ // dropped work. This is currently unobservable but will become
264
+ // observable when the first sibling has lower priority work remaining
265
+ // than the next sibling. At that point we should add tests that catches
266
+ // this.
267
+
268
+ const currentChild = current.child;
269
+ if (!currentChild) {
270
+ return;
271
+ }
272
+ workInProgress.child = cloneFiber(
273
+ currentChild,
274
+ currentChild.pendingWorkPriority
275
+ );
276
+ cloneSiblings(currentChild, workInProgress.child, workInProgress);
277
+}
src/renderers/shared/fiber/ReactFiber.js
+2
-2
@@ -164,7 +164,7 @@ exports.cloneFiber = function(fiber : Fiber, priorityLevel : PriorityLevel) : Fi
164
alt.child = fiber.child;
165
alt.childInProgress = fiber.childInProgress;
166
alt.sibling = fiber.sibling;
167
- alt.ref = alt.ref;
167
+ alt.ref = fiber.ref;
168
alt.pendingProps = fiber.pendingProps;
169
alt.pendingWorkPriority = priorityLevel;
170
@@ -187,7 +187,7 @@ exports.cloneFiber = function(fiber : Fiber, priorityLevel : PriorityLevel) : Fi
187
alt.child = fiber.child;
188
alt.childInProgress = fiber.childInProgress;
189
alt.sibling = fiber.sibling;
190
- alt.ref = alt.ref;
190
+ alt.ref = fiber.ref;
191
// pendingProps is here for symmetry but is unnecessary in practice for now.
192
alt.pendingProps = fiber.pendingProps;
193
alt.pendingWorkPriority = priorityLevel;
src/renderers/shared/fiber/ReactFiberBeginWork.js
+74
-36
@@ -19,6 +19,7 @@ import type { HostConfig } from 'ReactFiberReconciler';
19
var {
20
reconcileChildFibers,
21
reconcileChildFibersInPlace,
22
+ cloneChildFibers,
23
} = require('ReactChildFiber');
24
var ReactTypeOfWork = require('ReactTypeOfWork');
25
var {
@@ -35,7 +36,6 @@ var {
36
NoWork,
37
OffscreenPriority,
38
} = require('ReactPriorityLevel');
38
-var { findNextUnitOfWorkAtPriority } = require('ReactFiberPendingWork');
39
40
module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
41
@@ -64,9 +64,10 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
64
priorityLevel
65
);
66
} else {
67
+ // TODO:
68
workInProgress.childInProgress = reconcileChildFibers(
69
workInProgress,
69
- current ? current.child : null,
70
+ current ? current.child : workInProgress.child,
71
nextChildren,
72
priorityLevel
73
);
@@ -76,8 +77,10 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
77
function updateFunctionalComponent(current, workInProgress) {
78
var fn = workInProgress.type;
79
var props = workInProgress.pendingProps;
80
+
81
var nextChildren = fn(props);
82
reconcileChildren(current, workInProgress, nextChildren);
83
+ return workInProgress.childInProgress;
84
}
85
86
function updateClassComponent(current : ?Fiber, workInProgress : Fiber) {
@@ -104,9 +107,11 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
107
}
108
}
109
}
110
+
111
instance.props = props;
112
var nextChildren = instance.render();
113
reconcileChildren(current, workInProgress, nextChildren);
114
+
115
return workInProgress.childInProgress;
116
}
117
@@ -125,6 +130,22 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
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;
150
} else {
151
reconcileChildren(current, workInProgress, nextChildren);
@@ -151,6 +172,7 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
172
}
173
}
174
reconcileChildren(current, workInProgress, value);
175
+ return workInProgress.childInProgress;
176
}
177
178
function updateCoroutineComponent(current, workInProgress) {
@@ -175,10 +197,13 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
197
// Update the returnFiber of the child to the newest fiber.
198
child.return = returnFiber;
199
// Retain the priority if there's any work left to do in the children.
178
- if (child.pendingWorkPriority !== NoWork &&
200
+ /*if (child.pendingWorkPriority !== NoWork &&
201
(returnFiber.pendingWorkPriority === NoWork ||
202
returnFiber.pendingWorkPriority > child.pendingWorkPriority)) {
203
returnFiber.pendingWorkPriority = child.pendingWorkPriority;
204
+ }*/
205
+ if (!child.pendingProps && !child.memoizedProps) {
206
+ throw new Error('Should have memoized props by now');
207
}
208
} while (child = child.sibling);
209
}
@@ -200,6 +225,7 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
225
} while (child = child.sibling);
226
}
227
228
+/*
229
function bailoutOnCurrent(current : Fiber, workInProgress : Fiber) : ?Fiber {
230
// The most likely scenario is that the previous copy of the tree contains
231
// the same props as the new one. In that case, we can just copy the output
@@ -207,41 +233,39 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
233
workInProgress.memoizedProps = workInProgress.pendingProps;
234
workInProgress.output = current.output;
235
const priorityLevel = workInProgress.pendingWorkPriority;
210
- workInProgress.pendingProps = null;
236
+ // workInProgress.pendingProps = null;
237
workInProgress.stateNode = current.stateNode;
212
- workInProgress.childInProgress = current.childInProgress;
213
- if (current.child) {
214
- // If we bail out but still has work with the current priority in this
215
- // subtree, we need to go find it right now. If we don't, we won't flush
216
- // it until the next tick.
217
- workInProgress.child = current.child;
218
- reuseChildren(workInProgress, workInProgress.child);
219
- if (workInProgress.pendingWorkPriority !== NoWork && workInProgress.pendingWorkPriority <= priorityLevel) {
220
- return findNextUnitOfWorkAtPriority(
221
- workInProgress,
222
- workInProgress.pendingWorkPriority
223
- );
224
- } else {
225
- return null;
226
- }
227
- } else {
228
- workInProgress.child = null;
229
- return null;
230
- }
238
+
239
+ workInProgress.nextEffect = null;
240
+ workInProgress.firstEffect = null;
241
+ workInProgress.lastEffect = null;
242
+
243
+ workInProgress.childInProgress = null; // current.childInProgress;
244
+ workInProgress.child = current.child;
245
+
246
+ cloneChildFibers(workInProgress);
247
+
248
+ // TODO: Maybe bailout with null if the children priority flag indicate
249
+ // that there is no nested work.
250
+ return workInProgress.child;
251
}
252
+*/
253
254
function bailoutOnAlreadyFinishedWork(current, workInProgress : Fiber) : ?Fiber {
255
// If we started this work before, and finished it, or if we're in a
256
// ping-pong update scenario, this version could already be what we're
257
// looking for. In that case, we should be able to just bail out.
258
const priorityLevel = workInProgress.pendingWorkPriority;
238
- workInProgress.pendingProps = null;
259
+ // workInProgress.pendingProps = null;
260
261
workInProgress.firstEffect = null;
262
workInProgress.nextEffect = null;
263
workInProgress.lastEffect = null;
264
265
const child = workInProgress.child;
266
+ if (workInProgress.childInProgress) {
267
+ throw new Error('Child in progress means we cannot bail here.');
268
+ }
269
if (child) {
270
// Ensure that the effects of reused work are preserved.
271
reuseChildrenEffects(workInProgress, child);
@@ -249,18 +273,31 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
273
// subtree, we need to go find it right now. If we don't, we won't flush
274
// it until the next tick.
275
reuseChildren(workInProgress, child);
252
- if (workInProgress.pendingWorkPriority !== NoWork &&
253
- workInProgress.pendingWorkPriority <= priorityLevel) {
254
- // TODO: This passes the current node and reads the priority level and
255
- // pending props from that. We want it to read our priority level and
256
- // pending props from the work in progress. Needs restructuring.
257
- return findNextUnitOfWorkAtPriority(workInProgress, priorityLevel);
258
- }
276
+ // TODO: Maybe bailout with null if the children priority flag indicate
277
+ // that there is no nested work.
278
+ return workInProgress.child;
279
}
280
return null;
281
}
282
263
- function beginWork(current : ?Fiber, workInProgress : Fiber) : ?Fiber {
283
+ function beginWork(current : ?Fiber, workInProgress : Fiber, priorityLevel) : ?Fiber {
284
+ if (!workInProgress.pendingProps) {
285
+ throw new Error('should have pending props here');
286
+ }
287
+
288
+ if (workInProgress.pendingWorkPriority === NoWork ||
289
+ 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;
299
+ }
300
+
301
// The current, flushed, state of this fiber is the alternate.
302
// Ideally nothing should rely on this, but relying on it here
303
// means that we don't need an additional field on the work in
@@ -276,11 +313,9 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
313
314
switch (workInProgress.tag) {
315
case IndeterminateComponent:
279
- mountIndeterminateComponent(current, workInProgress);
280
- return workInProgress.childInProgress;
316
+ return mountIndeterminateComponent(current, workInProgress);
317
case FunctionalComponent:
282
- updateFunctionalComponent(current, workInProgress);
283
- return workInProgress.childInProgress;
318
+ return updateFunctionalComponent(current, workInProgress);
319
case ClassComponent:
320
return updateClassComponent(current, workInProgress);
321
case HostContainer:
@@ -295,6 +330,9 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
330
}
331
return null;
332
case HostComponent:
333
+ if (workInProgress.stateNode && config.beginUpdate) {
334
+ config.beginUpdate(workInProgress.stateNode);
335
+ }
336
return updateHostComponent(current, workInProgress);
337
case CoroutineHandlerPhase:
338
// This is a restart. Reset the tag to the initial phase.
src/renderers/shared/fiber/ReactFiberPendingWork.js
deleted
-142
@@ -1,142 +0,0 @@
1
-/**
2
- * Copyright 2013-present, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- *
9
- * @providesModule ReactFiberPendingWork
10
- * @flow
11
- */
12
-
13
-'use strict';
14
-
15
-import type { Fiber } from 'ReactFiber';
16
-import type { PriorityLevel } from 'ReactPriorityLevel';
17
-
18
-var { cloneFiber } = require('ReactFiber');
19
-
20
-var {
21
- NoWork,
22
-} = require('ReactPriorityLevel');
23
-
24
-function cloneSiblings(current : Fiber, workInProgress : Fiber, returnFiber : Fiber) {
25
- workInProgress.return = returnFiber;
26
- while (current.sibling) {
27
- current = current.sibling;
28
- workInProgress = workInProgress.sibling = cloneFiber(
29
- current,
30
- current.pendingWorkPriority
31
- );
32
- workInProgress.return = returnFiber;
33
- }
34
- workInProgress.sibling = null;
35
-}
36
-
37
-function cloneChildrenIfNeeded(workInProgress : Fiber) {
38
- const current = workInProgress.alternate;
39
- if (!current || workInProgress.child !== current.child) {
40
- // If there is no alternate, then we don't need to clone the children.
41
- // If the children of the alternate fiber is a different set, then we don't
42
- // need to clone. We need to reset the return fiber though since we'll
43
- // traverse down into them.
44
- // TODO: I don't think it is actually possible for them to be anything but
45
- // equal at this point because this fiber was just cloned. Can we skip this
46
- // check? Similar question about the return fiber.
47
- let child = workInProgress.child;
48
- while (child) {
49
- child.return = workInProgress;
50
- child = child.sibling;
51
- }
52
- return;
53
- }
54
- // TODO: This used to reset the pending priority. Not sure if that is needed.
55
- // workInProgress.pendingWorkPriority = current.pendingWorkPriority;
56
-
57
- // TODO: The below priority used to be set to NoWork which would've
58
- // dropped work. This is currently unobservable but will become
59
- // observable when the first sibling has lower priority work remaining
60
- // than the next sibling. At that point we should add tests that catches
61
- // this.
62
-
63
- const currentChild = current.child;
64
- if (!currentChild) {
65
- return;
66
- }
67
- workInProgress.child = cloneFiber(
68
- currentChild,
69
- currentChild.pendingWorkPriority
70
- );
71
- cloneSiblings(currentChild, workInProgress.child, workInProgress);
72
-}
73
-
74
-exports.findNextUnitOfWorkAtPriority = function(workRoot : Fiber, priorityLevel : PriorityLevel) : ?Fiber {
75
- let workInProgress = workRoot;
76
- while (workInProgress) {
77
- if (workInProgress.pendingWorkPriority !== NoWork &&
78
- workInProgress.pendingWorkPriority <= priorityLevel) {
79
- // This node has work to do that fits our priority level criteria.
80
- if (workInProgress.pendingProps !== null) {
81
- return workInProgress;
82
- }
83
-
84
- // If we have a child let's see if any of our children has work to do.
85
- // Only bother doing this at all if the current priority level matches
86
- // because it is the highest priority for the whole subtree.
87
- // TODO: Coroutines can have work in their stateNode which is another
88
- // type of child that needs to be searched for work.
89
- if (workInProgress.childInProgress) {
90
- let child = workInProgress.childInProgress;
91
- while (child) {
92
- child.return = workInProgress;
93
- child = child.sibling;
94
- }
95
- child = workInProgress.childInProgress;
96
- while (child) {
97
- // Don't bother drilling further down this tree if there is no child
98
- // with more content.
99
- // TODO: Shouldn't this still drill down even though the first
100
- // shallow level doesn't have anything pending on it.
101
- if (child.pendingWorkPriority !== NoWork &&
102
- child.pendingWorkPriority <= priorityLevel &&
103
- child.pendingProps !== null) {
104
- return child;
105
- }
106
- child = child.sibling;
107
- }
108
- } else if (workInProgress.child) {
109
- cloneChildrenIfNeeded(workInProgress);
110
- workInProgress = workInProgress.child;
111
- continue;
112
- }
113
- // If we match the priority but has no child and no work to do,
114
- // then we can safely reset the flag.
115
- workInProgress.pendingWorkPriority = NoWork;
116
- }
117
- if (workInProgress === workRoot) {
118
- if (workInProgress.pendingWorkPriority <= priorityLevel) {
119
- // If this subtree had work left to do, we would have returned it by
120
- // now. This could happen if a child with pending work gets cleaned up
121
- // but we don't clear the flag then. It is safe to reset it now.
122
- workInProgress.pendingWorkPriority = NoWork;
123
- }
124
- return null;
125
- }
126
- while (!workInProgress.sibling) {
127
- workInProgress = workInProgress.return;
128
- if (!workInProgress || workInProgress === workRoot) {
129
- return null;
130
- }
131
- if (workInProgress.pendingWorkPriority <= priorityLevel) {
132
- // If this subtree had work left to do, we would have returned it by
133
- // now. This could happen if a child with pending work gets cleaned up
134
- // but we don't clear the flag then. It is safe to reset it now.
135
- workInProgress.pendingWorkPriority = NoWork;
136
- }
137
- }
138
- workInProgress.sibling.return = workInProgress.return;
139
- workInProgress = workInProgress.sibling;
140
- }
141
- return null;
142
-};
src/renderers/shared/fiber/ReactFiberScheduler.js
+32
-45
@@ -22,7 +22,6 @@ var ReactFiberCompleteWork = require('ReactFiberCompleteWork');
22
var ReactFiberCommitWork = require('ReactFiberCommitWork');
23
24
var { cloneFiber } = require('ReactFiber');
25
-var { findNextUnitOfWorkAtPriority } = require('ReactFiberPendingWork');
25
26
var {
27
NoWork,
@@ -65,36 +64,23 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
64
// TODO: This is scanning one root at a time. It should be scanning all
65
// roots for high priority work before moving on to lower priorities.
66
let root = nextScheduledRoot;
67
+ let highestPriorityRoot = null;
68
+ let highestPriorityLevel = NoWork;
69
while (root) {
69
- let rootInProgress = cloneFiber(
70
- root.current,
71
- root.current.pendingWorkPriority
72
- );
73
- // Find the highest possible priority work to do.
74
- // This loop is unrolled just to satisfy Flow's enum constraint.
75
- // We could make arbitrary many idle priority levels but having
76
- // too many just means flushing changes too often.
77
- let work = findNextUnitOfWorkAtPriority(rootInProgress, HighPriority);
78
- if (work) {
79
- nextPriorityLevel = HighPriority;
80
- return work;
81
- }
82
- work = findNextUnitOfWorkAtPriority(rootInProgress, LowPriority);
83
- if (work) {
84
- nextPriorityLevel = LowPriority;
85
- return work;
86
- }
87
- work = findNextUnitOfWorkAtPriority(rootInProgress, OffscreenPriority);
88
- if (work) {
89
- nextPriorityLevel = OffscreenPriority;
90
- return work;
70
+ if (highestPriorityLevel === NoWork ||
71
+ highestPriorityLevel > root.current.pendingWorkPriority) {
72
+ highestPriorityLevel = root.current.pendingWorkPriority;
73
+ highestPriorityRoot = root;
74
}
75
// We didn't find anything to do in this root, so let's try the next one.
76
root = root.nextScheduledRoot;
77
}
95
- root = nextScheduledRoot;
96
- while (root) {
97
- root = root.nextScheduledRoot;
78
+ if (highestPriorityRoot) {
79
+ nextPriorityLevel = highestPriorityLevel;
80
+ return cloneFiber(
81
+ highestPriorityRoot.current,
82
+ highestPriorityLevel
83
+ );
84
}
85
86
nextPriorityLevel = NoWork;
@@ -119,7 +105,7 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
105
106
function resetWorkPriority(workInProgress : Fiber) {
107
let newPriority = NoWork;
122
- let child = workInProgress.childInProgress || workInProgress.child;
108
+ let child = workInProgress.child;
109
while (child) {
110
// Ensure that remaining work priority bubbles up.
111
if (child.pendingWorkPriority !== NoWork &&
@@ -139,13 +125,25 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
125
// means that we don't need an additional field on the work in
126
// progress.
127
const current = workInProgress.alternate;
142
- const next = completeWork(current, workInProgress);
128
+ let next = null;
129
144
- resetWorkPriority(workInProgress);
130
+ // If this bailed at a lower priority.
131
+ // TODO: This branch is currently needed if a particular type of component
132
+ // ends up being a priority lowering. We should probably know that already
133
+ // before entering begin work.
134
+ if (workInProgress.pendingWorkPriority === NoWork ||
135
+ workInProgress.pendingWorkPriority > nextPriorityLevel) {
136
+ // This fiber was ignored. We need to fall through to the next fiber
137
+ // and leave the pending props and work untouched on this fiber.
138
+ } else {
139
+ next = completeWork(current, workInProgress);
140
146
- // The work is now done. We don't need this anymore. This flags
147
- // to the system not to redo any work here.
148
- workInProgress.pendingProps = null;
141
+ resetWorkPriority(workInProgress);
142
+
143
+ // The work is now done. We don't need this anymore. This flags
144
+ // to the system not to redo any work here.
145
+ workInProgress.pendingProps = null;
146
+ }
147
148
const returnFiber = workInProgress.return;
149
@@ -173,14 +171,6 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
171
} else if (returnFiber) {
172
// If there's no more work in this returnFiber. Complete the returnFiber.
173
workInProgress = returnFiber;
176
- // If we're stepping up through the child, that means we can now commit
177
- // this work. We should only do this when we're stepping upwards because
178
- // completing a downprioritized item is not the same as completing its
179
- // children.
180
- if (workInProgress.childInProgress) {
181
- workInProgress.child = workInProgress.childInProgress;
182
- workInProgress.childInProgress = null;
183
- }
174
continue;
175
} else {
176
// If we're at the root, there's no more work to do. We can flush it.
@@ -205,16 +195,13 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
195
}
196
197
function performUnitOfWork(workInProgress : Fiber) : ?Fiber {
208
- // Ignore work if there is nothing to do.
209
- if (workInProgress.pendingProps === null) {
210
- return completeUnitOfWork(workInProgress);
211
- }
198
// The current, flushed, state of this fiber is the alternate.
199
// Ideally nothing should rely on this, but relying on it here
200
// means that we don't need an additional field on the work in
201
// progress.
202
const current = workInProgress.alternate;
217
- const next = beginWork(current, workInProgress);
203
+ const next = beginWork(current, workInProgress, nextPriorityLevel);
204
+
205
if (next) {
206
// If this spawns new work, do that next.
207
return next;
src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
+3
-3
@@ -410,7 +410,7 @@ describe('ReactIncremental', () => {
410
411
// Init
412
ReactNoop.render(<Foo text="foo" text2="foo" step={0} />);
413
- ReactNoop.flushLowPri(55);
413
+ ReactNoop.flushLowPri(55 + 25);
414
415
// We only finish the higher priority work. So the low pri content
416
// has not yet finished mounting.
@@ -432,7 +432,7 @@ describe('ReactIncremental', () => {
432
// Make a quick update which will schedule low priority work to
433
// update the middle content.
434
ReactNoop.render(<Foo text="bar" text2="bar" step={1} />);
435
- ReactNoop.flushLowPri(30);
435
+ ReactNoop.flushLowPri(30 + 25);
436
437
expect(ops).toEqual(['Foo', 'Bar']);
438
@@ -526,7 +526,7 @@ describe('ReactIncremental', () => {
526
ops = [];
527
528
// The middle content is now pending rendering...
529
- ReactNoop.flushLowPri(30);
529
+ ReactNoop.flushLowPri(30 + 25);
530
expect(ops).toEqual(['Content', 'Middle', 'Bar']); // One more Middle left.
531
532
ops = [];
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
+2
-1
@@ -177,7 +177,7 @@ describe('ReactIncrementalSideEffects', () => {
177
// render some higher priority work. The middle content will bailout so
178
// it remains untouched which means that it should reuse it next time.
179
ReactNoop.render(<Foo text="foo" step={1} />);
180
- ReactNoop.flush(30);
180
+ ReactNoop.flush();
181
182
// Since we did nothing to the middle subtree during the interuption,
183
// we should be able to reuse the reconciliation work that we already did
@@ -270,6 +270,7 @@ describe('ReactIncrementalSideEffects', () => {
270
]);
271
});
272
273
+
274
// TODO: Test that side-effects are not cut off when a work in progress node
275
// moves to "current" without flushing due to having lower priority. Does this
276
// even happen? Maybe a child doesn't get processed because it is lower prio?