@samitouri / QOS-React-2 / commits / 2d68bd0960

Fix message loop behavior when host callback is cancelled (#16407)

* Add a regression test for cancelCallback with message loop * If there's nothing scheduled, we're not running * Add more tests from #16271

Dan Abramov committed Aug 19, 2019 at 21:20 UTC 2d68bd09603fc54d927240003810db9aa6f2e3e5
2 files changed +74 -1
packages/scheduler/src/__tests__/SchedulerBrowser-test.internal.js
+72 -1
@@ -15,6 +15,7 @@
15 let Scheduler;
16 let runtime;
17 let performance;
18 +let cancelCallback;
19 let scheduleCallback;
20 let NormalPriority;
21
@@ -52,6 +53,7 @@ describe('SchedulerBrowser', () => {
53 performance = window.performance;
54 require('scheduler/src/SchedulerFeatureFlags').enableMessageLoopImplementation = enableMessageLoopImplementation;
55 Scheduler = require('scheduler');
56 + cancelCallback = Scheduler.unstable_cancelCallback;
57 scheduleCallback = Scheduler.unstable_scheduleCallback;
58 NormalPriority = Scheduler.unstable_NormalPriority;
59 });
@@ -360,6 +362,15 @@ describe('SchedulerBrowser', () => {
362 const enableMessageLoopImplementation = true;
363 beforeAndAfterHooks(enableMessageLoopImplementation);
364
365 + it('task that finishes before deadline', () => {
366 + scheduleCallback(NormalPriority, () => {
367 + runtime.log('Task');
368 + });
369 + runtime.assertLog(['Post Message']);
370 + runtime.fireMessageEvent();
371 + runtime.assertLog(['Message Event', 'Task']);
372 + });
373 +
374 it('task with continutation', () => {
375 scheduleCallback(NormalPriority, () => {
376 runtime.log('Task');
@@ -385,7 +396,48 @@ describe('SchedulerBrowser', () => {
396 runtime.assertLog(['Message Event', 'Continuation']);
397 });
398
388 - it('task that throws', () => {
399 + it('multiple tasks', () => {
400 + scheduleCallback(NormalPriority, () => {
401 + runtime.log('A');
402 + });
403 + scheduleCallback(NormalPriority, () => {
404 + runtime.log('B');
405 + });
406 + runtime.assertLog(['Post Message']);
407 + runtime.fireMessageEvent();
408 + runtime.assertLog(['Message Event', 'A', 'B']);
409 + });
410 +
411 + it('multiple tasks with a yield in between', () => {
412 + scheduleCallback(NormalPriority, () => {
413 + runtime.log('A');
414 + runtime.advanceTime(4999);
415 + });
416 + scheduleCallback(NormalPriority, () => {
417 + runtime.log('B');
418 + });
419 + runtime.assertLog(['Post Message']);
420 + runtime.fireMessageEvent();
421 + runtime.assertLog([
422 + 'Message Event',
423 + 'A',
424 + // Ran out of time. Post a continuation event.
425 + 'Post Message',
426 + ]);
427 + runtime.fireMessageEvent();
428 + runtime.assertLog(['Message Event', 'B']);
429 + });
430 +
431 + it('cancels tasks', () => {
432 + const task = scheduleCallback(NormalPriority, () => {
433 + runtime.log('Task');
434 + });
435 + runtime.assertLog(['Post Message']);
436 + cancelCallback(task);
437 + runtime.assertLog([]);
438 + });
439 +
440 + it('throws when a task errors then continues in a new event', () => {
441 scheduleCallback(NormalPriority, () => {
442 runtime.log('Oops!');
443 throw Error('Oops!');
@@ -418,5 +470,24 @@ describe('SchedulerBrowser', () => {
470 runtime.fireMessageEvent();
471 runtime.assertLog(['Message Event', 'B']);
472 });
473 +
474 + it('schedule new task after a cancellation', () => {
475 + let handle = scheduleCallback(NormalPriority, () => {
476 + runtime.log('A');
477 + });
478 +
479 + runtime.assertLog(['Post Message']);
480 + cancelCallback(handle);
481 +
482 + runtime.fireMessageEvent();
483 + runtime.assertLog(['Message Event']);
484 +
485 + scheduleCallback(NormalPriority, () => {
486 + runtime.log('B');
487 + });
488 + runtime.assertLog(['Post Message']);
489 + runtime.fireMessageEvent();
490 + runtime.assertLog(['Message Event', 'B']);
491 + });
492 });
493 });
packages/scheduler/src/forks/SchedulerHostConfig.default.js
+2
@@ -235,6 +235,8 @@ if (
235 port.postMessage(null);
236 throw error;
237 }
238 + } else {
239 + isMessageLoopRunning = false;
240 }
241 // Yielding to the browser will give it a chance to paint, so we can
242 // reset this.