Meant to commit these changes with #8206... oops.
Andrew Clark committed
Nov 8, 2016 at 13:47 UTC
f829e2f1f1d950db7d588a5dd288d3e39e074d4d
5 files changed
+146
-66
scripts/fiber/tests-failing.txt
-3
@@ -72,9 +72,6 @@ src/renderers/art/__tests__/ReactART-test.js
72
* resolves refs before componentDidMount
73
* resolves refs before componentDidUpdate
74
75
-src/renderers/dom/__tests__/ReactDOMProduction-test.js
76
-* should throw with an error code in production
77
-
75
src/renderers/dom/shared/__tests__/CSSPropertyOperations-test.js
76
* should set style attribute when styles exist
77
* should warn when using hyphenated style names
scripts/fiber/tests-passing.txt
+3
-1
@@ -453,6 +453,7 @@ src/renderers/dom/__tests__/ReactDOMProduction-test.js
453
* should use prod React
454
* should handle a simple flow
455
* should call lifecycle methods
456
+* should throw with an error code in production
457
458
src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
459
* should render strings as children
@@ -842,6 +843,8 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
843
* splits deferred work on multiple roots
844
* works on deferred roots in the order they were scheduled
845
* handles interleaved deferred and animation work
846
+* schedules sync updates when inside componentDidMount/Update
847
+* can opt-in to deferred/animation scheduling inside componentDidMount/Update
848
849
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
850
* can update child nodes of a host instance
@@ -862,7 +865,6 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
865
* calls setState callback even if component bails out
866
* calls componentWillUnmount after a deletion, even if nested
867
* calls componentDidMount/Update after insertion/update
865
-* schedules sync updates when inside componentDidMount/Update
868
* invokes ref callbacks after insertion/update/unmount
869
* supports string refs
870
src/renderers/shared/fiber/ReactFiberScheduler.js
+5
-2
@@ -211,8 +211,11 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
211
const current = effectfulFiber.alternate;
212
const previousPriorityContext = priorityContext;
213
priorityContext = TaskPriority;
214
- commitLifeCycles(current, effectfulFiber);
215
- priorityContext = previousPriorityContext;
214
+ try {
215
+ commitLifeCycles(current, effectfulFiber);
216
+ } finally {
217
+ priorityContext = previousPriorityContext;
218
+ }
219
}
220
const next = effectfulFiber.nextEffect;
221
// Ensure that we clean these up so that we don't accidentally keep them.
src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
+138
@@ -449,4 +449,142 @@ describe('ReactIncrementalScheduling', () => {
449
expect(ReactNoop.getChildren('b')).toEqual([span('b:3')]);
450
expect(ReactNoop.getChildren('c')).toEqual([span('c:3')]);
451
});
452
+
453
+ it('schedules sync updates when inside componentDidMount/Update', () => {
454
+ var instance;
455
+ var ops = [];
456
+
457
+ class Foo extends React.Component {
458
+ state = { tick: 0 };
459
+
460
+ componentDidMount() {
461
+ ops.push('componentDidMount (before setState): ' + this.state.tick);
462
+ this.setState({ tick: 1 });
463
+ // We're in a batch. Update hasn't flushed yet.
464
+ ops.push('componentDidMount (after setState): ' + this.state.tick);
465
+ }
466
+
467
+ componentDidUpdate() {
468
+ ops.push('componentDidUpdate: ' + this.state.tick);
469
+ if (this.state.tick === 2) {
470
+ ops.push('componentDidUpdate (before setState): ' + this.state.tick);
471
+ this.setState({ tick: 3 });
472
+ ops.push('componentDidUpdate (after setState): ' + this.state.tick);
473
+ // We're in a batch. Update hasn't flushed yet.
474
+ }
475
+ }
476
+
477
+ render() {
478
+ ops.push('render: ' + this.state.tick);
479
+ instance = this;
480
+ return <span prop={this.state.tick} />;
481
+ }
482
+ }
483
+
484
+ ReactNoop.render(<Foo />);
485
+
486
+ ReactNoop.flushDeferredPri(20);
487
+ expect(ops).toEqual([
488
+ 'render: 0',
489
+ 'componentDidMount (before setState): 0',
490
+ 'componentDidMount (after setState): 0',
491
+ // If the setState inside componentDidMount were deferred, there would be
492
+ // no more ops. Because it has Task priority, we get these ops, too:
493
+ 'render: 1',
494
+ 'componentDidUpdate: 1',
495
+ ]);
496
+
497
+ ops = [];
498
+ instance.setState({ tick: 2 });
499
+ ReactNoop.flushDeferredPri(20);
500
+
501
+ expect(ops).toEqual([
502
+ 'render: 2',
503
+ 'componentDidUpdate: 2',
504
+ 'componentDidUpdate (before setState): 2',
505
+ 'componentDidUpdate (after setState): 2',
506
+ // If the setState inside componentDidUpdate were deferred, there would be
507
+ // no more ops. Because it has Task priority, we get these ops, too:
508
+ 'render: 3',
509
+ 'componentDidUpdate: 3',
510
+ ]);
511
+ });
512
+
513
+ it('can opt-in to deferred/animation scheduling inside componentDidMount/Update', () => {
514
+ var instance;
515
+ var ops = [];
516
+
517
+ class Foo extends React.Component {
518
+ state = { tick: 0 };
519
+
520
+ componentDidMount() {
521
+ ReactNoop.performAnimationWork(() => {
522
+ ops.push('componentDidMount (before setState): ' + this.state.tick);
523
+ this.setState({ tick: 1 });
524
+ ops.push('componentDidMount (after setState): ' + this.state.tick);
525
+ });
526
+ }
527
+
528
+ componentDidUpdate() {
529
+ ReactNoop.performAnimationWork(() => {
530
+ ops.push('componentDidUpdate: ' + this.state.tick);
531
+ if (this.state.tick === 2) {
532
+ ops.push('componentDidUpdate (before setState): ' + this.state.tick);
533
+ this.setState({ tick: 3 });
534
+ ops.push('componentDidUpdate (after setState): ' + this.state.tick);
535
+ }
536
+ });
537
+ }
538
+
539
+ render() {
540
+ ops.push('render: ' + this.state.tick);
541
+ instance = this;
542
+ return <span prop={this.state.tick} />;
543
+ }
544
+ }
545
+
546
+ ReactNoop.render(<Foo />);
547
+
548
+ ReactNoop.flushDeferredPri(20);
549
+ expect(ops).toEqual([
550
+ 'render: 0',
551
+ 'componentDidMount (before setState): 0',
552
+ 'componentDidMount (after setState): 0',
553
+ // Following items shouldn't appear because they are the result of an
554
+ // update scheduled with animation priority
555
+ // 'render: 1',
556
+ // 'componentDidUpdate: 1',
557
+ ]);
558
+
559
+ ops = [];
560
+
561
+ ReactNoop.flushAnimationPri();
562
+ expect(ops).toEqual([
563
+ 'render: 1',
564
+ 'componentDidUpdate: 1',
565
+ ]);
566
+
567
+ ops = [];
568
+ instance.setState({ tick: 2 });
569
+ ReactNoop.flushDeferredPri(20);
570
+
571
+ expect(ops).toEqual([
572
+ 'render: 2',
573
+ 'componentDidUpdate: 2',
574
+ 'componentDidUpdate (before setState): 2',
575
+ 'componentDidUpdate (after setState): 2',
576
+ // Following items shouldn't appear because they are the result of an
577
+ // update scheduled with animation priority
578
+ // 'render: 3',
579
+ // 'componentDidUpdate: 3',
580
+ ]);
581
+
582
+ ops = [];
583
+
584
+ ReactNoop.flushAnimationPri();
585
+ expect(ops).toEqual([
586
+ 'render: 3',
587
+ 'componentDidUpdate: 3',
588
+ ]);
589
+ });
590
});
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
-60
@@ -1036,66 +1036,6 @@ describe('ReactIncrementalSideEffects', () => {
1036
1037
});
1038
1039
- it('schedules sync updates when inside componentDidMount/Update', () => {
1040
- var instance;
1041
- var ops = [];
1042
-
1043
- class Foo extends React.Component {
1044
- state = { tick: 0 };
1045
-
1046
- componentDidMount() {
1047
- ops.push('componentDidMount (before setState): ' + this.state.tick);
1048
- this.setState({ tick: 1 });
1049
- // We're in a batch. Update hasn't flushed yet.
1050
- ops.push('componentDidMount (after setState): ' + this.state.tick);
1051
- }
1052
-
1053
- componentDidUpdate() {
1054
- ops.push('componentDidUpdate: ' + this.state.tick);
1055
- if (this.state.tick === 2) {
1056
- ops.push('componentDidUpdate (before setState): ' + this.state.tick);
1057
- this.setState({ tick: 3 });
1058
- ops.push('componentDidUpdate (after setState): ' + this.state.tick);
1059
- // We're in a batch. Update hasn't flushed yet.
1060
- }
1061
- }
1062
-
1063
- render() {
1064
- ops.push('render: ' + this.state.tick);
1065
- instance = this;
1066
- return <span prop={this.state.tick} />;
1067
- }
1068
- }
1069
-
1070
- ReactNoop.render(<Foo />);
1071
-
1072
- ReactNoop.flushDeferredPri(20);
1073
- expect(ops).toEqual([
1074
- 'render: 0',
1075
- 'componentDidMount (before setState): 0',
1076
- 'componentDidMount (after setState): 0',
1077
- // If the setState inside componentDidMount were deferred, there would be
1078
- // no more ops. Because it has Task priority, we get these ops, too:
1079
- 'render: 1',
1080
- 'componentDidUpdate: 1',
1081
- ]);
1082
-
1083
- ops = [];
1084
- instance.setState({ tick: 2 });
1085
- ReactNoop.flushDeferredPri(20);
1086
-
1087
- expect(ops).toEqual([
1088
- 'render: 2',
1089
- 'componentDidUpdate: 2',
1090
- 'componentDidUpdate (before setState): 2',
1091
- 'componentDidUpdate (after setState): 2',
1092
- // If the setState inside componentDidUpdate were deferred, there would be
1093
- // no more ops. Because it has Task priority, we get these ops, too:
1094
- 'render: 3',
1095
- 'componentDidUpdate: 3',
1096
- ]);
1097
- });
1098
-
1039
it('invokes ref callbacks after insertion/update/unmount', () => {
1040
1041
var classInstance = null;