From 182642b2ea9073cf036dc9da37d3dadb4b7482be Mon Sep 17 00:00:00 2001 From: Manas Date: Thu, 27 Apr 2017 17:43:03 +0530 Subject: [PATCH] Fiber ReactDOM shouldn't throw on import in Node environment if it's unused (#9389) * Fixes #9102 by fake polyfilling rAF (and rIC) * Ensure we restore globals even if test fails + minor nits * Remove periods --- scripts/fiber/tests-passing.txt | 4 ++ .../shared/ReactDOMFrameScheduling.js | 20 ++++++- .../__tests__/ReactDOMFrameScheduling-test.js | 55 +++++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/renderers/shared/__tests__/ReactDOMFrameScheduling-test.js diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index 927f2489e9..a1be0e38c9 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -1642,6 +1642,10 @@ src/renderers/native/__tests__/ReactNativeMount-test.js * returns the correct instance and calls it in the callback * renders and reorders children +src/renderers/shared/__tests__/ReactDOMFrameScheduling-test.js +* throws when requestAnimationFrame is not polyfilled in the browser +* can import findDOMNode in Node environment + src/renderers/shared/__tests__/ReactDebugTool-test.js * should add and remove hooks * warns once when an error is thrown in hook diff --git a/src/renderers/shared/ReactDOMFrameScheduling.js b/src/renderers/shared/ReactDOMFrameScheduling.js index 17a8749154..e08d430393 100644 --- a/src/renderers/shared/ReactDOMFrameScheduling.js +++ b/src/renderers/shared/ReactDOMFrameScheduling.js @@ -23,11 +23,29 @@ import type {Deadline} from 'ReactFiberReconciler'; var invariant = require('fbjs/lib/invariant'); +var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment'); // TODO: There's no way to cancel these, because Fiber doesn't atm. let rAF: (callback: (time: number) => void) => number; let rIC: (callback: (deadline: Deadline) => void) => number; -if (typeof requestAnimationFrame !== 'function') { + +if (!ExecutionEnvironment.canUseDOM) { + rAF = function(frameCallback: (time: number) => void): number { + setTimeout(frameCallback, 16); + return 0; + }; + + rIC = function(frameCallback: (deadline: Deadline) => void): number { + setTimeout(() => { + frameCallback({ + timeRemaining() { + return Infinity; + }, + }); + }); + return 0; + }; +} else if (typeof requestAnimationFrame !== 'function') { invariant( false, 'React depends on requestAnimationFrame. Make sure that you load a ' + diff --git a/src/renderers/shared/__tests__/ReactDOMFrameScheduling-test.js b/src/renderers/shared/__tests__/ReactDOMFrameScheduling-test.js new file mode 100644 index 0000000000..5a8a532374 --- /dev/null +++ b/src/renderers/shared/__tests__/ReactDOMFrameScheduling-test.js @@ -0,0 +1,55 @@ +/** + * Copyright 2016-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @emails react-core + */ + +'use strict'; + +const ReactDOMFeatureFlags = require('ReactDOMFeatureFlags'); +const describeFiber = ReactDOMFeatureFlags.useFiber ? describe : xdescribe; + +describeFiber('ReactDOMFrameScheduling', () => { + it('throws when requestAnimationFrame is not polyfilled in the browser', () => { + const previousRAF = global.requestAnimationFrame; + try { + global.requestAnimationFrame = undefined; + jest.resetModules(); + expect(() => { + require('ReactDOM'); + }).toThrow( + 'React depends on requestAnimationFrame. Make sure that you load a ' + + 'polyfill in older browsers.', + ); + } finally { + global.requestAnimationFrame = previousRAF; + } + }); + + // We're just testing importing, not using it. + // It is important because even isomorphic components may import it. + it('can import findDOMNode in Node environment', () => { + const previousRAF = global.requestAnimationFrame; + const previousRIC = global.requestIdleCallback; + const prevWindow = global.window; + try { + global.requestAnimationFrame = undefined; + global.requestIdleCallback = undefined; + // Simulate the Node environment: + delete global.window; + jest.resetModules(); + expect(() => { + require('ReactDOM'); + }).not.toThrow(); + } finally { + global.requestAnimationFrame = previousRAF; + global.requestIdleCallback = previousRIC; + global.window = prevWindow; + } + }); +});