@samitouri / QOS-React / commits / f56eb89389

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 });