Skip to content

Commit 05960df

Browse files
committed
Swap .child and .stateNode in coroutines
It is slightly more useful this way because when we want to find host nodes we typically want to do so in the second phase. That's the real tree where as the first phase is more of a virtual part of the tree.
1 parent b75a477 commit 05960df

File tree

6 files changed

+55
-16
lines changed

6 files changed

+55
-16
lines changed

scripts/fiber/tests-passing.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,7 @@ src/renderers/shared/__tests__/ReactPerf-test.js
10311031

10321032
src/renderers/shared/fiber/__tests__/ReactCoroutine-test.js
10331033
* should render a coroutine
1034+
* should unmount a composite in a coroutine
10341035

10351036
src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
10361037
* should render a simple component

src/renderers/shared/fiber/ReactFiberBeginWork.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,41 @@ module.exports = function<T, P, I, TI, C>(
296296
if (!coroutine) {
297297
throw new Error('Should be resolved by now');
298298
}
299-
reconcileChildren(current, workInProgress, coroutine.children);
299+
300+
const nextChildren = coroutine.children;
301+
const priorityLevel = workInProgress.pendingWorkPriority;
302+
// At this point any memoization is no longer valid since we'll have changed
303+
// the children.
304+
workInProgress.memoizedProps = null;
305+
if (!current) {
306+
workInProgress.stateNode = mountChildFibersInPlace(
307+
workInProgress,
308+
workInProgress.stateNode,
309+
nextChildren,
310+
priorityLevel
311+
);
312+
} else if (current.child === workInProgress.child) {
313+
clearDeletions(workInProgress);
314+
315+
workInProgress.stateNode = reconcileChildFibers(
316+
workInProgress,
317+
workInProgress.stateNode,
318+
nextChildren,
319+
priorityLevel
320+
);
321+
322+
transferDeletions(workInProgress);
323+
} else {
324+
workInProgress.stateNode = reconcileChildFibersInPlace(
325+
workInProgress,
326+
workInProgress.stateNode,
327+
nextChildren,
328+
priorityLevel
329+
);
330+
331+
transferDeletions(workInProgress);
332+
}
333+
// markChildAsProgressed(current, workInProgress, priorityLevel);
300334
}
301335

302336
function updatePortalComponent(current, workInProgress) {
@@ -462,9 +496,7 @@ module.exports = function<T, P, I, TI, C>(
462496
// Intentionally fall through since this is now the same.
463497
case CoroutineComponent:
464498
updateCoroutineComponent(current, workInProgress);
465-
// This doesn't take arbitrary time so we could synchronously just begin
466-
// eagerly do the work of workInProgress.child as an optimization.
467-
return workInProgress.child;
499+
return workInProgress.stateNode;
468500
case YieldComponent:
469501
// A yield component is just a placeholder, we can just run through the
470502
// next one immediately.

src/renderers/shared/fiber/ReactFiberCommitWork.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ module.exports = function<T, P, I, TI, C>(
112112
while (node.tag !== HostComponent && node.tag !== HostText) {
113113
// If it is not host node and, we might have a host node inside it.
114114
// Try to search down until we find one.
115-
// TODO: For coroutines, this will have to search the stateNode.
116115
if (node.effectTag & Placement) {
117116
// If we don't have a child, try the siblings instead.
118117
continue siblings;
@@ -151,7 +150,6 @@ module.exports = function<T, P, I, TI, C>(
151150
// down its children. Instead, we'll get insertions from each child in
152151
// the portal directly.
153152
} else if (node.child) {
154-
// TODO: Coroutines need to visit the stateNode.
155153
node = node.child;
156154
continue;
157155
}
@@ -178,7 +176,6 @@ module.exports = function<T, P, I, TI, C>(
178176
while (true) {
179177
commitUnmount(node);
180178
if (node.child) {
181-
// TODO: Coroutines need to visit the stateNode.
182179
node.child.return = node;
183180
node = node.child;
184181
continue;
@@ -218,7 +215,6 @@ module.exports = function<T, P, I, TI, C>(
218215
} else {
219216
commitUnmount(node);
220217
if (node.child) {
221-
// TODO: Coroutines need to visit the stateNode.
222218
node.child.return = node;
223219
node = node.child;
224220
continue;

src/renderers/shared/fiber/ReactFiberCompleteWork.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
5151
const createTextInstance = config.createTextInstance;
5252
const prepareUpdate = config.prepareUpdate;
5353

54+
function markChildAsProgressed(current, workInProgress, priorityLevel) {
55+
// We now have clones. Let's store them as the currently progressed work.
56+
workInProgress.progressedChild = workInProgress.child;
57+
workInProgress.progressedPriority = priorityLevel;
58+
if (current) {
59+
// We also store it on the current. When the alternate swaps in we can
60+
// continue from this point.
61+
current.progressedChild = workInProgress.progressedChild;
62+
current.progressedPriority = workInProgress.progressedPriority;
63+
}
64+
}
65+
5466
function markUpdate(workInProgress : Fiber) {
5567
// Tag the fiber with an update effect. This turns a Placement into
5668
// an UpdateAndPlacement.
@@ -63,15 +75,14 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
6375
}
6476

6577
function appendAllYields(yields : Array<ReifiedYield>, workInProgress : Fiber) {
66-
let node = workInProgress.child;
78+
let node = workInProgress.stateNode;
6779
while (node) {
6880
if (node.tag === HostComponent || node.tag === HostText ||
6981
node.tag === Portal) {
7082
throw new Error('A coroutine cannot have host component children.');
7183
} else if (node.tag === YieldComponent) {
7284
yields.push(node.type);
7385
} else if (node.child) {
74-
// TODO: Coroutines need to visit the stateNode.
7586
node.child.return = node;
7687
node = node.child;
7788
continue;
@@ -113,16 +124,17 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
113124
var props = coroutine.props;
114125
var nextChildren = fn(props, yields);
115126

116-
var currentFirstChild = current ? current.stateNode : null;
127+
var currentFirstChild = current ? current.child : null;
117128
// Inherit the priority of the returnFiber.
118129
const priority = workInProgress.pendingWorkPriority;
119-
workInProgress.stateNode = reconcileChildFibers(
130+
workInProgress.child = reconcileChildFibers(
120131
workInProgress,
121132
currentFirstChild,
122133
nextChildren,
123134
priority
124135
);
125-
return workInProgress.stateNode;
136+
markChildAsProgressed(current, workInProgress, priority);
137+
return workInProgress.child;
126138
}
127139

128140
function appendAllChildren(parent : I, workInProgress : Fiber) {
@@ -137,7 +149,6 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
137149
// down its children. Instead, we'll get insertions from each child in
138150
// the portal directly.
139151
} else if (node.child) {
140-
// TODO: Coroutines need to visit the stateNode.
141152
node = node.child;
142153
continue;
143154
}

src/renderers/shared/fiber/ReactFiberScheduler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
288288

289289
const returnFiber = workInProgress.return;
290290

291-
if (returnFiber) {
291+
if (returnFiber && !next) {
292292
// Append all the effects of the subtree and this fiber onto the effect
293293
// list of the parent. The completion order of the children affects the
294294
// side-effect order.

src/renderers/shared/fiber/ReactFiberTreeReflection.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ exports.findCurrentHostFiber = function(parent : Fiber) : Fiber | null {
112112
if (node.tag === HostComponent || node.tag === HostText) {
113113
return node;
114114
} else if (node.child) {
115-
// TODO: Coroutines need to visit the stateNode.
116115
node = node.child;
117116
continue;
118117
}

0 commit comments

Comments
 (0)