Add additional scheduling tests
Tests whether certain types of work can be performed after the deadline has expired.
Andrew Clark committed
Dec 7, 2016 at 22:47 UTC
f56eb893897cb0609e2ea0a940fe131c699988cc
5 files changed
+78
-13
scripts/fiber/tests-passing.txt
+2
@@ -1150,6 +1150,8 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
1150
* handles interleaved deferred and animation work
1151
* schedules sync updates when inside componentDidMount/Update
1152
* can opt-in to deferred/animation scheduling inside componentDidMount/Update
1153
+* performs Task work even after time runs out
1154
+* does not perform animation work after time runs out
1155
1156
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
1157
* can update child nodes of a host instance
src/renderers/shared/fiber/ReactFiberScheduler.js
+12
-8
@@ -548,7 +548,9 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
548
nextUnitOfWork = findNextUnitOfWork();
549
}
550
551
- if (deadline) {
551
+ // If there's a deadline, and we're not performing Task work, perform work
552
+ // using this loop that checks the deadline on every iteration.
553
+ if (deadline && priorityLevel > TaskPriority) {
554
// The deferred work loop will run until there's no time left in
555
// the current frame.
556
while (nextUnitOfWork && !deadlineHasExpired) {
@@ -575,13 +577,9 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
577
}
578
}
579
} else {
578
- // The non-deferred work loop will run until there's no more work
579
- // at the given priority level
580
- if (priorityLevel >= HighPriority) {
581
- throw new Error(
582
- 'Deferred work should only be performed using deferredWorkLoop'
583
- );
584
- }
580
+ // If there's no deadline, or if we're performing Task work, use this loop
581
+ // that doesn't check how much time is remaining. It will keep running
582
+ // until we run out of work at this priority level.
583
while (nextUnitOfWork &&
584
nextPriorityLevel !== NoWork &&
585
nextPriorityLevel <= priorityLevel) {
@@ -610,6 +608,12 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
608
// catching an error. It also lets us flush Task work at the end of a
609
// deferred batch.
610
while (priorityLevel !== NoWork) {
611
+ if (priorityLevel >= HighPriority && !deadline) {
612
+ throw new Error(
613
+ 'Cannot perform deferred work without a deadline.'
614
+ );
615
+ }
616
+
617
// Before starting any work, check to see if there are any pending
618
// commits from the previous frame. An exception is if we're flushing
619
// Task work in a deferred batch and the pending commit does not
src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
+1
-1
@@ -410,7 +410,7 @@ describe('ReactIncremental', () => {
410
// Make a quick update which will create a low pri tree on top of the
411
// already low pri tree.
412
ReactNoop.render(<Foo text="bar" />);
413
- ReactNoop.flushDeferredPri(15 + 5);
413
+ ReactNoop.flushDeferredPri(15);
414
415
expect(ops).toEqual(['Foo']);
416
src/renderers/shared/fiber/__tests__/ReactIncrementalErrorHandling-test.js
+1
-1
@@ -93,7 +93,7 @@ describe('ReactIncrementalErrorHandling', () => {
93
expect(ReactNoop.getChildren()).toEqual([]);
94
95
ops.length = 0;
96
- ReactNoop.flushDeferredPri(25 + 10);
96
+ ReactNoop.flushDeferredPri(30);
97
expect(ops).toEqual([
98
'BrokenRender',
99
'ErrorBoundary unstable_handleError',
src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
+62
-3
@@ -341,7 +341,7 @@ describe('ReactIncrementalScheduling', () => {
341
expect(ReactNoop.getChildren('b')).toEqual([]);
342
expect(ReactNoop.getChildren('c')).toEqual(null);
343
// Then the second one gets processed
344
- ReactNoop.flushDeferredPri(15 + 5 + 5);
344
+ ReactNoop.flushDeferredPri(15 + 5);
345
expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
346
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
347
expect(ReactNoop.getChildren('c')).toEqual(null);
@@ -483,7 +483,7 @@ describe('ReactIncrementalScheduling', () => {
483
484
ReactNoop.render(<Foo />);
485
486
- ReactNoop.flushDeferredPri(5 + 20 + 20);
486
+ ReactNoop.flushDeferredPri(20 + 5);
487
expect(ops).toEqual([
488
'render: 0',
489
'componentDidMount (before setState): 0',
@@ -496,7 +496,7 @@ describe('ReactIncrementalScheduling', () => {
496
497
ops = [];
498
instance.setState({ tick: 2 });
499
- ReactNoop.flushDeferredPri(5 + 20 + 20);
499
+ ReactNoop.flushDeferredPri(20 + 5);
500
501
expect(ops).toEqual([
502
'render: 2',
@@ -587,4 +587,63 @@ describe('ReactIncrementalScheduling', () => {
587
'componentDidUpdate: 3',
588
]);
589
});
590
+
591
+ it('performs Task work even after time runs out', () => {
592
+ class Foo extends React.Component {
593
+ state = { step: 1 };
594
+ componentDidMount() {
595
+ this.setState({ step: 2 }, () => {
596
+ this.setState({ step: 3 }, () => {
597
+ this.setState({ step: 4 }, () => {
598
+ this.setState({ step: 5 });
599
+ });
600
+ });
601
+ });
602
+ }
603
+ render() {
604
+ return <span prop={this.state.step} />;
605
+ }
606
+ }
607
+ ReactNoop.render(<Foo />);
608
+ // This should be just enough to complete all the work, but not enough to
609
+ // commit it.
610
+ ReactNoop.flushDeferredPri(20);
611
+ expect(ReactNoop.getChildren()).toEqual([]);
612
+
613
+ // Do one more unit of work.
614
+ ReactNoop.flushDeferredPri(10);
615
+ // The updates should all be flushed with Task priority
616
+ expect(ReactNoop.getChildren()).toEqual([span(5)]);
617
+ });
618
+
619
+ it('does not perform animation work after time runs out', () => {
620
+ class Foo extends React.Component {
621
+ state = { step: 1 };
622
+ componentDidMount() {
623
+ ReactNoop.performAnimationWork(() => {
624
+ this.setState({ step: 2 }, () => {
625
+ this.setState({ step: 3 }, () => {
626
+ this.setState({ step: 4 }, () => {
627
+ this.setState({ step: 5 });
628
+ });
629
+ });
630
+ });
631
+ });
632
+ }
633
+ render() {
634
+ return <span prop={this.state.step} />;
635
+ }
636
+ }
637
+ ReactNoop.render(<Foo />);
638
+ // This should be just enough to complete all the work, but not enough to
639
+ // commit it.
640
+ ReactNoop.flushDeferredPri(20);
641
+ expect(ReactNoop.getChildren()).toEqual([]);
642
+
643
+ // Do one more unit of work.
644
+ ReactNoop.flushDeferredPri(10);
645
+ // None of the updates should be flushed because they only have
646
+ // animation priority.
647
+ expect(ReactNoop.getChildren()).toEqual([span(1)]);
648
+ });
649
});