Skip to content

Commit 4910b16

Browse files
committed
Unmount child from the first phase of a coroutine
1 parent 0b997a6 commit 4910b16

File tree

4 files changed

+79
-7
lines changed

4 files changed

+79
-7
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/ReactFiberCommitWork.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var {
2121
HostContainer,
2222
HostComponent,
2323
HostText,
24+
CoroutineComponent,
2425
Portal,
2526
} = ReactTypeOfWork;
2627
var { callCallbacks } = require('ReactFiberUpdateQueue');
@@ -278,6 +279,10 @@ module.exports = function<T, P, I, TI, C>(
278279
detachRef(current);
279280
return;
280281
}
282+
case CoroutineComponent: {
283+
commitNestedUnmounts(current.stateNode);
284+
return;
285+
}
281286
}
282287
}
283288

src/renderers/shared/fiber/ReactFiberScheduler.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
286286
workInProgress.pendingProps = null;
287287
workInProgress.updateQueue = null;
288288

289+
if (next) {
290+
// If completing this work spawned new work, do that next. We'll come
291+
// back here again.
292+
return next;
293+
}
294+
289295
const returnFiber = workInProgress.return;
290296

291297
if (returnFiber) {
@@ -318,10 +324,7 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
318324
}
319325
}
320326

321-
if (next) {
322-
// If completing this work spawned new work, do that next.
323-
return next;
324-
} else if (workInProgress.sibling) {
327+
if (workInProgress.sibling) {
325328
// If there is more work to do in this returnFiber, do that next.
326329
return workInProgress.sibling;
327330
} else if (returnFiber) {

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

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ describe('ReactCoroutine', () => {
2424
});
2525

2626
it('should render a coroutine', () => {
27-
2827
var ops = [];
2928

30-
3129
function Continuation({ isSame }) {
3230
ops.push(['Continuation', isSame]);
3331
return <span>{isSame ? 'foo==bar' : 'foo!=bar'}</span>;
@@ -84,7 +82,72 @@ describe('ReactCoroutine', () => {
8482
['Continuation', true],
8583
['Continuation', false],
8684
]);
87-
8885
});
8986

87+
it('should unmount a composite in a coroutine', () => {
88+
var ops = [];
89+
90+
class Continuation extends React.Component {
91+
render() {
92+
ops.push('Continuation');
93+
return <div />;
94+
}
95+
componentWillUnmount() {
96+
ops.push('Unmount Continuation');
97+
}
98+
}
99+
100+
class Child extends React.Component {
101+
render() {
102+
ops.push('Child');
103+
return ReactCoroutine.createYield({}, Continuation, null);
104+
}
105+
componentWillUnmount() {
106+
ops.push('Unmount Child');
107+
}
108+
}
109+
110+
function HandleYields(props, yields) {
111+
ops.push('HandleYields');
112+
return yields.map(y => <y.continuation />);
113+
}
114+
115+
class Parent extends React.Component {
116+
render() {
117+
ops.push('Parent');
118+
return ReactCoroutine.createCoroutine(
119+
this.props.children,
120+
HandleYields,
121+
this.props
122+
);
123+
}
124+
componentWillUnmount() {
125+
ops.push('Unmount Parent');
126+
}
127+
}
128+
129+
ReactNoop.render(<Parent><Child /></Parent>);
130+
ReactNoop.flush();
131+
132+
expect(ops).toEqual([
133+
'Parent',
134+
'Child',
135+
'HandleYields',
136+
'Continuation',
137+
]);
138+
139+
ops = [];
140+
141+
ReactNoop.render(<div />);
142+
ReactNoop.flush();
143+
144+
expect(ops).toEqual([
145+
'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',
149+
'Unmount Child',
150+
]);
151+
152+
});
90153
});

0 commit comments

Comments
 (0)