UNPKG

react

Version:

React is a JavaScript library for building user interfaces.

1,587 lines (1,370 loc) 101 kB
/** @license React v16.8.0 * react.development.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.React = factory()); }(this, (function () { 'use strict'; // TODO: this is special because it gets imported during build. var ReactVersion = '16.8.0'; // The Symbol used to tag the ReactElement-like types. If there is no native Symbol // nor polyfill, then a plain number is used for performance. var hasSymbol = typeof Symbol === 'function' && Symbol.for; var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7; var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca; var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb; var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc; var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2; var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd; var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf; var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0; var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1; var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3; var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4; var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = '@@iterator'; function getIteratorFn(maybeIterable) { if (maybeIterable === null || typeof maybeIterable !== 'object') { return null; } var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; if (typeof maybeIterator === 'function') { return maybeIterator; } return null; } /* object-assign (c) Sindre Sorhus @license MIT */ /* eslint-disable no-unused-vars */ var getOwnPropertySymbols = Object.getOwnPropertySymbols; var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; function toObject(val) { if (val === null || val === undefined) { throw new TypeError('Object.assign cannot be called with null or undefined'); } return Object(val); } function shouldUseNative() { try { if (!Object.assign) { return false; } // Detect buggy property enumeration order in older V8 versions. // https://bugs.chromium.org/p/v8/issues/detail?id=4118 var test1 = new String('abc'); // eslint-disable-line no-new-wrappers test1[5] = 'de'; if (Object.getOwnPropertyNames(test1)[0] === '5') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test2 = {}; for (var i = 0; i < 10; i++) { test2['_' + String.fromCharCode(i)] = i; } var order2 = Object.getOwnPropertyNames(test2).map(function (n) { return test2[n]; }); if (order2.join('') !== '0123456789') { return false; } // https://bugs.chromium.org/p/v8/issues/detail?id=3056 var test3 = {}; 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { test3[letter] = letter; }); if (Object.keys(Object.assign({}, test3)).join('') !== 'abcdefghijklmnopqrst') { return false; } return true; } catch (err) { // We don't expect any of the above to throw, but better to be safe. return false; } } var objectAssign = shouldUseNative() ? Object.assign : function (target, source) { var from; var to = toObject(target); var symbols; for (var s = 1; s < arguments.length; s++) { from = Object(arguments[s]); for (var key in from) { if (hasOwnProperty.call(from, key)) { to[key] = from[key]; } } if (getOwnPropertySymbols) { symbols = getOwnPropertySymbols(from); for (var i = 0; i < symbols.length; i++) { if (propIsEnumerable.call(from, symbols[i])) { to[symbols[i]] = from[symbols[i]]; } } } } return to; }; /** * Use invariant() to assert state which your program assumes to be true. * * Provide sprintf-style format (only %s is supported) and arguments * to provide information about what broke and what you were * expecting. * * The invariant message will be stripped in production, but the invariant * will remain to ensure logic does not differ in production. */ var validateFormat = function () {}; { validateFormat = function (format) { if (format === undefined) { throw new Error('invariant requires an error message argument'); } }; } function invariant(condition, format, a, b, c, d, e, f) { validateFormat(format); if (!condition) { var error = void 0; if (format === undefined) { error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); } else { var args = [a, b, c, d, e, f]; var argIndex = 0; error = new Error(format.replace(/%s/g, function () { return args[argIndex++]; })); error.name = 'Invariant Violation'; } error.framesToPop = 1; // we don't care about invariant's own frame throw error; } } // Relying on the `invariant()` implementation lets us // preserve the format and params in the www builds. /** * Forked from fbjs/warning: * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js * * Only change is we use console.warn instead of console.error, * and do nothing when 'console' is not supported. * This really simplifies the code. * --- * Similar to invariant but only logs a warning if the condition is not met. * This can be used to log issues in development environments in critical * paths. Removing the logging code for production environments will keep the * same logic and follow the same code paths. */ var lowPriorityWarning = function () {}; { var printWarning = function (format) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } var argIndex = 0; var message = 'Warning: ' + format.replace(/%s/g, function () { return args[argIndex++]; }); if (typeof console !== 'undefined') { console.warn(message); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. throw new Error(message); } catch (x) {} }; lowPriorityWarning = function (condition, format) { if (format === undefined) { throw new Error('`lowPriorityWarning(condition, format, ...args)` requires a warning ' + 'message argument'); } if (!condition) { for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; } printWarning.apply(undefined, [format].concat(args)); } }; } var lowPriorityWarning$1 = lowPriorityWarning; /** * Similar to invariant but only logs a warning if the condition is not met. * This can be used to log issues in development environments in critical * paths. Removing the logging code for production environments will keep the * same logic and follow the same code paths. */ var warningWithoutStack = function () {}; { warningWithoutStack = function (condition, format) { for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } if (format === undefined) { throw new Error('`warningWithoutStack(condition, format, ...args)` requires a warning ' + 'message argument'); } if (args.length > 8) { // Check before the condition to catch violations early. throw new Error('warningWithoutStack() currently supports at most 8 arguments.'); } if (condition) { return; } if (typeof console !== 'undefined') { var argsWithFormat = args.map(function (item) { return '' + item; }); argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it // breaks IE9: https://github.com/facebook/react/issues/13610 Function.prototype.apply.call(console.error, console, argsWithFormat); } try { // --- Welcome to debugging React --- // This error was thrown as a convenience so that you can use this stack // to find the callsite that caused this warning to fire. var argIndex = 0; var message = 'Warning: ' + format.replace(/%s/g, function () { return args[argIndex++]; }); throw new Error(message); } catch (x) {} }; } var warningWithoutStack$1 = warningWithoutStack; var didWarnStateUpdateForUnmountedComponent = {}; function warnNoop(publicInstance, callerName) { { var _constructor = publicInstance.constructor; var componentName = _constructor && (_constructor.displayName || _constructor.name) || 'ReactClass'; var warningKey = componentName + '.' + callerName; if (didWarnStateUpdateForUnmountedComponent[warningKey]) { return; } warningWithoutStack$1(false, "Can't call %s on a component that is not yet mounted. " + 'This is a no-op, but it might indicate a bug in your application. ' + 'Instead, assign to `this.state` directly or define a `state = {};` ' + 'class property with the desired state in the %s component.', callerName, componentName); didWarnStateUpdateForUnmountedComponent[warningKey] = true; } } /** * This is the abstract API for an update queue. */ var ReactNoopUpdateQueue = { /** * Checks whether or not this composite component is mounted. * @param {ReactClass} publicInstance The instance we want to test. * @return {boolean} True if mounted, false otherwise. * @protected * @final */ isMounted: function (publicInstance) { return false; }, /** * Forces an update. This should only be invoked when it is known with * certainty that we are **not** in a DOM transaction. * * You may want to call this when you know that some deeper aspect of the * component's state has changed but `setState` was not called. * * This will not invoke `shouldComponentUpdate`, but it will invoke * `componentWillUpdate` and `componentDidUpdate`. * * @param {ReactClass} publicInstance The instance that should rerender. * @param {?function} callback Called after component is updated. * @param {?string} callerName name of the calling function in the public API. * @internal */ enqueueForceUpdate: function (publicInstance, callback, callerName) { warnNoop(publicInstance, 'forceUpdate'); }, /** * Replaces all of the state. Always use this or `setState` to mutate state. * You should treat `this.state` as immutable. * * There is no guarantee that `this.state` will be immediately updated, so * accessing `this.state` after calling this method may return the old value. * * @param {ReactClass} publicInstance The instance that should rerender. * @param {object} completeState Next state. * @param {?function} callback Called after component is updated. * @param {?string} callerName name of the calling function in the public API. * @internal */ enqueueReplaceState: function (publicInstance, completeState, callback, callerName) { warnNoop(publicInstance, 'replaceState'); }, /** * Sets a subset of the state. This only exists because _pendingState is * internal. This provides a merging strategy that is not available to deep * properties which is confusing. TODO: Expose pendingState or don't use it * during the merge. * * @param {ReactClass} publicInstance The instance that should rerender. * @param {object} partialState Next partial state to be merged with state. * @param {?function} callback Called after component is updated. * @param {?string} Name of the calling function in the public API. * @internal */ enqueueSetState: function (publicInstance, partialState, callback, callerName) { warnNoop(publicInstance, 'setState'); } }; var emptyObject = {}; { Object.freeze(emptyObject); } /** * Base class helpers for the updating state of a component. */ function Component(props, context, updater) { this.props = props; this.context = context; // If a component has string refs, we will assign a different object later. this.refs = emptyObject; // We initialize the default updater but the real one gets injected by the // renderer. this.updater = updater || ReactNoopUpdateQueue; } Component.prototype.isReactComponent = {}; /** * Sets a subset of the state. Always use this to mutate * state. You should treat `this.state` as immutable. * * There is no guarantee that `this.state` will be immediately updated, so * accessing `this.state` after calling this method may return the old value. * * There is no guarantee that calls to `setState` will run synchronously, * as they may eventually be batched together. You can provide an optional * callback that will be executed when the call to setState is actually * completed. * * When a function is provided to setState, it will be called at some point in * the future (not synchronously). It will be called with the up to date * component arguments (state, props, context). These values can be different * from this.* because your function may be called after receiveProps but before * shouldComponentUpdate, and this new state, props, and context will not yet be * assigned to this. * * @param {object|function} partialState Next partial state or function to * produce next partial state to be merged with current state. * @param {?function} callback Called after state is updated. * @final * @protected */ Component.prototype.setState = function (partialState, callback) { !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : void 0; this.updater.enqueueSetState(this, partialState, callback, 'setState'); }; /** * Forces an update. This should only be invoked when it is known with * certainty that we are **not** in a DOM transaction. * * You may want to call this when you know that some deeper aspect of the * component's state has changed but `setState` was not called. * * This will not invoke `shouldComponentUpdate`, but it will invoke * `componentWillUpdate` and `componentDidUpdate`. * * @param {?function} callback Called after update is complete. * @final * @protected */ Component.prototype.forceUpdate = function (callback) { this.updater.enqueueForceUpdate(this, callback, 'forceUpdate'); }; /** * Deprecated APIs. These APIs used to exist on classic React classes but since * we would like to deprecate them, we're not going to move them over to this * modern base class. Instead, we define a getter that warns if it's accessed. */ { var deprecatedAPIs = { isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'], replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).'] }; var defineDeprecationWarning = function (methodName, info) { Object.defineProperty(Component.prototype, methodName, { get: function () { lowPriorityWarning$1(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]); return undefined; } }); }; for (var fnName in deprecatedAPIs) { if (deprecatedAPIs.hasOwnProperty(fnName)) { defineDeprecationWarning(fnName, deprecatedAPIs[fnName]); } } } function ComponentDummy() {} ComponentDummy.prototype = Component.prototype; /** * Convenience component with default shallow equality check for sCU. */ function PureComponent(props, context, updater) { this.props = props; this.context = context; // If a component has string refs, we will assign a different object later. this.refs = emptyObject; this.updater = updater || ReactNoopUpdateQueue; } var pureComponentPrototype = PureComponent.prototype = new ComponentDummy(); pureComponentPrototype.constructor = PureComponent; // Avoid an extra prototype jump for these methods. objectAssign(pureComponentPrototype, Component.prototype); pureComponentPrototype.isPureReactComponent = true; // an immutable object with a single mutable value function createRef() { var refObject = { current: null }; { Object.seal(refObject); } return refObject; } var enableSchedulerDebugging = false; /* eslint-disable no-var */ // TODO: Use symbols? var ImmediatePriority = 1; var UserBlockingPriority = 2; var NormalPriority = 3; var LowPriority = 4; var IdlePriority = 5; // Max 31 bit integer. The max integer size in V8 for 32-bit systems. // Math.pow(2, 30) - 1 // 0b111111111111111111111111111111 var maxSigned31BitInt = 1073741823; // Times out immediately var IMMEDIATE_PRIORITY_TIMEOUT = -1; // Eventually times out var USER_BLOCKING_PRIORITY = 250; var NORMAL_PRIORITY_TIMEOUT = 5000; var LOW_PRIORITY_TIMEOUT = 10000; // Never times out var IDLE_PRIORITY = maxSigned31BitInt; // Callbacks are stored as a circular, doubly linked list. var firstCallbackNode = null; var currentDidTimeout = false; // Pausing the scheduler is useful for debugging. var isSchedulerPaused = false; var currentPriorityLevel = NormalPriority; var currentEventStartTime = -1; var currentExpirationTime = -1; // This is set when a callback is being executed, to prevent re-entrancy. var isExecutingCallback = false; var isHostCallbackScheduled = false; var hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function'; function ensureHostCallbackIsScheduled() { if (isExecutingCallback) { // Don't schedule work yet; wait until the next time we yield. return; } // Schedule the host callback using the earliest expiration in the list. var expirationTime = firstCallbackNode.expirationTime; if (!isHostCallbackScheduled) { isHostCallbackScheduled = true; } else { // Cancel the existing host callback. cancelHostCallback(); } requestHostCallback(flushWork, expirationTime); } function flushFirstCallback() { var flushedNode = firstCallbackNode; // Remove the node from the list before calling the callback. That way the // list is in a consistent state even if the callback throws. var next = firstCallbackNode.next; if (firstCallbackNode === next) { // This is the last callback in the list. firstCallbackNode = null; next = null; } else { var lastCallbackNode = firstCallbackNode.previous; firstCallbackNode = lastCallbackNode.next = next; next.previous = lastCallbackNode; } flushedNode.next = flushedNode.previous = null; // Now it's safe to call the callback. var callback = flushedNode.callback; var expirationTime = flushedNode.expirationTime; var priorityLevel = flushedNode.priorityLevel; var previousPriorityLevel = currentPriorityLevel; var previousExpirationTime = currentExpirationTime; currentPriorityLevel = priorityLevel; currentExpirationTime = expirationTime; var continuationCallback; try { continuationCallback = callback(); } finally { currentPriorityLevel = previousPriorityLevel; currentExpirationTime = previousExpirationTime; } // A callback may return a continuation. The continuation should be scheduled // with the same priority and expiration as the just-finished callback. if (typeof continuationCallback === 'function') { var continuationNode = { callback: continuationCallback, priorityLevel: priorityLevel, expirationTime: expirationTime, next: null, previous: null }; // Insert the new callback into the list, sorted by its expiration. This is // almost the same as the code in `scheduleCallback`, except the callback // is inserted into the list *before* callbacks of equal expiration instead // of after. if (firstCallbackNode === null) { // This is the first callback in the list. firstCallbackNode = continuationNode.next = continuationNode.previous = continuationNode; } else { var nextAfterContinuation = null; var node = firstCallbackNode; do { if (node.expirationTime >= expirationTime) { // This callback expires at or after the continuation. We will insert // the continuation *before* this callback. nextAfterContinuation = node; break; } node = node.next; } while (node !== firstCallbackNode); if (nextAfterContinuation === null) { // No equal or lower priority callback was found, which means the new // callback is the lowest priority callback in the list. nextAfterContinuation = firstCallbackNode; } else if (nextAfterContinuation === firstCallbackNode) { // The new callback is the highest priority callback in the list. firstCallbackNode = continuationNode; ensureHostCallbackIsScheduled(); } var previous = nextAfterContinuation.previous; previous.next = nextAfterContinuation.previous = continuationNode; continuationNode.next = nextAfterContinuation; continuationNode.previous = previous; } } } function flushImmediateWork() { if ( // Confirm we've exited the outer most event handler currentEventStartTime === -1 && firstCallbackNode !== null && firstCallbackNode.priorityLevel === ImmediatePriority) { isExecutingCallback = true; try { do { flushFirstCallback(); } while ( // Keep flushing until there are no more immediate callbacks firstCallbackNode !== null && firstCallbackNode.priorityLevel === ImmediatePriority); } finally { isExecutingCallback = false; if (firstCallbackNode !== null) { // There's still work remaining. Request another callback. ensureHostCallbackIsScheduled(); } else { isHostCallbackScheduled = false; } } } } function flushWork(didTimeout) { // Exit right away if we're currently paused if (enableSchedulerDebugging && isSchedulerPaused) { return; } isExecutingCallback = true; var previousDidTimeout = currentDidTimeout; currentDidTimeout = didTimeout; try { if (didTimeout) { // Flush all the expired callbacks without yielding. while (firstCallbackNode !== null && !(enableSchedulerDebugging && isSchedulerPaused)) { // TODO Wrap in feature flag // Read the current time. Flush all the callbacks that expire at or // earlier than that time. Then read the current time again and repeat. // This optimizes for as few performance.now calls as possible. var currentTime = getCurrentTime(); if (firstCallbackNode.expirationTime <= currentTime) { do { flushFirstCallback(); } while (firstCallbackNode !== null && firstCallbackNode.expirationTime <= currentTime && !(enableSchedulerDebugging && isSchedulerPaused)); continue; } break; } } else { // Keep flushing callbacks until we run out of time in the frame. if (firstCallbackNode !== null) { do { if (enableSchedulerDebugging && isSchedulerPaused) { break; } flushFirstCallback(); } while (firstCallbackNode !== null && !shouldYieldToHost()); } } } finally { isExecutingCallback = false; currentDidTimeout = previousDidTimeout; if (firstCallbackNode !== null) { // There's still work remaining. Request another callback. ensureHostCallbackIsScheduled(); } else { isHostCallbackScheduled = false; } // Before exiting, flush all the immediate work that was scheduled. flushImmediateWork(); } } function unstable_runWithPriority(priorityLevel, eventHandler) { switch (priorityLevel) { case ImmediatePriority: case UserBlockingPriority: case NormalPriority: case LowPriority: case IdlePriority: break; default: priorityLevel = NormalPriority; } var previousPriorityLevel = currentPriorityLevel; var previousEventStartTime = currentEventStartTime; currentPriorityLevel = priorityLevel; currentEventStartTime = getCurrentTime(); try { return eventHandler(); } finally { currentPriorityLevel = previousPriorityLevel; currentEventStartTime = previousEventStartTime; // Before exiting, flush all the immediate work that was scheduled. flushImmediateWork(); } } function unstable_wrapCallback(callback) { var parentPriorityLevel = currentPriorityLevel; return function () { // This is a fork of runWithPriority, inlined for performance. var previousPriorityLevel = currentPriorityLevel; var previousEventStartTime = currentEventStartTime; currentPriorityLevel = parentPriorityLevel; currentEventStartTime = getCurrentTime(); try { return callback.apply(this, arguments); } finally { currentPriorityLevel = previousPriorityLevel; currentEventStartTime = previousEventStartTime; flushImmediateWork(); } }; } function unstable_scheduleCallback(callback, deprecated_options) { var startTime = currentEventStartTime !== -1 ? currentEventStartTime : getCurrentTime(); var expirationTime; if (typeof deprecated_options === 'object' && deprecated_options !== null && typeof deprecated_options.timeout === 'number') { // FIXME: Remove this branch once we lift expiration times out of React. expirationTime = startTime + deprecated_options.timeout; } else { switch (currentPriorityLevel) { case ImmediatePriority: expirationTime = startTime + IMMEDIATE_PRIORITY_TIMEOUT; break; case UserBlockingPriority: expirationTime = startTime + USER_BLOCKING_PRIORITY; break; case IdlePriority: expirationTime = startTime + IDLE_PRIORITY; break; case LowPriority: expirationTime = startTime + LOW_PRIORITY_TIMEOUT; break; case NormalPriority: default: expirationTime = startTime + NORMAL_PRIORITY_TIMEOUT; } } var newNode = { callback: callback, priorityLevel: currentPriorityLevel, expirationTime: expirationTime, next: null, previous: null }; // Insert the new callback into the list, ordered first by expiration, then // by insertion. So the new callback is inserted any other callback with // equal expiration. if (firstCallbackNode === null) { // This is the first callback in the list. firstCallbackNode = newNode.next = newNode.previous = newNode; ensureHostCallbackIsScheduled(); } else { var next = null; var node = firstCallbackNode; do { if (node.expirationTime > expirationTime) { // The new callback expires before this one. next = node; break; } node = node.next; } while (node !== firstCallbackNode); if (next === null) { // No callback with a later expiration was found, which means the new // callback has the latest expiration in the list. next = firstCallbackNode; } else if (next === firstCallbackNode) { // The new callback has the earliest expiration in the entire list. firstCallbackNode = newNode; ensureHostCallbackIsScheduled(); } var previous = next.previous; previous.next = next.previous = newNode; newNode.next = next; newNode.previous = previous; } return newNode; } function unstable_pauseExecution() { isSchedulerPaused = true; } function unstable_continueExecution() { isSchedulerPaused = false; if (firstCallbackNode !== null) { ensureHostCallbackIsScheduled(); } } function unstable_getFirstCallbackNode() { return firstCallbackNode; } function unstable_cancelCallback(callbackNode) { var next = callbackNode.next; if (next === null) { // Already cancelled. return; } if (next === callbackNode) { // This is the only scheduled callback. Clear the list. firstCallbackNode = null; } else { // Remove the callback from its position in the list. if (callbackNode === firstCallbackNode) { firstCallbackNode = next; } var previous = callbackNode.previous; previous.next = next; next.previous = previous; } callbackNode.next = callbackNode.previous = null; } function unstable_getCurrentPriorityLevel() { return currentPriorityLevel; } function unstable_shouldYield() { return !currentDidTimeout && (firstCallbackNode !== null && firstCallbackNode.expirationTime < currentExpirationTime || shouldYieldToHost()); } // The remaining code is essentially a polyfill for requestIdleCallback. It // works by scheduling a requestAnimationFrame, storing the time for the start // of the frame, then scheduling a postMessage which gets scheduled after paint. // Within the postMessage handler do as much work as possible until time + frame // rate. By separating the idle call into a separate event tick we ensure that // layout, paint and other browser work is counted against the available time. // The frame rate is dynamically adjusted. // We capture a local reference to any global, in case it gets polyfilled after // this module is initially evaluated. We want to be using a // consistent implementation. var localDate = Date; // This initialization code may run even on server environments if a component // just imports ReactDOM (e.g. for findDOMNode). Some environments might not // have setTimeout or clearTimeout. However, we always expect them to be defined // on the client. https://github.com/facebook/react/pull/13088 var localSetTimeout = typeof setTimeout === 'function' ? setTimeout : undefined; var localClearTimeout = typeof clearTimeout === 'function' ? clearTimeout : undefined; // We don't expect either of these to necessarily be defined, but we will error // later if they are missing on the client. var localRequestAnimationFrame = typeof requestAnimationFrame === 'function' ? requestAnimationFrame : undefined; var localCancelAnimationFrame = typeof cancelAnimationFrame === 'function' ? cancelAnimationFrame : undefined; var getCurrentTime; // requestAnimationFrame does not run when the tab is in the background. If // we're backgrounded we prefer for that work to happen so that the page // continues to load in the background. So we also schedule a 'setTimeout' as // a fallback. // TODO: Need a better heuristic for backgrounded work. var ANIMATION_FRAME_TIMEOUT = 100; var rAFID; var rAFTimeoutID; var requestAnimationFrameWithTimeout = function (callback) { // schedule rAF and also a setTimeout rAFID = localRequestAnimationFrame(function (timestamp) { // cancel the setTimeout localClearTimeout(rAFTimeoutID); callback(timestamp); }); rAFTimeoutID = localSetTimeout(function () { // cancel the requestAnimationFrame localCancelAnimationFrame(rAFID); callback(getCurrentTime()); }, ANIMATION_FRAME_TIMEOUT); }; if (hasNativePerformanceNow) { var Performance = performance; getCurrentTime = function () { return Performance.now(); }; } else { getCurrentTime = function () { return localDate.now(); }; } var requestHostCallback; var cancelHostCallback; var shouldYieldToHost; var globalValue = null; if (typeof window !== 'undefined') { globalValue = window; } else if (typeof global !== 'undefined') { globalValue = global; } if (globalValue && globalValue._schedMock) { // Dynamic injection, only for testing purposes. var globalImpl = globalValue._schedMock; requestHostCallback = globalImpl[0]; cancelHostCallback = globalImpl[1]; shouldYieldToHost = globalImpl[2]; getCurrentTime = globalImpl[3]; } else if ( // If Scheduler runs in a non-DOM environment, it falls back to a naive // implementation using setTimeout. typeof window === 'undefined' || // Check if MessageChannel is supported, too. typeof MessageChannel !== 'function') { // If this accidentally gets imported in a non-browser environment, e.g. JavaScriptCore, // fallback to a naive implementation. var _callback = null; var _flushCallback = function (didTimeout) { if (_callback !== null) { try { _callback(didTimeout); } finally { _callback = null; } } }; requestHostCallback = function (cb, ms) { if (_callback !== null) { // Protect against re-entrancy. setTimeout(requestHostCallback, 0, cb); } else { _callback = cb; setTimeout(_flushCallback, 0, false); } }; cancelHostCallback = function () { _callback = null; }; shouldYieldToHost = function () { return false; }; } else { if (typeof console !== 'undefined') { // TODO: Remove fb.me link if (typeof localRequestAnimationFrame !== 'function') { console.error("This browser doesn't support requestAnimationFrame. " + 'Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills'); } if (typeof localCancelAnimationFrame !== 'function') { console.error("This browser doesn't support cancelAnimationFrame. " + 'Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills'); } } var scheduledHostCallback = null; var isMessageEventScheduled = false; var timeoutTime = -1; var isAnimationFrameScheduled = false; var isFlushingHostCallback = false; var frameDeadline = 0; // We start out assuming that we run at 30fps but then the heuristic tracking // will adjust this value to a faster fps if we get more frequent animation // frames. var previousFrameTime = 33; var activeFrameTime = 33; shouldYieldToHost = function () { return frameDeadline <= getCurrentTime(); }; // We use the postMessage trick to defer idle work until after the repaint. var channel = new MessageChannel(); var port = channel.port2; channel.port1.onmessage = function (event) { isMessageEventScheduled = false; var prevScheduledCallback = scheduledHostCallback; var prevTimeoutTime = timeoutTime; scheduledHostCallback = null; timeoutTime = -1; var currentTime = getCurrentTime(); var didTimeout = false; if (frameDeadline - currentTime <= 0) { // There's no time left in this idle period. Check if the callback has // a timeout and whether it's been exceeded. if (prevTimeoutTime !== -1 && prevTimeoutTime <= currentTime) { // Exceeded the timeout. Invoke the callback even though there's no // time left. didTimeout = true; } else { // No timeout. if (!isAnimationFrameScheduled) { // Schedule another animation callback so we retry later. isAnimationFrameScheduled = true; requestAnimationFrameWithTimeout(animationTick); } // Exit without invoking the callback. scheduledHostCallback = prevScheduledCallback; timeoutTime = prevTimeoutTime; return; } } if (prevScheduledCallback !== null) { isFlushingHostCallback = true; try { prevScheduledCallback(didTimeout); } finally { isFlushingHostCallback = false; } } }; var animationTick = function (rafTime) { if (scheduledHostCallback !== null) { // Eagerly schedule the next animation callback at the beginning of the // frame. If the scheduler queue is not empty at the end of the frame, it // will continue flushing inside that callback. If the queue *is* empty, // then it will exit immediately. Posting the callback at the start of the // frame ensures it's fired within the earliest possible frame. If we // waited until the end of the frame to post the callback, we risk the // browser skipping a frame and not firing the callback until the frame // after that. requestAnimationFrameWithTimeout(animationTick); } else { // No pending work. Exit. isAnimationFrameScheduled = false; return; } var nextFrameTime = rafTime - frameDeadline + activeFrameTime; if (nextFrameTime < activeFrameTime && previousFrameTime < activeFrameTime) { if (nextFrameTime < 8) { // Defensive coding. We don't support higher frame rates than 120hz. // If the calculated frame time gets lower than 8, it is probably a bug. nextFrameTime = 8; } // If one frame goes long, then the next one can be short to catch up. // If two frames are short in a row, then that's an indication that we // actually have a higher frame rate than what we're currently optimizing. // We adjust our heuristic dynamically accordingly. For example, if we're // running on 120hz display or 90hz VR display. // Take the max of the two in case one of them was an anomaly due to // missed frame deadlines. activeFrameTime = nextFrameTime < previousFrameTime ? previousFrameTime : nextFrameTime; } else { previousFrameTime = nextFrameTime; } frameDeadline = rafTime + activeFrameTime; if (!isMessageEventScheduled) { isMessageEventScheduled = true; port.postMessage(undefined); } }; requestHostCallback = function (callback, absoluteTimeout) { scheduledHostCallback = callback; timeoutTime = absoluteTimeout; if (isFlushingHostCallback || absoluteTimeout < 0) { // Don't wait for the next frame. Continue working ASAP, in a new event. port.postMessage(undefined); } else if (!isAnimationFrameScheduled) { // If rAF didn't already schedule one, we need to schedule a frame. // TODO: If this rAF doesn't materialize because the browser throttles, we // might want to still have setTimeout trigger rIC as a backup to ensure // that we keep performing work. isAnimationFrameScheduled = true; requestAnimationFrameWithTimeout(animationTick); } }; cancelHostCallback = function () { scheduledHostCallback = null; isMessageEventScheduled = false; timeoutTime = -1; }; } // Helps identify side effects in begin-phase lifecycle hooks and setState reducers: // In some cases, StrictMode should also double-render lifecycles. // This can be confusing for tests though, // And it can be bad for performance in production. // This feature flag can be used to control the behavior: // To preserve the "Pause on caught exceptions" behavior of the debugger, we // replay the begin phase of a failed component inside invokeGuardedCallback. // Warn about deprecated, async-unsafe lifecycles; relates to RFC #6: // Gather advanced timing metrics for Profiler subtrees. // Trace which interactions trigger each commit. var enableSchedulerTracing = true; // Only used in www builds. // TODO: true? Here it might just be false. // Only used in www builds. // Only used in www builds. // React Fire: prevent the value and checked attributes from syncing // with their related DOM properties // These APIs will no longer be "unstable" in the upcoming 16.7 release, // Control this behavior with a flag to support 16.6 minor releases in the meanwhile. var enableStableConcurrentModeAPIs = false; var DEFAULT_THREAD_ID = 0; // Counters used to generate unique IDs. var interactionIDCounter = 0; var threadIDCounter = 0; // Set of currently traced interactions. // Interactions "stack"– // Meaning that newly traced interactions are appended to the previously active set. // When an interaction goes out of scope, the previous set (if any) is restored. var interactionsRef = null; // Listener(s) to notify when interactions begin and end. var subscriberRef = null; if (enableSchedulerTracing) { interactionsRef = { current: new Set() }; subscriberRef = { current: null }; } function unstable_clear(callback) { if (!enableSchedulerTracing) { return callback(); } var prevInteractions = interactionsRef.current; interactionsRef.current = new Set(); try { return callback(); } finally { interactionsRef.current = prevInteractions; } } function unstable_getCurrent() { if (!enableSchedulerTracing) { return null; } else { return interactionsRef.current; } } function unstable_getThreadID() { return ++threadIDCounter; } function unstable_trace(name, timestamp, callback) { var threadID = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : DEFAULT_THREAD_ID; if (!enableSchedulerTracing) { return callback(); } var interaction = { __count: 1, id: interactionIDCounter++, name: name, timestamp: timestamp }; var prevInteractions = interactionsRef.current; // Traced interactions should stack/accumulate. // To do that, clone the current interactions. // The previous set will be restored upon completion. var interactions = new Set(prevInteractions); interactions.add(interaction); interactionsRef.current = interactions; var subscriber = subscriberRef.current; var returnValue = void 0; try { if (subscriber !== null) { subscriber.onInteractionTraced(interaction); } } finally { try { if (subscriber !== null) { subscriber.onWorkStarted(interactions, threadID); } } finally { try { returnValue = callback(); } finally { interactionsRef.current = prevInteractions; try { if (subscriber !== null) { subscriber.onWorkStopped(interactions, threadID); } } finally { interaction.__count--; // If no async work was scheduled for this interaction, // Notify subscribers that it's completed. if (subscriber !== null && interaction.__count === 0) { subscriber.onInteractionScheduledWorkCompleted(interaction); } } } } } return returnValue; } function unstable_wrap(callback) { var threadID = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_THREAD_ID; if (!enableSchedulerTracing) { return callback; } var wrappedInteractions = interactionsRef.current; var subscriber = subscriberRef.current; if (subscriber !== null) { subscriber.onWorkScheduled(wrappedInteractions, threadID); } // Update the pending async work count for the current interactions. // Update after calling subscribers in case of error. wrappedInteractions.forEach(function (interaction) { interaction.__count++; }); var hasRun = false; function wrapped() { var prevInteractions = interactionsRef.current; interactionsRef.current = wrappedInteractions; subscriber = subscriberRef.current; try { var returnValue = void 0; try { if (subscriber !== null) { subscriber.onWorkStarted(wrappedInteractions, threadID); } } finally { try { returnValue = callback.apply(undefined, arguments); } finally { interactionsRef.current = prevInteractions; if (subscriber !== null) { subscriber.onWorkStopped(wrappedInteractions, threadID); } } } return returnValue; } finally { if (!hasRun) { // We only expect a wrapped function to be executed once, // But in the event that it's executed more than once– // Only decrement the outstanding interaction counts once. hasRun = true; // Update pending async counts for all wrapped interactions. // If this was the last scheduled async work for any of them, // Mark them as completed. wrappedInteractions.forEach(function (interaction) { interaction.__count--; if (subscriber !== null && interaction.__count === 0) { subscriber.onInteractionScheduledWorkCompleted(interaction); } }); } } } wrapped.cancel = function cancel() { subscriber = subscriberRef.current; try { if (subscriber !== null) { subscriber.onWorkCanceled(wrappedInteractions, threadID); } } finally { // Update pending async counts for all wrapped interactions. // If this was the last scheduled async work for any of them, // Mark them as completed. wrappedInteractions.forEach(function (interaction) { interaction.__count--; if (subscriber && interaction.__count === 0) { subscriber.onInteractionScheduledWorkCompleted(interaction); } }); } }; return wrapped; } var subscribers = null; if (enableSchedulerTracing) { subscribers = new Set(); } function unstable_subscribe(subscriber) { if (enableSchedulerTracing) { subscribers.add(subscriber); if (subscribers.size === 1) { subscriberRef.current = { onInteractionScheduledWorkCompleted: onInteractionScheduledWorkCompleted, onInteractionTraced: onInteractionTraced, onWorkCanceled: onWorkCanceled, onWorkScheduled: onWorkScheduled, onWorkStarted: onWorkStarted, onWorkStopped: onWorkStopped }; } } } function unstable_unsubscribe(subscriber) { if (enableSchedulerTracing) { subscribers.delete(subscriber); if (subscribers.size === 0) { subscriberRef.current = null; } } } function onInteractionTraced(interaction) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onInteractionTraced(interaction); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onInteractionScheduledWorkCompleted(interaction) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onInteractionScheduledWorkCompleted(interaction); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onWorkScheduled(interactions, threadID) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onWorkScheduled(interactions, threadID); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onWorkStarted(interactions, threadID) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onWorkStarted(interactions, threadID); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onWorkStopped(interactions, threadID) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onWorkStopped(interactions, threadID); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } function onWorkCanceled(interactions, threadID) { var didCatchError = false; var caughtError = null; subscribers.forEach(function (subscriber) { try { subscriber.onWorkCanceled(interactions, threadID); } catch (error) { if (!didCatchError) { didCatchError = true; caughtError = error; } } }); if (didCatchError) { throw caughtError; } } /** * Keeps track of the current dispatcher. */ var ReactCurrentDispatcher = { /** * @internal * @type {ReactComponent} */ current: null }; /** * Keeps track of the current owner. * * The current owner is the component who should own any components that are * currently being constructed. */ var ReactCurrentOwner = { /** * @internal * @type {ReactComponent} */ current: null }; var BEFORE_SLASH_RE = /^(.*)[\\\/]/; var describeComponentFrame = function (name, source, ownerName) { var sourceInfo = ''; if (source) { var path = source.fileName; var fileName = path.replace(BEFORE_SLASH_RE, ''); { // In DEV, include code for a common special case: // prefer "folder/index.js" instead of just "index.js". if (/^index\./.test(fileName)) { var match = path.match(BEFORE_SLASH_RE); if (match) { var pathBeforeSlash = match[1]; if (pathBeforeSlash) { var folderName = pathBeforeSlash.replace(BEFORE_SLASH_RE, ''); fileName = folderName + '/' + fileName; } } } } sourceInfo = ' (at ' + fileName + ':' + source.lineNumber + ')'; } else if (ownerName) { sourceInfo = ' (created by ' + ownerName + ')'; } return '\n in ' + (name || 'Unknown') + sourceInfo; }; var Resolved = 1; function refineResolvedLazyComponent(lazyComponent) { return lazyComponent._status === Resolved ?