Skip to content

Commit 7cace1b

Browse files
committed
Confirm that a shallow bailout does not drop work in the child
Includes a test that confirms that work that is bailed out before completing can be reused without dropping the entire subtree.
1 parent cd9e652 commit 7cace1b

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

scripts/fiber/tests-passing.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,7 @@ src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
11421142
* can resume work in a subtree even when a parent bails out
11431143
* can resume work in a bailed subtree within one pass
11441144
* can reuse work done after being preempted
1145+
* can reuse work that began but did not complete, after being preempted
11451146
* can reuse work if shouldComponentUpdate is false, after being preempted
11461147
* memoizes work even if shouldComponentUpdate returns false
11471148
* can update in the middle of a tree using setState

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,80 @@ describe('ReactIncremental', () => {
541541

542542
});
543543

544+
it('can reuse work that began but did not complete, after being preempted', () => {
545+
let ops = [];
546+
let child;
547+
let sibling;
548+
549+
function GreatGrandchild() {
550+
ops.push('GreatGrandchild');
551+
return <div />;
552+
}
553+
554+
function Grandchild() {
555+
ops.push('Grandchild');
556+
return <GreatGrandchild />;
557+
}
558+
559+
class Child extends React.Component {
560+
state = { step: 0 };
561+
render() {
562+
child = this;
563+
ops.push('Child');
564+
return <Grandchild />;
565+
}
566+
}
567+
568+
class Sibling extends React.Component {
569+
render() {
570+
ops.push('Sibling');
571+
sibling = this;
572+
return <div />;
573+
}
574+
}
575+
576+
function Parent() {
577+
ops.push('Parent');
578+
return [
579+
// The extra div is necessary because when Parent bails out during the
580+
// high priority update, its progressedPriority is set to high.
581+
// So its direct children cannot be reused when we resume at
582+
// low priority. I think this would be fixed by changing
583+
// pendingWorkPriority and progressedPriority to be the priority of
584+
// the children only, not including the fiber itself.
585+
<div><Child /></div>,
586+
<Sibling />,
587+
];
588+
}
589+
590+
ReactNoop.render(<Parent />);
591+
ReactNoop.flush();
592+
ops = [];
593+
594+
// Begin working on a low priority update to Child, but stop before
595+
// GreatGrandchild. Child and Grandchild begin but don't complete.
596+
child.setState({ step: 1 });
597+
ReactNoop.flushDeferredPri(30);
598+
expect(ops).toEqual([
599+
'Child',
600+
'Grandchild',
601+
]);
602+
603+
// Interrupt the current low pri work with a high pri update elsewhere in
604+
// the tree.
605+
ops = [];
606+
ReactNoop.performAnimationWork(() => {
607+
sibling.setState({});
608+
});
609+
ReactNoop.flushAnimationPri();
610+
expect(ops).toEqual(['Sibling']);
611+
612+
// Continue the low pri work.
613+
ops = [];
614+
ReactNoop.flush();
615+
expect(ops).toEqual(['GreatGrandchild']);
616+
});
617+
544618
it('can reuse work if shouldComponentUpdate is false, after being preempted', () => {
545619

546620
var ops = [];

0 commit comments

Comments
 (0)