[scheduler] Remove window.postMessage fallback
Every browser we can about supports MessageChannel. The ones we don't care about will fallback to the setTimeout implementation.
Andrew Clark committed
Nov 14, 2018 at 14:33 UTC
8feeed10d8f79a0c01ca293890880cbe72b3788d
4 files changed
+17
-47
packages/react-dom/src/__tests__/ReactDOM-test.js
-16
@@ -450,22 +450,6 @@ describe('ReactDOM', () => {
450
}
451
});
452
453
- it('warns when requestAnimationFrame is not polyfilled', () => {
454
- const previousRAF = global.requestAnimationFrame;
455
- try {
456
- delete global.requestAnimationFrame;
457
- jest.resetModules();
458
- spyOnDevAndProd(console, 'error');
459
- require('react-dom');
460
- expect(console.error.calls.count()).toEqual(1);
461
- expect(console.error.calls.argsFor(0)[0]).toMatch(
462
- "This browser doesn't support requestAnimationFrame.",
463
- );
464
- } finally {
465
- global.requestAnimationFrame = previousRAF;
466
- }
467
- });
468
-
453
it('reports stacks with re-entrant renderToString() calls on the client', () => {
454
function Child2(props) {
455
return <span ariaTypo3="no">{props.children}</span>;
packages/scheduler/src/Scheduler.js
+7
-29
@@ -457,9 +457,8 @@ if (typeof window !== 'undefined' && window._schedMock) {
457
// If Scheduler runs in a non-DOM environment, it falls back to a naive
458
// implementation using setTimeout.
459
typeof window === 'undefined' ||
460
- // "addEventListener" might not be available on the window object
461
- // if this is a mocked "window" object. So we need to validate that too.
462
- typeof window.addEventListener !== 'function'
460
+ // Check if MessageChannel is supported, too.
461
+ typeof MessageChannel !== 'function'
462
) {
463
var _callback = null;
464
var _currentTime = -1;
@@ -533,17 +532,9 @@ if (typeof window !== 'undefined' && window._schedMock) {
532
};
533
534
// We use the postMessage trick to defer idle work until after the repaint.
536
- var port = null;
537
- var messageKey =
538
- '__reactIdleCallback$' +
539
- Math.random()
540
- .toString(36)
541
- .slice(2);
542
- var idleTick = function(event) {
543
- if (event.source !== port || event.data !== messageKey) {
544
- return;
545
- }
546
-
535
+ var channel = new MessageChannel();
536
+ var port = channel.port2;
537
+ channel.port1.onmessage = function(event) {
538
isMessageEventScheduled = false;
539
540
var prevScheduledCallback = scheduledHostCallback;
@@ -627,7 +618,7 @@ if (typeof window !== 'undefined' && window._schedMock) {
618
frameDeadline = rafTime + activeFrameTime;
619
if (!isMessageEventScheduled) {
620
isMessageEventScheduled = true;
630
- port.postMessage(messageKey, '*');
621
+ port.postMessage('*');
622
}
623
};
624
@@ -636,7 +627,7 @@ if (typeof window !== 'undefined' && window._schedMock) {
627
timeoutTime = absoluteTimeout;
628
if (isFlushingHostCallback || absoluteTimeout < 0) {
629
// Don't wait for the next frame. Continue working ASAP, in a new event.
639
- port.postMessage(messageKey, '*');
630
+ port.postMessage('*');
631
} else if (!isAnimationFrameScheduled) {
632
// If rAF didn't already schedule one, we need to schedule a frame.
633
// TODO: If this rAF doesn't materialize because the browser throttles, we
@@ -647,19 +638,6 @@ if (typeof window !== 'undefined' && window._schedMock) {
638
}
639
};
640
650
- if (typeof MessageChannel === 'function') {
651
- // Use a MessageChannel, if support exists
652
- var channel = new MessageChannel();
653
- channel.port1.onmessage = idleTick;
654
- port = channel.port2;
655
- } else {
656
- // Otherwise post a message to the window. This isn't ideal because message
657
- // handlers will fire on every frame until the queue is empty, including
658
- // some browser extensions.
659
- window.addEventListener('message', idleTick, false);
660
- port = window;
661
- }
662
-
641
cancelHostCallback = function() {
642
scheduledHostCallback = null;
643
isMessageEventScheduled = false;
packages/scheduler/src/__tests__/SchedulerDOM-test.js
+1
-1
@@ -83,7 +83,7 @@ describe('SchedulerDOM', () => {
83
this.port1 = port1;
84
this.port2 = port2;
85
};
86
- postMessageCallback = event => port1.onmessage(event);
86
+ postMessageCallback = () => port1.onmessage();
87
global.Date.now = function() {
88
return currentTime;
89
};
packages/shared/__tests__/ReactDOMFrameScheduling-test.js
+9
-1
@@ -12,8 +12,15 @@
12
describe('ReactDOMFrameScheduling', () => {
13
it('warns when requestAnimationFrame is not polyfilled in the browser', () => {
14
const previousRAF = global.requestAnimationFrame;
15
+ const previousMessageChannel = global.MessageChannel;
16
try {
16
- global.requestAnimationFrame = undefined;
17
+ delete global.requestAnimationFrame;
18
+ global.MessageChannel = function MessageChannel() {
19
+ return {
20
+ port1: {},
21
+ port2: {},
22
+ };
23
+ };
24
jest.resetModules();
25
spyOnDevAndProd(console, 'error');
26
require('react-dom');
@@ -22,6 +29,7 @@ describe('ReactDOMFrameScheduling', () => {
29
"This browser doesn't support requestAnimationFrame.",
30
);
31
} finally {
32
+ global.MessageChannel = previousMessageChannel;
33
global.requestAnimationFrame = previousRAF;
34
}
35
});