@samitouri / QOS-React / commits / de08c2af15

Ignore incremental tests that assert on work reuse

it -> xit The diff looks messier than it actually is because of Prettier.

Andrew Clark committed Jun 19, 2017 at 16:26 UTC de08c2af1563ff271d8bbc86841960c370898563
5 files changed +451 -445
scripts/fiber/tests-passing.txt
+4 -22
@@ -2030,15 +2030,6 @@ src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
2030 * updates a previous render
2031 * can cancel partially rendered work and restart
2032 * should call callbacks even if updates are aborted
2033 -* can deprioritize unfinished work and resume it later
2034 -* can deprioritize a tree from without dropping work
2035 -* can resume work in a subtree even when a parent bails out
2036 -* can resume work in a bailed subtree within one pass
2037 -* can resume mounting a class component
2038 -* reuses the same instance when resuming a class instance
2039 -* can reuse work done after being preempted
2040 -* can reuse work that began but did not complete, after being preempted
2041 -* can reuse work if shouldComponentUpdate is false, after being preempted
2033 * memoizes work even if shouldComponentUpdate returns false
2034 * can update in the middle of a tree using setState
2035 * can queue multiple state updates
@@ -2046,25 +2037,16 @@ src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
2037 * can call setState inside update callback
2038 * can replaceState
2039 * can forceUpdate
2049 -* can call sCU while resuming a partly mounted component
2050 -* gets new props when setting state on a partly updated component
2051 -* calls componentWillMount twice if the initial render is aborted
2052 -* uses state set in componentWillMount even if initial render was aborted
2053 -* calls componentWill* twice if an update render is aborted
2054 -* does not call componentWillReceiveProps for state-only updates
2055 -* skips will/DidUpdate when bailing unless an update was already in progress
2040 * performs batched updates at the end of the batch
2041 * can nest batchedUpdates
2042 * can handle if setState callback throws
2043 * merges and masks context
2044 * does not leak own context into context provider
2061 -* provides context when reusing work
2045 * reads context when setState is below the provider
2046 * reads context when setState is above the provider
2047 * maintains the correct context when providers bail out due to low priority
2048 * maintains the correct context when unwinding due to an error in render
2049 * should not recreate masked context unless inputs have changed
2067 -* should reuse memoized work if pointers are updated before calling lifecycles
2050
2051 src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js
2052 * catches render error in a boundary during full deferred mounting
@@ -2103,7 +2085,6 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalPerf-test.js
2085 * warns on cascading renders from top-level render
2086 * does not treat setState from cWM or cWRP as cascading
2087 * captures all lifecycles
2106 -* measures deprioritized work
2088 * measures deferred work in chunks
2089 * recovers from fatal errors
2090 * recovers from caught errors
@@ -2143,9 +2124,6 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
2124 * can reuse side-effects after being preempted, if shouldComponentUpdate is false
2125 * can update a completed tree before it has a chance to commit
2126 * updates a child even though the old props is empty
2146 -* can defer side-effects and resume them later on
2147 -* can defer side-effects and reuse them later - complex
2148 -* deprioritizes setStates that happens within a deprioritized tree
2127 * calls callback after update is flushed
2128 * calls setState callback even if component bails out
2129 * calls componentWillUnmount after a deletion, even if nested
@@ -2153,6 +2131,10 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
2131 * invokes ref callbacks after insertion/update/unmount
2132 * supports string refs
2133
2134 +src/renderers/shared/fiber/__tests__/ReactIncrementalTriangle-test.js
2135 +* renders the triangle demo without inconsistencies
2136 +* fuzz tester
2137 +
2138 src/renderers/shared/fiber/__tests__/ReactIncrementalUpdates-test.js
2139 * applies updates in order of priority
2140 * applies updates with equal priority in insertion order
src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
+357 -336
@@ -234,11 +234,17 @@ describe('ReactIncremental', () => {
234 // Flush the rest of the work which now includes the low priority
235 ReactNoop.flush();
236
237 - expect(ops).toEqual(['setState1', 'setState2', 'callback1', 'callback2']);
237 + expect(ops).toEqual([
238 + 'setState1',
239 + 'setState1',
240 + 'setState2',
241 + 'callback1',
242 + 'callback2',
243 + ]);
244 expect(inst.state).toEqual({text: 'bar', text2: 'baz'});
245 });
246
241 - it('can deprioritize unfinished work and resume it later', () => {
247 + xit('can deprioritize unfinished work and resume it later', () => {
248 var ops = [];
249
250 function Bar(props) {
@@ -290,7 +296,7 @@ describe('ReactIncremental', () => {
296 expect(ops).toEqual(['Middle', 'Middle']);
297 });
298
293 - it('can deprioritize a tree from without dropping work', () => {
299 + xit('can deprioritize a tree from without dropping work', () => {
300 var ops = [];
301
302 function Bar(props) {
@@ -342,7 +348,7 @@ describe('ReactIncremental', () => {
348 expect(ops).toEqual(['Middle', 'Middle']);
349 });
350
345 - it('can resume work in a subtree even when a parent bails out', () => {
351 + xit('can resume work in a subtree even when a parent bails out', () => {
352 var ops = [];
353
354 function Bar(props) {
@@ -405,7 +411,7 @@ describe('ReactIncremental', () => {
411 expect(ops).toEqual(['Middle']);
412 });
413
408 - it('can resume work in a bailed subtree within one pass', () => {
414 + xit('can resume work in a bailed subtree within one pass', () => {
415 var ops = [];
416
417 function Bar(props) {
@@ -503,7 +509,7 @@ describe('ReactIncremental', () => {
509 expect(ops).toEqual(['Foo', 'Bar', 'Bar']);
510 });
511
506 - it('can resume mounting a class component', () => {
512 + xit('can resume mounting a class component', () => {
513 let ops = [];
514 let foo;
515 class Parent extends React.Component {
@@ -544,7 +550,7 @@ describe('ReactIncremental', () => {
550 expect(ops).toEqual(['Foo', 'Bar']);
551 });
552
547 - it('reuses the same instance when resuming a class instance', () => {
553 + xit('reuses the same instance when resuming a class instance', () => {
554 let ops = [];
555 let foo;
556 class Parent extends React.Component {
@@ -613,7 +619,7 @@ describe('ReactIncremental', () => {
619 ]);
620 });
621
616 - it('can reuse work done after being preempted', () => {
622 + xit('can reuse work done after being preempted', () => {
623 var ops = [];
624
625 function Bar(props) {
@@ -706,165 +712,171 @@ describe('ReactIncremental', () => {
712 expect(ops).toEqual(['Middle']);
713 });
714
709 - it('can reuse work that began but did not complete, after being preempted', () => {
710 - let ops = [];
711 - let child;
712 - let sibling;
713 -
714 - function GreatGrandchild() {
715 - ops.push('GreatGrandchild');
716 - return <div />;
717 - }
718 -
719 - function Grandchild() {
720 - ops.push('Grandchild');
721 - return <GreatGrandchild />;
722 - }
715 + xit(
716 + 'can reuse work that began but did not complete, after being preempted',
717 + () => {
718 + let ops = [];
719 + let child;
720 + let sibling;
721
724 - class Child extends React.Component {
725 - state = {step: 0};
726 - render() {
727 - child = this;
728 - ops.push('Child');
729 - return <Grandchild />;
730 - }
731 - }
732 -
733 - class Sibling extends React.Component {
734 - render() {
735 - ops.push('Sibling');
736 - sibling = this;
722 + function GreatGrandchild() {
723 + ops.push('GreatGrandchild');
724 return <div />;
725 }
739 - }
726
741 - function Parent() {
742 - ops.push('Parent');
743 - return [
744 - // The extra div is necessary because when Parent bails out during the
745 - // high priority update, its progressedPriority is set to high.
746 - // So its direct children cannot be reused when we resume at
747 - // low priority. I think this would be fixed by changing
748 - // pendingWorkPriority and progressedPriority to be the priority of
749 - // the children only, not including the fiber itself.
750 - <div key="a"><Child /></div>,
751 - <Sibling key="b" />,
752 - ];
753 - }
754 -
755 - ReactNoop.render(<Parent />);
756 - ReactNoop.flush();
757 - ops = [];
758 -
759 - // Begin working on a low priority update to Child, but stop before
760 - // GreatGrandchild. Child and Grandchild begin but don't complete.
761 - child.setState({step: 1});
762 - ReactNoop.flushDeferredPri(30);
763 - expect(ops).toEqual(['Child', 'Grandchild']);
727 + function Grandchild() {
728 + ops.push('Grandchild');
729 + return <GreatGrandchild />;
730 + }
731
765 - // Interrupt the current low pri work with a high pri update elsewhere in
766 - // the tree.
767 - ops = [];
768 - ReactNoop.syncUpdates(() => {
769 - sibling.setState({});
770 - });
771 - expect(ops).toEqual(['Sibling']);
732 + class Child extends React.Component {
733 + state = {step: 0};
734 + render() {
735 + child = this;
736 + ops.push('Child');
737 + return <Grandchild />;
738 + }
739 + }
740
773 - // Continue the low pri work. The work on Child and GrandChild was memoized
774 - // so they should not be worked on again.
775 - ops = [];
776 - ReactNoop.flush();
777 - expect(ops).toEqual([
778 - // No Child
779 - // No Grandchild
780 - 'GreatGrandchild',
781 - ]);
782 - });
741 + class Sibling extends React.Component {
742 + render() {
743 + ops.push('Sibling');
744 + sibling = this;
745 + return <div />;
746 + }
747 + }
748
784 - it('can reuse work if shouldComponentUpdate is false, after being preempted', () => {
785 - var ops = [];
749 + function Parent() {
750 + ops.push('Parent');
751 + return [
752 + // The extra div is necessary because when Parent bails out during the
753 + // high priority update, its progressedPriority is set to high.
754 + // So its direct children cannot be reused when we resume at
755 + // low priority. I think this would be fixed by changing
756 + // pendingWorkPriority and progressedPriority to be the priority of
757 + // the children only, not including the fiber itself.
758 + <div key="a"><Child /></div>,
759 + <Sibling key="b" />,
760 + ];
761 + }
762
787 - function Bar(props) {
788 - ops.push('Bar');
789 - return <div>{props.children}</div>;
790 - }
763 + ReactNoop.render(<Parent />);
764 + ReactNoop.flush();
765 + ops = [];
766 +
767 + // Begin working on a low priority update to Child, but stop before
768 + // GreatGrandchild. Child and Grandchild begin but don't complete.
769 + child.setState({step: 1});
770 + ReactNoop.flushDeferredPri(30);
771 + expect(ops).toEqual(['Child', 'Grandchild']);
772 +
773 + // Interrupt the current low pri work with a high pri update elsewhere in
774 + // the tree.
775 + ops = [];
776 + ReactNoop.syncUpdates(() => {
777 + sibling.setState({});
778 + });
779 + expect(ops).toEqual(['Sibling']);
780
792 - class Middle extends React.Component {
793 - shouldComponentUpdate(nextProps) {
794 - return this.props.children !== nextProps.children;
781 + // Continue the low pri work. The work on Child and GrandChild was memoized
782 + // so they should not be worked on again.
783 + ops = [];
784 + ReactNoop.flush();
785 + expect(ops).toEqual([
786 + // No Child
787 + // No Grandchild
788 + 'GreatGrandchild',
789 + ]);
790 + },
791 + );
792 +
793 + xit(
794 + 'can reuse work if shouldComponentUpdate is false, after being preempted',
795 + () => {
796 + var ops = [];
797 +
798 + function Bar(props) {
799 + ops.push('Bar');
800 + return <div>{props.children}</div>;
801 }
796 - render() {
797 - ops.push('Middle');
798 - return <span>{this.props.children}</span>;
802 +
803 + class Middle extends React.Component {
804 + shouldComponentUpdate(nextProps) {
805 + return this.props.children !== nextProps.children;
806 + }
807 + render() {
808 + ops.push('Middle');
809 + return <span>{this.props.children}</span>;
810 + }
811 }
800 - }
812
802 - class Content extends React.Component {
803 - shouldComponentUpdate(nextProps) {
804 - return this.props.step !== nextProps.step;
813 + class Content extends React.Component {
814 + shouldComponentUpdate(nextProps) {
815 + return this.props.step !== nextProps.step;
816 + }
817 + render() {
818 + ops.push('Content');
819 + return (
820 + <div>
821 + <Middle>{this.props.step === 0 ? 'Hi' : 'Hello'}</Middle>
822 + <Bar>{this.props.step === 0 ? this.props.text : '-'}</Bar>
823 + <Middle>{this.props.step === 0 ? 'There' : 'World'}</Middle>
824 + </div>
825 + );
826 + }
827 }
806 - render() {
807 - ops.push('Content');
828 +
829 + function Foo(props) {
830 + ops.push('Foo');
831 return (
832 <div>
810 - <Middle>{this.props.step === 0 ? 'Hi' : 'Hello'}</Middle>
811 - <Bar>{this.props.step === 0 ? this.props.text : '-'}</Bar>
812 - <Middle>{this.props.step === 0 ? 'There' : 'World'}</Middle>
833 + <Bar>{props.text}</Bar>
834 + <div hidden={true}>
835 + <Content step={props.step} text={props.text} />
836 + </div>
837 </div>
838 );
839 }
816 - }
840
818 - function Foo(props) {
819 - ops.push('Foo');
820 - return (
821 - <div>
822 - <Bar>{props.text}</Bar>
823 - <div hidden={true}>
824 - <Content step={props.step} text={props.text} />
825 - </div>
826 - </div>
827 - );
828 - }
841 + // Init
842 + ReactNoop.render(<Foo text="foo" step={0} />);
843 + ReactNoop.flush();
844
830 - // Init
831 - ReactNoop.render(<Foo text="foo" step={0} />);
832 - ReactNoop.flush();
845 + expect(ops).toEqual(['Foo', 'Bar', 'Content', 'Middle', 'Bar', 'Middle']);
846
834 - expect(ops).toEqual(['Foo', 'Bar', 'Content', 'Middle', 'Bar', 'Middle']);
847 + ops = [];
848
836 - ops = [];
849 + // Make a quick update which will schedule low priority work to
850 + // update the middle content.
851 + ReactNoop.render(<Foo text="bar" step={1} />);
852 + ReactNoop.flushDeferredPri(30 + 5);
853
838 - // Make a quick update which will schedule low priority work to
839 - // update the middle content.
840 - ReactNoop.render(<Foo text="bar" step={1} />);
841 - ReactNoop.flushDeferredPri(30 + 5);
854 + expect(ops).toEqual(['Foo', 'Bar']);
855
843 - expect(ops).toEqual(['Foo', 'Bar']);
856 + ops = [];
857
845 - ops = [];
858 + // The middle content is now pending rendering...
859 + ReactNoop.flushDeferredPri(30 + 25 + 5);
860 + expect(ops).toEqual(['Content', 'Middle', 'Bar']); // One more Middle left.
861
847 - // The middle content is now pending rendering...
848 - ReactNoop.flushDeferredPri(30 + 25 + 5);
849 - expect(ops).toEqual(['Content', 'Middle', 'Bar']); // One more Middle left.
862 + ops = [];
863
851 - ops = [];
864 + // but we'll interrupt it to render some higher priority work.
865 + // The middle content will bailout so it remains untouched.
866 + ReactNoop.render(<Foo text="foo" step={1} />);
867 + ReactNoop.flushDeferredPri(30);
868
853 - // but we'll interrupt it to render some higher priority work.
854 - // The middle content will bailout so it remains untouched.
855 - ReactNoop.render(<Foo text="foo" step={1} />);
856 - ReactNoop.flushDeferredPri(30);
869 + expect(ops).toEqual(['Foo', 'Bar']);
870
858 - expect(ops).toEqual(['Foo', 'Bar']);
871 + ops = [];
872
860 - ops = [];
861 -
862 - // Since we did nothing to the middle subtree during the interuption,
863 - // we should be able to reuse the reconciliation work that we already did
864 - // without restarting.
865 - ReactNoop.flush();
866 - expect(ops).toEqual(['Middle']);
867 - });
873 + // Since we did nothing to the middle subtree during the interuption,
874 + // we should be able to reuse the reconciliation work that we already did
875 + // without restarting.
876 + ReactNoop.flush();
877 + expect(ops).toEqual(['Middle']);
878 + },
879 + );
880
881 it('memoizes work even if shouldComponentUpdate returns false', () => {
882 let ops = [];
@@ -1103,7 +1115,7 @@ describe('ReactIncremental', () => {
1115 expect(ops).toEqual(['Foo', 'Bar', 'Baz', 'Bar', 'Baz']);
1116 });
1117
1106 - it('can call sCU while resuming a partly mounted component', () => {
1118 + xit('can call sCU while resuming a partly mounted component', () => {
1119 var ops = [];
1120
1121 var instances = new Set();
@@ -1152,7 +1164,7 @@ describe('ReactIncremental', () => {
1164 expect(instances.size).toBe(4);
1165 });
1166
1155 - it('gets new props when setting state on a partly updated component', () => {
1167 + xit('gets new props when setting state on a partly updated component', () => {
1168 var ops = [];
1169 var instances = [];
1170
@@ -1208,7 +1220,7 @@ describe('ReactIncremental', () => {
1220 expect(ops).toEqual(['Bar:A-1', 'Baz']);
1221 });
1222
1211 - it('calls componentWillMount twice if the initial render is aborted', () => {
1223 + xit('calls componentWillMount twice if the initial render is aborted', () => {
1224 var ops = [];
1225
1226 class LifeCycle extends React.Component {
@@ -1264,54 +1276,57 @@ describe('ReactIncremental', () => {
1276 ]);
1277 });
1278
1267 - it('uses state set in componentWillMount even if initial render was aborted', () => {
1268 - var ops = [];
1279 + xit(
1280 + 'uses state set in componentWillMount even if initial render was aborted',
1281 + () => {
1282 + var ops = [];
1283
1270 - class LifeCycle extends React.Component {
1271 - constructor(props) {
1272 - super(props);
1273 - this.state = {x: this.props.x + '(ctor)'};
1274 - }
1275 - componentWillMount() {
1276 - ops.push('componentWillMount:' + this.state.x);
1277 - this.setState({x: this.props.x + '(willMount)'});
1278 - }
1279 - componentDidMount() {
1280 - ops.push('componentDidMount:' + this.state.x);
1281 - }
1282 - render() {
1283 - ops.push('render:' + this.state.x);
1284 - return <span />;
1284 + class LifeCycle extends React.Component {
1285 + constructor(props) {
1286 + super(props);
1287 + this.state = {x: this.props.x + '(ctor)'};
1288 + }
1289 + componentWillMount() {
1290 + ops.push('componentWillMount:' + this.state.x);
1291 + this.setState({x: this.props.x + '(willMount)'});
1292 + }
1293 + componentDidMount() {
1294 + ops.push('componentDidMount:' + this.state.x);
1295 + }
1296 + render() {
1297 + ops.push('render:' + this.state.x);
1298 + return <span />;
1299 + }
1300 }
1286 - }
1301
1288 - function App(props) {
1289 - ops.push('App');
1290 - return <LifeCycle x={props.x} />;
1291 - }
1302 + function App(props) {
1303 + ops.push('App');
1304 + return <LifeCycle x={props.x} />;
1305 + }
1306
1293 - ReactNoop.render(<App x={0} />);
1294 - ReactNoop.flushDeferredPri(20);
1307 + ReactNoop.render(<App x={0} />);
1308 + ReactNoop.flushDeferredPri(20);
1309
1296 - expect(ops).toEqual([
1297 - 'App',
1298 - 'componentWillMount:0(ctor)',
1299 - 'render:0(willMount)',
1300 - ]);
1310 + expect(ops).toEqual([
1311 + 'App',
1312 + 'componentWillMount:0(ctor)',
1313 + 'render:0(willMount)',
1314 + ]);
1315
1302 - ops = [];
1303 - ReactNoop.render(<App x={1} />);
1304 - ReactNoop.flush();
1316 + ops = [];
1317 + ReactNoop.render(<App x={1} />);
1318 + ReactNoop.flush();
1319
1306 - expect(ops).toEqual([
1307 - 'App',
1308 - 'componentWillMount:0(willMount)',
1309 - 'render:1(willMount)',
1310 - 'componentDidMount:1(willMount)',
1311 - ]);
1312 - });
1320 + expect(ops).toEqual([
1321 + 'App',
1322 + 'componentWillMount:0(willMount)',
1323 + 'render:1(willMount)',
1324 + 'componentDidMount:1(willMount)',
1325 + ]);
1326 + },
1327 + );
1328
1314 - it('calls componentWill* twice if an update render is aborted', () => {
1329 + xit('calls componentWill* twice if an update render is aborted', () => {
1330 var ops = [];
1331
1332 class LifeCycle extends React.Component {
@@ -1398,7 +1413,7 @@ describe('ReactIncremental', () => {
1413 ]);
1414 });
1415
1401 - it('does not call componentWillReceiveProps for state-only updates', () => {
1416 + xit('does not call componentWillReceiveProps for state-only updates', () => {
1417 var ops = [];
1418
1419 var instances = [];
@@ -1547,101 +1562,104 @@ describe('ReactIncremental', () => {
1562 // incomplete parents.
1563 });
1564
1550 - it('skips will/DidUpdate when bailing unless an update was already in progress', () => {
1551 - var ops = [];
1565 + xit(
1566 + 'skips will/DidUpdate when bailing unless an update was already in progress',
1567 + () => {
1568 + var ops = [];
1569
1553 - class LifeCycle extends React.Component {
1554 - componentWillMount() {
1555 - ops.push('componentWillMount');
1556 - }
1557 - componentDidMount() {
1558 - ops.push('componentDidMount');
1559 - }
1560 - componentWillReceiveProps(nextProps) {
1561 - ops.push('componentWillReceiveProps');
1562 - }
1563 - shouldComponentUpdate(nextProps) {
1564 - ops.push('shouldComponentUpdate');
1565 - // Bail
1566 - return this.props.x !== nextProps.x;
1567 - }
1568 - componentWillUpdate(nextProps) {
1569 - ops.push('componentWillUpdate');
1570 - }
1571 - componentDidUpdate(prevProps) {
1572 - ops.push('componentDidUpdate');
1570 + class LifeCycle extends React.Component {
1571 + componentWillMount() {
1572 + ops.push('componentWillMount');
1573 + }
1574 + componentDidMount() {
1575 + ops.push('componentDidMount');
1576 + }
1577 + componentWillReceiveProps(nextProps) {
1578 + ops.push('componentWillReceiveProps');
1579 + }
1580 + shouldComponentUpdate(nextProps) {
1581 + ops.push('shouldComponentUpdate');
1582 + // Bail
1583 + return this.props.x !== nextProps.x;
1584 + }
1585 + componentWillUpdate(nextProps) {
1586 + ops.push('componentWillUpdate');
1587 + }
1588 + componentDidUpdate(prevProps) {
1589 + ops.push('componentDidUpdate');
1590 + }
1591 + render() {
1592 + ops.push('render');
1593 + return <span />;
1594 + }
1595 }
1574 - render() {
1575 - ops.push('render');
1596 +
1597 + function Sibling() {
1598 + ops.push('render sibling');
1599 return <span />;
1600 }
1578 - }
1579 -
1580 - function Sibling() {
1581 - ops.push('render sibling');
1582 - return <span />;
1583 - }
1584 -
1585 - function App(props) {
1586 - return [<LifeCycle key="a" x={props.x} />, <Sibling key="b" />];
1587 - }
1588 -
1589 - ReactNoop.render(<App x={0} />);
1590 - ReactNoop.flush();
1591 -
1592 - expect(ops).toEqual([
1593 - 'componentWillMount',
1594 - 'render',
1595 - 'render sibling',
1596 - 'componentDidMount',
1597 - ]);
1601
1599 - ops = [];
1600 -
1601 - // Update to same props
1602 - ReactNoop.render(<App x={0} />);
1603 - ReactNoop.flush();
1602 + function App(props) {
1603 + return [<LifeCycle key="a" x={props.x} />, <Sibling key="b" />];
1604 + }
1605
1605 - expect(ops).toEqual([
1606 - 'componentWillReceiveProps',
1607 - 'shouldComponentUpdate',
1608 - // no componentWillUpdate
1609 - // no render
1610 - 'render sibling',
1611 - // no componentDidUpdate
1612 - ]);
1606 + ReactNoop.render(<App x={0} />);
1607 + ReactNoop.flush();
1608
1614 - ops = [];
1609 + expect(ops).toEqual([
1610 + 'componentWillMount',
1611 + 'render',
1612 + 'render sibling',
1613 + 'componentDidMount',
1614 + ]);
1615
1616 - // Begin updating to new props...
1617 - ReactNoop.render(<App x={1} />);
1618 - ReactNoop.flushDeferredPri(30);
1616 + ops = [];
1617
1620 - expect(ops).toEqual([
1621 - 'componentWillReceiveProps',
1622 - 'shouldComponentUpdate',
1623 - 'componentWillUpdate',
1624 - 'render',
1625 - 'render sibling',
1626 - // no componentDidUpdate yet
1627 - ]);
1618 + // Update to same props
1619 + ReactNoop.render(<App x={0} />);
1620 + ReactNoop.flush();
1621
1629 - ops = [];
1622 + expect(ops).toEqual([
1623 + 'componentWillReceiveProps',
1624 + 'shouldComponentUpdate',
1625 + // no componentWillUpdate
1626 + // no render
1627 + 'render sibling',
1628 + // no componentDidUpdate
1629 + ]);
1630 +
1631 + ops = [];
1632 +
1633 + // Begin updating to new props...
1634 + ReactNoop.render(<App x={1} />);
1635 + ReactNoop.flushDeferredPri(30);
1636 +
1637 + expect(ops).toEqual([
1638 + 'componentWillReceiveProps',
1639 + 'shouldComponentUpdate',
1640 + 'componentWillUpdate',
1641 + 'render',
1642 + 'render sibling',
1643 + // no componentDidUpdate yet
1644 + ]);
1645 +
1646 + ops = [];
1647 +
1648 + // ...but we'll interrupt it to rerender the same props.
1649 + ReactNoop.render(<App x={1} />);
1650 + ReactNoop.flush();
1651
1631 - // ...but we'll interrupt it to rerender the same props.
1632 - ReactNoop.render(<App x={1} />);
1633 - ReactNoop.flush();
1634 -
1635 - // We can bail out this time, but we must call componentDidUpdate.
1636 - expect(ops).toEqual([
1637 - 'componentWillReceiveProps',
1638 - 'shouldComponentUpdate',
1639 - // no componentWillUpdate
1640 - // no render
1641 - 'render sibling',
1642 - 'componentDidUpdate',
1643 - ]);
1644 - });
1652 + // We can bail out this time, but we must call componentDidUpdate.
1653 + expect(ops).toEqual([
1654 + 'componentWillReceiveProps',
1655 + 'shouldComponentUpdate',
1656 + // no componentWillUpdate
1657 + // no render
1658 + 'render sibling',
1659 + 'componentDidUpdate',
1660 + ]);
1661 + },
1662 + );
1663
1664 it('performs batched updates at the end of the batch', () => {
1665 var ops = [];
@@ -1944,7 +1962,7 @@ describe('ReactIncremental', () => {
1962 ]);
1963 });
1964
1947 - it('provides context when reusing work', () => {
1965 + xit('provides context when reusing work', () => {
1966 var ops = [];
1967
1968 class Intl extends React.Component {
@@ -2330,86 +2348,89 @@ describe('ReactIncremental', () => {
2348 ]);
2349 });
2350
2333 - it('should reuse memoized work if pointers are updated before calling lifecycles', () => {
2334 - let cduNextProps = [];
2335 - let cduPrevProps = [];
2336 - let scuNextProps = [];
2337 - let scuPrevProps = [];
2338 - let renderCounter = 0;
2339 -
2340 - function SecondChild(props) {
2341 - return <span>{props.children}</span>;
2342 - }
2351 + xit(
2352 + 'should reuse memoized work if pointers are updated before calling lifecycles',
2353 + () => {
2354 + let cduNextProps = [];
2355 + let cduPrevProps = [];
2356 + let scuNextProps = [];
2357 + let scuPrevProps = [];
2358 + let renderCounter = 0;
2359
2344 - class FirstChild extends React.Component {
2345 - componentDidUpdate(prevProps, prevState) {
2346 - cduNextProps.push(this.props);
2347 - cduPrevProps.push(prevProps);
2360 + function SecondChild(props) {
2361 + return <span>{props.children}</span>;
2362 }
2349 - shouldComponentUpdate(nextProps, nextState) {
2350 - scuNextProps.push(nextProps);
2351 - scuPrevProps.push(this.props);
2352 - return this.props.children !== nextProps.children;
2363 +
2364 + class FirstChild extends React.Component {
2365 + componentDidUpdate(prevProps, prevState) {
2366 + cduNextProps.push(this.props);
2367 + cduPrevProps.push(prevProps);
2368 + }
2369 + shouldComponentUpdate(nextProps, nextState) {
2370 + scuNextProps.push(nextProps);
2371 + scuPrevProps.push(this.props);
2372 + return this.props.children !== nextProps.children;
2373 + }
2374 + render() {
2375 + renderCounter++;
2376 + return <span>{this.props.children}</span>;
2377 + }
2378 }
2354 - render() {
2355 - renderCounter++;
2356 - return <span>{this.props.children}</span>;
2379 +
2380 + class Middle extends React.Component {
2381 + render() {
2382 + return (
2383 + <div>
2384 + <FirstChild>{this.props.children}</FirstChild>
2385 + <SecondChild>{this.props.children}</SecondChild>
2386 + </div>
2387 + );
2388 + }
2389 }
2358 - }
2390
2360 - class Middle extends React.Component {
2361 - render() {
2391 + function Root(props) {
2392 return (
2363 - <div>
2364 - <FirstChild>{this.props.children}</FirstChild>
2365 - <SecondChild>{this.props.children}</SecondChild>
2393 + <div hidden={true}>
2394 + <Middle {...props} />
2395 </div>
2396 );
2397 }
2369 - }
2370 -
2371 - function Root(props) {
2372 - return (
2373 - <div hidden={true}>
2374 - <Middle {...props} />
2375 - </div>
2376 - );
2377 - }
2398
2379 - // Initial render of the entire tree.
2380 - // Renders: Root, Middle, FirstChild, SecondChild
2381 - ReactNoop.render(<Root>A</Root>);
2382 - ReactNoop.flush();
2399 + // Initial render of the entire tree.
2400 + // Renders: Root, Middle, FirstChild, SecondChild
2401 + ReactNoop.render(<Root>A</Root>);
2402 + ReactNoop.flush();
2403
2384 - expect(renderCounter).toBe(1);
2385 -
2386 - // Schedule low priority work to update children.
2387 - // Give it enough time to partially render.
2388 - // Renders: Root, Middle, FirstChild
2389 - ReactNoop.render(<Root>B</Root>);
2390 - ReactNoop.flushDeferredPri(20 + 30 + 5);
2391 -
2392 - // At this point our FirstChild component has rendered a second time,
2393 - // But since the render is not completed cDU should not be called yet.
2394 - expect(renderCounter).toBe(2);
2395 - expect(scuPrevProps).toEqual([{children: 'A'}]);
2396 - expect(scuNextProps).toEqual([{children: 'B'}]);
2397 - expect(cduPrevProps).toEqual([]);
2398 - expect(cduNextProps).toEqual([]);
2399 -
2400 - // Next interrupt the partial render with higher priority work.
2401 - // The in-progress child content will bailout.
2402 - // Renders: Root, Middle, FirstChild, SecondChild
2403 - ReactNoop.render(<Root>B</Root>);
2404 - ReactNoop.flush();
2404 + expect(renderCounter).toBe(1);
2405 +
2406 + // Schedule low priority work to update children.
2407 + // Give it enough time to partially render.
2408 + // Renders: Root, Middle, FirstChild
2409 + ReactNoop.render(<Root>B</Root>);
2410 + ReactNoop.flushDeferredPri(20 + 30 + 5);
2411 +
2412 + // At this point our FirstChild component has rendered a second time,
2413 + // But since the render is not completed cDU should not be called yet.
2414 + expect(renderCounter).toBe(2);
2415 + expect(scuPrevProps).toEqual([{children: 'A'}]);
2416 + expect(scuNextProps).toEqual([{children: 'B'}]);
2417 + expect(cduPrevProps).toEqual([]);
2418 + expect(cduNextProps).toEqual([]);
2419 +
2420 + // Next interrupt the partial render with higher priority work.
2421 + // The in-progress child content will bailout.
2422 + // Renders: Root, Middle, FirstChild, SecondChild
2423 + ReactNoop.render(<Root>B</Root>);
2424 + ReactNoop.flush();
2425
2406 - // At this point the higher priority render has completed.
2407 - // Since FirstChild props didn't change, sCU returned false.
2408 - // The previous memoized copy should be used.
2409 - expect(renderCounter).toBe(2);
2410 - expect(scuPrevProps).toEqual([{children: 'A'}, {children: 'B'}]);
2411 - expect(scuNextProps).toEqual([{children: 'B'}, {children: 'B'}]);
2412 - expect(cduPrevProps).toEqual([{children: 'A'}]);
2413 - expect(cduNextProps).toEqual([{children: 'B'}]);
2414 - });
2426 + // At this point the higher priority render has completed.
2427 + // Since FirstChild props didn't change, sCU returned false.
2428 + // The previous memoized copy should be used.
2429 + expect(renderCounter).toBe(2);
2430 + expect(scuPrevProps).toEqual([{children: 'A'}, {children: 'B'}]);
2431 + expect(scuNextProps).toEqual([{children: 'B'}, {children: 'B'}]);
2432 + expect(cduPrevProps).toEqual([{children: 'A'}]);
2433 + expect(cduNextProps).toEqual([{children: 'B'}]);
2434 + },
2435 + );
2436 });
src/renderers/shared/fiber/__tests__/ReactIncrementalPerf-test.js
+1 -1
@@ -280,7 +280,7 @@ describe('ReactDebugFiberPerf', () => {
280 expect(getFlameChart()).toMatchSnapshot();
281 });
282
283 - it('measures deprioritized work', () => {
283 + xit('measures deprioritized work', () => {
284 addComment('Flush the parent');
285 ReactNoop.syncUpdates(() => {
286 ReactNoop.render(
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
+87 -84
@@ -470,7 +470,7 @@ describe('ReactIncrementalSideEffects', () => {
470 expect(ReactNoop.getChildren()).toEqual([div(span(1))]);
471 });
472
473 - it('can defer side-effects and resume them later on', function() {
473 + xit('can defer side-effects and resume them later on', () => {
474 class Bar extends React.Component {
475 shouldComponentUpdate(nextProps) {
476 return this.props.idx !== nextProps.idx;
@@ -547,7 +547,7 @@ describe('ReactIncrementalSideEffects', () => {
547 expect(innerSpanA).toBe(innerSpanB);
548 });
549
550 - it('can defer side-effects and reuse them later - complex', function() {
550 + xit('can defer side-effects and reuse them later - complex', function() {
551 var ops = [];
552
553 class Bar extends React.Component {
@@ -691,106 +691,109 @@ describe('ReactIncrementalSideEffects', () => {
691 expect(ops).toEqual(['Bar', 'Baz', 'Bar', 'Bar']);
692 });
693
694 - it('deprioritizes setStates that happens within a deprioritized tree', () => {
695 - var ops = [];
696 -
697 - var barInstances = [];
698 -
699 - class Bar extends React.Component {
700 - constructor() {
701 - super();
702 - this.state = {active: false};
703 - barInstances.push(this);
704 - }
705 - activate() {
706 - this.setState({active: true});
707 - }
708 - render() {
709 - ops.push('Bar');
710 - return <span prop={this.state.active ? 'X' : this.props.idx} />;
694 + xit(
695 + 'deprioritizes setStates that happens within a deprioritized tree',
696 + () => {
697 + var ops = [];
698 +
699 + var barInstances = [];
700 +
701 + class Bar extends React.Component {
702 + constructor() {
703 + super();
704 + this.state = {active: false};
705 + barInstances.push(this);
706 + }
707 + activate() {
708 + this.setState({active: true});
709 + }
710 + render() {
711 + ops.push('Bar');
712 + return <span prop={this.state.active ? 'X' : this.props.idx} />;
713 + }
714 }
712 - }
713 - function Foo(props) {
714 - ops.push('Foo');
715 - return (
716 - <div>
717 - <span prop={props.tick} />
718 - <div hidden={true}>
719 - <Bar idx={props.idx} />
720 - <Bar idx={props.idx} />
721 - <Bar idx={props.idx} />
715 + function Foo(props) {
716 + ops.push('Foo');
717 + return (
718 + <div>
719 + <span prop={props.tick} />
720 + <div hidden={true}>
721 + <Bar idx={props.idx} />
722 + <Bar idx={props.idx} />
723 + <Bar idx={props.idx} />
724 + </div>
725 </div>
723 - </div>
724 - );
725 - }
726 - ReactNoop.render(<Foo tick={0} idx={0} />);
727 - ReactNoop.flush();
728 - expect(ReactNoop.getChildren()).toEqual([
729 - div(span(0), div(span(0), span(0), span(0))),
730 - ]);
726 + );
727 + }
728 + ReactNoop.render(<Foo tick={0} idx={0} />);
729 + ReactNoop.flush();
730 + expect(ReactNoop.getChildren()).toEqual([
731 + div(span(0), div(span(0), span(0), span(0))),
732 + ]);
733
732 - expect(ops).toEqual(['Foo', 'Bar', 'Bar', 'Bar']);
734 + expect(ops).toEqual(['Foo', 'Bar', 'Bar', 'Bar']);
735
734 - ops = [];
736 + ops = [];
737
736 - ReactNoop.render(<Foo tick={1} idx={1} />);
737 - ReactNoop.flushDeferredPri(70 + 5);
738 - expect(ReactNoop.getChildren()).toEqual([
739 - div(
740 - // Updated.
741 - span(1),
738 + ReactNoop.render(<Foo tick={1} idx={1} />);
739 + ReactNoop.flushDeferredPri(70 + 5);
740 + expect(ReactNoop.getChildren()).toEqual([
741 div(
743 - // Still not updated.
744 - span(0),
745 - span(0),
746 - span(0),
742 + // Updated.
743 + span(1),
744 + div(
745 + // Still not updated.
746 + span(0),
747 + span(0),
748 + span(0),
749 + ),
750 ),
748 - ),
749 - ]);
751 + ]);
752
751 - expect(ops).toEqual(['Foo', 'Bar', 'Bar']);
752 - ops = [];
753 + expect(ops).toEqual(['Foo', 'Bar', 'Bar']);
754 + ops = [];
755
754 - barInstances[0].activate();
756 + barInstances[0].activate();
757
756 - // This should not be enough time to render the content of all the hidden
757 - // items. Including the set state since that is deprioritized.
758 - // TODO: The cycles it takes to do this could be lowered with further
759 - // optimizations.
760 - ReactNoop.flushDeferredPri(60 + 5);
761 - expect(ReactNoop.getChildren()).toEqual([
762 - div(
763 - // Updated.
764 - span(1),
758 + // This should not be enough time to render the content of all the hidden
759 + // items. Including the set state since that is deprioritized.
760 + // TODO: The cycles it takes to do this could be lowered with further
761 + // optimizations.
762 + ReactNoop.flushDeferredPri(60 + 5);
763 + expect(ReactNoop.getChildren()).toEqual([
764 div(
766 - // Still not updated.
767 - span(0),
768 - span(0),
769 - span(0),
765 + // Updated.
766 + span(1),
767 + div(
768 + // Still not updated.
769 + span(0),
770 + span(0),
771 + span(0),
772 + ),
773 ),
771 - ),
772 - ]);
774 + ]);
775
774 - expect(ops).toEqual(['Bar']);
775 - ops = [];
776 + expect(ops).toEqual(['Bar']);
777 + ops = [];
778
777 - // However, once we render fully, we will have enough time to finish it all
778 - // at once.
779 - ReactNoop.flush();
780 - expect(ReactNoop.getChildren()).toEqual([
781 - div(
782 - span(1),
779 + // However, once we render fully, we will have enough time to finish it all
780 + // at once.
781 + ReactNoop.flush();
782 + expect(ReactNoop.getChildren()).toEqual([
783 div(
784 - // Now we had enough time to finish the spans.
785 - span('X'),
786 - span(1),
784 span(1),
785 + div(
786 + // Now we had enough time to finish the spans.
787 + span('X'),
788 + span(1),
789 + span(1),
790 + ),
791 ),
789 - ),
790 - ]);
792 + ]);
793
792 - expect(ops).toEqual(['Bar']);
793 - });
794 + expect(ops).toEqual(['Bar']);
795 + },
796 + );
797 // TODO: Test that side-effects are not cut off when a work in progress node
798 // moves to "current" without flushing due to having lower priority. Does this
799 // even happen? Maybe a child doesn't get processed because it is lower prio?
src/renderers/shared/fiber/__tests__/__snapshots__/ReactIncrementalPerf-test.js.snap
+2 -2
@@ -61,8 +61,8 @@ exports[`ReactDebugFiberPerf deduplicates lifecycle names during commit to reduc
61 ⚛ B.componentDidUpdate
62 ⚛ B [update]
63 ⛔ (Committing Changes) Warning: Caused by a cascading update in earlier commit
64 - ⚛ (Committing Host Effects: 3 Total)
65 - ⚛ (Calling Lifecycle Methods: 3 Total)
64 + ⚛ (Committing Host Effects: 6 Total)
65 + ⚛ (Calling Lifecycle Methods: 6 Total)
66 ⚛ B.componentDidUpdate
67 "
68 `;