Skip to content

Commit 1972b8f

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 30c7c4f commit 1972b8f

File tree

6 files changed

+56
-17
lines changed

6 files changed

+56
-17
lines changed

src/renderers/shared/fiber/ReactFiberBeginWork.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,11 +518,46 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
518518
} else if (nextCoroutine === null || workInProgress.memoizedProps === nextCoroutine) {
519519
return bailoutOnAlreadyFinishedWork(current, workInProgress);
520520
}
521-
reconcileChildren(current, workInProgress, nextCoroutine.children);
521+
522+
const nextChildren = nextCoroutine.children;
523+
const priorityLevel = workInProgress.pendingWorkPriority;
524+
// At this point any memoization is no longer valid since we'll have changed
525+
// the children.
526+
workInProgress.memoizedProps = null;
527+
if (!current) {
528+
workInProgress.stateNode = mountChildFibersInPlace(
529+
workInProgress,
530+
workInProgress.stateNode,
531+
nextChildren,
532+
priorityLevel
533+
);
534+
} else if (current.child === workInProgress.child) {
535+
clearDeletions(workInProgress);
536+
537+
workInProgress.stateNode = reconcileChildFibers(
538+
workInProgress,
539+
workInProgress.stateNode,
540+
nextChildren,
541+
priorityLevel
542+
);
543+
544+
transferDeletions(workInProgress);
545+
} else {
546+
workInProgress.stateNode = reconcileChildFibersInPlace(
547+
workInProgress,
548+
workInProgress.stateNode,
549+
nextChildren,
550+
priorityLevel
551+
);
552+
553+
transferDeletions(workInProgress);
554+
}
555+
// markChildAsProgressed(current, workInProgress, priorityLevel);
556+
522557
memoizeProps(workInProgress, nextCoroutine);
523558
// This doesn't take arbitrary time so we could synchronously just begin
524559
// eagerly do the work of workInProgress.child as an optimization.
525-
return workInProgress.child;
560+
return workInProgress.stateNode;
526561
}
527562

528563
function updatePortalComponent(current, workInProgress) {

src/renderers/shared/fiber/ReactFiberCommitWork.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
136136
while (node.tag !== HostComponent && node.tag !== HostText) {
137137
// If it is not host node and, we might have a host node inside it.
138138
// Try to search down until we find one.
139-
// TODO: For coroutines, this will have to search the stateNode.
140139
if (node.effectTag & Placement) {
141140
// If we don't have a child, try the siblings instead.
142141
continue siblings;
@@ -198,7 +197,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
198197
// down its children. Instead, we'll get insertions from each child in
199198
// the portal directly.
200199
} else if (node.child) {
201-
// TODO: Coroutines need to visit the stateNode.
202200
node.child.return = node;
203201
node = node.child;
204202
continue;
@@ -229,7 +227,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
229227
// Visit children because they may contain more composite or host nodes.
230228
// Skip portals because commitUnmount() currently visits them recursively.
231229
if (node.child && node.tag !== HostPortal) {
232-
// TODO: Coroutines need to visit the stateNode.
233230
node.child.return = node;
234231
node = node.child;
235232
continue;
@@ -273,7 +270,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
273270
commitUnmount(node);
274271
// Visit children because we may find more host components below.
275272
if (node.child) {
276-
// TODO: Coroutines need to visit the stateNode.
277273
node.child.return = node;
278274
node = node.child;
279275
continue;

src/renderers/shared/fiber/ReactFiberCompleteWork.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,33 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
6666
popHostContainer,
6767
} = hostContext;
6868

69+
function markChildAsProgressed(current, workInProgress, priorityLevel) {
70+
// We now have clones. Let's store them as the currently progressed work.
71+
workInProgress.progressedChild = workInProgress.child;
72+
workInProgress.progressedPriority = priorityLevel;
73+
if (current) {
74+
// We also store it on the current. When the alternate swaps in we can
75+
// continue from this point.
76+
current.progressedChild = workInProgress.progressedChild;
77+
current.progressedPriority = workInProgress.progressedPriority;
78+
}
79+
}
80+
6981
function markUpdate(workInProgress : Fiber) {
7082
// Tag the fiber with an update effect. This turns a Placement into
7183
// an UpdateAndPlacement.
7284
workInProgress.effectTag |= Update;
7385
}
7486

7587
function appendAllYields(yields : Array<ReifiedYield>, workInProgress : Fiber) {
76-
let node = workInProgress.child;
88+
let node = workInProgress.stateNode;
7789
while (node) {
7890
if (node.tag === HostComponent || node.tag === HostText ||
7991
node.tag === HostPortal) {
8092
throw new Error('A coroutine cannot have host component children.');
8193
} else if (node.tag === YieldComponent) {
8294
yields.push(node.type);
8395
} else if (node.child) {
84-
// TODO: Coroutines need to visit the stateNode.
8596
node.child.return = node;
8697
node = node.child;
8798
continue;
@@ -123,16 +134,17 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
123134
var props = coroutine.props;
124135
var nextChildren = fn(props, yields);
125136

126-
var currentFirstChild = current ? current.stateNode : null;
137+
var currentFirstChild = current ? current.child : null;
127138
// Inherit the priority of the returnFiber.
128139
const priority = workInProgress.pendingWorkPriority;
129-
workInProgress.stateNode = reconcileChildFibers(
140+
workInProgress.child = reconcileChildFibers(
130141
workInProgress,
131142
currentFirstChild,
132143
nextChildren,
133144
priority
134145
);
135-
return workInProgress.stateNode;
146+
markChildAsProgressed(current, workInProgress, priority);
147+
return workInProgress.child;
136148
}
137149

138150
function appendAllChildren(parent : I, workInProgress : Fiber) {
@@ -147,7 +159,6 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
147159
// down its children. Instead, we'll get insertions from each child in
148160
// the portal directly.
149161
} else if (node.child) {
150-
// TODO: Coroutines need to visit the stateNode.
151162
node = node.child;
152163
continue;
153164
}

src/renderers/shared/fiber/ReactFiberScheduler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P,
473473
return next;
474474
}
475475

476-
if (returnFiber) {
476+
if (returnFiber && !next) {
477477
// Append all the effects of the subtree and this fiber onto the effect
478478
// list of the parent. The completion order of the children affects the
479479
// side-effect order.

src/renderers/shared/fiber/ReactFiberTreeReflection.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ exports.findCurrentHostFiber = function(parent : Fiber) : Fiber | null {
168168
return node;
169169
} else if (node.child) {
170170
// TODO: If we hit a Portal, we're supposed to skip it.
171-
// TODO: Coroutines need to visit the stateNode.
172171
node.child.return = node;
173172
node = node.child;
174173
continue;

src/renderers/shared/fiber/__tests__/ReactCoroutine-test.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,8 @@ describe('ReactCoroutine', () => {
143143

144144
expect(ops).toEqual([
145145
'Unmount Parent',
146-
// TODO: This should happen in the order Child, Continuation which it
147-
// will once we swap stateNode and child positions of these.
148-
'Unmount Continuation',
149146
'Unmount Child',
147+
'Unmount Continuation',
150148
]);
151149

152150
});

0 commit comments

Comments
 (0)