react-test-renderer
Version:
React package for snapshot testing.
1,751 lines (1,441 loc) • 538 kB
JavaScript
/** @license React v16.13.1
* react-test-renderer.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';
if (process.env.NODE_ENV !== "production") {
(function() {
'use strict';
var _assign = require('object-assign');
var Scheduler = require('scheduler/unstable_mock');
var React = require('react');
var checkPropTypes = require('prop-types/checkPropTypes');
var Scheduler$1 = require('scheduler');
var tracing = require('scheduler/tracing');
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Prevent newer renderers from RTE when used with older react package versions.
// Current owner and dispatcher used to share the same ref,
// but PR #14548 split them out to better support the react-debug-tools package.
if (!ReactSharedInternals.hasOwnProperty('ReactCurrentDispatcher')) {
ReactSharedInternals.ReactCurrentDispatcher = {
current: null
};
}
if (!ReactSharedInternals.hasOwnProperty('ReactCurrentBatchConfig')) {
ReactSharedInternals.ReactCurrentBatchConfig = {
suspense: null
};
}
// by calls to these methods by a Babel plugin.
//
// In PROD (or in packages without access to React internals),
// they are left as they are instead.
function warn(format) {
{
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
printWarning('warn', format, args);
}
}
function error(format) {
{
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
printWarning('error', format, args);
}
}
function printWarning(level, format, args) {
// When changing this logic, you might want to also
// update consoleWithStackDev.www.js as well.
{
var hasExistingStack = args.length > 0 && typeof args[args.length - 1] === 'string' && args[args.length - 1].indexOf('\n in') === 0;
if (!hasExistingStack) {
var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
var stack = ReactDebugCurrentFrame.getStackAddendum();
if (stack !== '') {
format += '%s';
args = args.concat([stack]);
}
}
var argsWithFormat = args.map(function (item) {
return '' + item;
}); // Careful: RN currently depends on this prefix
argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
// breaks IE9: https://github.com/facebook/react/issues/13610
// eslint-disable-next-line react-internal/no-production-logging
Function.prototype.apply.call(console[level], 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 FunctionComponent = 0;
var ClassComponent = 1;
var IndeterminateComponent = 2; // Before we know whether it is function or class
var HostRoot = 3; // Root of a host tree. Could be nested inside another node.
var HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
var HostComponent = 5;
var HostText = 6;
var Fragment = 7;
var Mode = 8;
var ContextConsumer = 9;
var ContextProvider = 10;
var ForwardRef = 11;
var Profiler = 12;
var SuspenseComponent = 13;
var MemoComponent = 14;
var SimpleMemoComponent = 15;
var LazyComponent = 16;
var IncompleteClassComponent = 17;
var DehydratedFragment = 18;
var SuspenseListComponent = 19;
var FundamentalComponent = 20;
var ScopeComponent = 21;
var Block = 22;
/**
* `ReactInstanceMap` maintains a mapping from a public facing stateful
* instance (key) and the internal representation (value). This allows public
* methods to accept the user facing instance as an argument and map them back
* to internal methods.
*
* Note that this module is currently shared and assumed to be stateless.
* If this becomes an actual Map, that will break.
*/
function get(key) {
return key._reactInternalFiber;
}
function set(key, value) {
key._reactInternalFiber = value;
}
// 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; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
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_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;
var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;
var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;
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;
}
var Uninitialized = -1;
var Pending = 0;
var Resolved = 1;
var Rejected = 2;
function refineResolvedLazyComponent(lazyComponent) {
return lazyComponent._status === Resolved ? lazyComponent._result : null;
}
function initializeLazyComponentType(lazyComponent) {
if (lazyComponent._status === Uninitialized) {
lazyComponent._status = Pending;
var ctor = lazyComponent._ctor;
var thenable = ctor();
lazyComponent._result = thenable;
thenable.then(function (moduleObject) {
if (lazyComponent._status === Pending) {
var defaultExport = moduleObject.default;
{
if (defaultExport === undefined) {
error('lazy: Expected the result of a dynamic import() call. ' + 'Instead received: %s\n\nYour code should look like: \n ' + "const MyComponent = lazy(() => import('./MyComponent'))", moduleObject);
}
}
lazyComponent._status = Resolved;
lazyComponent._result = defaultExport;
}
}, function (error) {
if (lazyComponent._status === Pending) {
lazyComponent._status = Rejected;
lazyComponent._result = error;
}
});
}
}
function getWrappedName(outerType, innerType, wrapperName) {
var functionName = innerType.displayName || innerType.name || '';
return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName);
}
function getComponentName(type) {
if (type == null) {
// Host root, text node or just invalid type.
return null;
}
{
if (typeof type.tag === 'number') {
error('Received an unexpected object in getComponentName(). ' + 'This is likely a bug in React. Please file an issue.');
}
}
if (typeof type === 'function') {
return type.displayName || type.name || null;
}
if (typeof type === 'string') {
return type;
}
switch (type) {
case REACT_FRAGMENT_TYPE:
return 'Fragment';
case REACT_PORTAL_TYPE:
return 'Portal';
case REACT_PROFILER_TYPE:
return "Profiler";
case REACT_STRICT_MODE_TYPE:
return 'StrictMode';
case REACT_SUSPENSE_TYPE:
return 'Suspense';
case REACT_SUSPENSE_LIST_TYPE:
return 'SuspenseList';
}
if (typeof type === 'object') {
switch (type.$$typeof) {
case REACT_CONTEXT_TYPE:
return 'Context.Consumer';
case REACT_PROVIDER_TYPE:
return 'Context.Provider';
case REACT_FORWARD_REF_TYPE:
return getWrappedName(type, type.render, 'ForwardRef');
case REACT_MEMO_TYPE:
return getComponentName(type.type);
case REACT_BLOCK_TYPE:
return getComponentName(type.render);
case REACT_LAZY_TYPE:
{
var thenable = type;
var resolvedThenable = refineResolvedLazyComponent(thenable);
if (resolvedThenable) {
return getComponentName(resolvedThenable);
}
break;
}
}
}
return null;
}
// Don't change these two values. They're used by React Dev Tools.
var NoEffect =
/* */
0;
var PerformedWork =
/* */
1; // You can change the rest (and add more).
var Placement =
/* */
2;
var Update =
/* */
4;
var PlacementAndUpdate =
/* */
6;
var Deletion =
/* */
8;
var ContentReset =
/* */
16;
var Callback =
/* */
32;
var DidCapture =
/* */
64;
var Ref =
/* */
128;
var Snapshot =
/* */
256;
var Passive =
/* */
512;
var Hydrating =
/* */
1024;
var HydratingAndUpdate =
/* */
1028; // Passive & Update & Callback & Ref & Snapshot
var LifecycleEffectMask =
/* */
932; // Union of all host effects
var HostEffectMask =
/* */
2047;
var Incomplete =
/* */
2048;
var ShouldCapture =
/* */
4096;
var enableProfilerTimer = true;
var enableFundamentalAPI = false;
var warnAboutStringRefs = false;
var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
function getNearestMountedFiber(fiber) {
var node = fiber;
var nearestMounted = fiber;
if (!fiber.alternate) {
// If there is no alternate, this might be a new tree that isn't inserted
// yet. If it is, then it will have a pending insertion effect on it.
var nextNode = node;
do {
node = nextNode;
if ((node.effectTag & (Placement | Hydrating)) !== NoEffect) {
// This is an insertion or in-progress hydration. The nearest possible
// mounted fiber is the parent but we need to continue to figure out
// if that one is still mounted.
nearestMounted = node.return;
}
nextNode = node.return;
} while (nextNode);
} else {
while (node.return) {
node = node.return;
}
}
if (node.tag === HostRoot) {
// TODO: Check if this was a nested HostRoot when used with
// renderContainerIntoSubtree.
return nearestMounted;
} // If we didn't hit the root, that means that we're in an disconnected tree
// that has been unmounted.
return null;
}
function isFiberMounted(fiber) {
return getNearestMountedFiber(fiber) === fiber;
}
function isMounted(component) {
{
var owner = ReactCurrentOwner.current;
if (owner !== null && owner.tag === ClassComponent) {
var ownerFiber = owner;
var instance = ownerFiber.stateNode;
if (!instance._warnedAboutRefsInRender) {
error('%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', getComponentName(ownerFiber.type) || 'A component');
}
instance._warnedAboutRefsInRender = true;
}
}
var fiber = get(component);
if (!fiber) {
return false;
}
return getNearestMountedFiber(fiber) === fiber;
}
function assertIsMounted(fiber) {
if (!(getNearestMountedFiber(fiber) === fiber)) {
{
throw Error( "Unable to find node on an unmounted component." );
}
}
}
function findCurrentFiberUsingSlowPath(fiber) {
var alternate = fiber.alternate;
if (!alternate) {
// If there is no alternate, then we only need to check if it is mounted.
var nearestMounted = getNearestMountedFiber(fiber);
if (!(nearestMounted !== null)) {
{
throw Error( "Unable to find node on an unmounted component." );
}
}
if (nearestMounted !== fiber) {
return null;
}
return fiber;
} // If we have two possible branches, we'll walk backwards up to the root
// to see what path the root points to. On the way we may hit one of the
// special cases and we'll deal with them.
var a = fiber;
var b = alternate;
while (true) {
var parentA = a.return;
if (parentA === null) {
// We're at the root.
break;
}
var parentB = parentA.alternate;
if (parentB === null) {
// There is no alternate. This is an unusual case. Currently, it only
// happens when a Suspense component is hidden. An extra fragment fiber
// is inserted in between the Suspense fiber and its children. Skip
// over this extra fragment fiber and proceed to the next parent.
var nextParent = parentA.return;
if (nextParent !== null) {
a = b = nextParent;
continue;
} // If there's no parent, we're at the root.
break;
} // If both copies of the parent fiber point to the same child, we can
// assume that the child is current. This happens when we bailout on low
// priority: the bailed out fiber's child reuses the current child.
if (parentA.child === parentB.child) {
var child = parentA.child;
while (child) {
if (child === a) {
// We've determined that A is the current branch.
assertIsMounted(parentA);
return fiber;
}
if (child === b) {
// We've determined that B is the current branch.
assertIsMounted(parentA);
return alternate;
}
child = child.sibling;
} // We should never have an alternate for any mounting node. So the only
// way this could possibly happen is if this was unmounted, if at all.
{
{
throw Error( "Unable to find node on an unmounted component." );
}
}
}
if (a.return !== b.return) {
// The return pointer of A and the return pointer of B point to different
// fibers. We assume that return pointers never criss-cross, so A must
// belong to the child set of A.return, and B must belong to the child
// set of B.return.
a = parentA;
b = parentB;
} else {
// The return pointers point to the same fiber. We'll have to use the
// default, slow path: scan the child sets of each parent alternate to see
// which child belongs to which set.
//
// Search parent A's child set
var didFindChild = false;
var _child = parentA.child;
while (_child) {
if (_child === a) {
didFindChild = true;
a = parentA;
b = parentB;
break;
}
if (_child === b) {
didFindChild = true;
b = parentA;
a = parentB;
break;
}
_child = _child.sibling;
}
if (!didFindChild) {
// Search parent B's child set
_child = parentB.child;
while (_child) {
if (_child === a) {
didFindChild = true;
a = parentB;
b = parentA;
break;
}
if (_child === b) {
didFindChild = true;
b = parentB;
a = parentA;
break;
}
_child = _child.sibling;
}
if (!didFindChild) {
{
throw Error( "Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue." );
}
}
}
}
if (!(a.alternate === b)) {
{
throw Error( "Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue." );
}
}
} // If the root is not a host container, we're in a disconnected tree. I.e.
// unmounted.
if (!(a.tag === HostRoot)) {
{
throw Error( "Unable to find node on an unmounted component." );
}
}
if (a.stateNode.current === a) {
// We've determined that A is the current branch.
return fiber;
} // Otherwise B has to be current branch.
return alternate;
}
function findCurrentHostFiber(parent) {
var currentParent = findCurrentFiberUsingSlowPath(parent);
if (!currentParent) {
return null;
} // Next we'll drill down this component to find the first HostComponent/Text.
var node = currentParent;
while (true) {
if (node.tag === HostComponent || node.tag === HostText) {
return node;
} else if (node.child) {
node.child.return = node;
node = node.child;
continue;
}
if (node === currentParent) {
return null;
}
while (!node.sibling) {
if (!node.return || node.return === currentParent) {
return null;
}
node = node.return;
}
node.sibling.return = node.return;
node = node.sibling;
} // Flow needs the return null here, but ESLint complains about it.
// eslint-disable-next-line no-unreachable
return null;
}
// can re-export everything from this module.
function shim() {
{
{
throw Error( "The current renderer does not support hydration. This error is likely caused by a bug in React. Please file an issue." );
}
}
} // Hydration (when unsupported)
var isSuspenseInstancePending = shim;
var isSuspenseInstanceFallback = shim;
var hydrateTextInstance = shim;
var NO_CONTEXT = {};
var UPDATE_SIGNAL = {};
var nodeToInstanceMap = new WeakMap();
{
Object.freeze(NO_CONTEXT);
Object.freeze(UPDATE_SIGNAL);
}
function getPublicInstance(inst) {
switch (inst.tag) {
case 'INSTANCE':
var createNodeMock = inst.rootContainerInstance.createNodeMock;
var mockNode = createNodeMock({
type: inst.type,
props: inst.props
});
if (typeof mockNode === 'object' && mockNode !== null) {
nodeToInstanceMap.set(mockNode, inst);
}
return mockNode;
default:
return inst;
}
}
function appendChild(parentInstance, child) {
{
if (!Array.isArray(parentInstance.children)) {
error('An invalid container has been provided. ' + 'This may indicate that another renderer is being used in addition to the test renderer. ' + '(For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) ' + 'This is not supported.');
}
}
var index = parentInstance.children.indexOf(child);
if (index !== -1) {
parentInstance.children.splice(index, 1);
}
parentInstance.children.push(child);
}
function insertBefore(parentInstance, child, beforeChild) {
var index = parentInstance.children.indexOf(child);
if (index !== -1) {
parentInstance.children.splice(index, 1);
}
var beforeIndex = parentInstance.children.indexOf(beforeChild);
parentInstance.children.splice(beforeIndex, 0, child);
}
function removeChild(parentInstance, child) {
var index = parentInstance.children.indexOf(child);
parentInstance.children.splice(index, 1);
}
function getRootHostContext(rootContainerInstance) {
return NO_CONTEXT;
}
function getChildHostContext(parentHostContext, type, rootContainerInstance) {
return NO_CONTEXT;
}
function prepareForCommit(containerInfo) {// noop
}
function resetAfterCommit(containerInfo) {// noop
}
function createInstance(type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
var propsToUse = props;
return {
type: type,
props: propsToUse,
isHidden: false,
children: [],
internalInstanceHandle: internalInstanceHandle,
rootContainerInstance: rootContainerInstance,
tag: 'INSTANCE'
};
}
function appendInitialChild(parentInstance, child) {
var index = parentInstance.children.indexOf(child);
if (index !== -1) {
parentInstance.children.splice(index, 1);
}
parentInstance.children.push(child);
}
function prepareUpdate(testElement, type, oldProps, newProps, rootContainerInstance, hostContext) {
return UPDATE_SIGNAL;
}
function shouldSetTextContent(type, props) {
return false;
}
function shouldDeprioritizeSubtree(type, props) {
return false;
}
function createTextInstance(text, rootContainerInstance, hostContext, internalInstanceHandle) {
return {
text: text,
isHidden: false,
tag: 'TEXT'
};
}
var scheduleTimeout = setTimeout;
var cancelTimeout = clearTimeout;
var noTimeout = -1; // -------------------
function commitUpdate(instance, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
instance.type = type;
instance.props = newProps;
}
function commitTextUpdate(textInstance, oldText, newText) {
textInstance.text = newText;
}
function resetTextContent(testElement) {// noop
}
var appendChildToContainer = appendChild;
var insertInContainerBefore = insertBefore;
var removeChildFromContainer = removeChild;
function hideInstance(instance) {
instance.isHidden = true;
}
function hideTextInstance(textInstance) {
textInstance.isHidden = true;
}
function unhideInstance(instance, props) {
instance.isHidden = false;
}
function unhideTextInstance(textInstance, text) {
textInstance.isHidden = false;
}
var BEFORE_SLASH_RE = /^(.*)[\\\/]/;
function describeComponentFrame (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 ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
function describeFiber(fiber) {
switch (fiber.tag) {
case HostRoot:
case HostPortal:
case HostText:
case Fragment:
case ContextProvider:
case ContextConsumer:
return '';
default:
var owner = fiber._debugOwner;
var source = fiber._debugSource;
var name = getComponentName(fiber.type);
var ownerName = null;
if (owner) {
ownerName = getComponentName(owner.type);
}
return describeComponentFrame(name, source, ownerName);
}
}
function getStackByFiberInDevAndProd(workInProgress) {
var info = '';
var node = workInProgress;
do {
info += describeFiber(node);
node = node.return;
} while (node);
return info;
}
var current = null;
var isRendering = false;
function getCurrentFiberOwnerNameInDevOrNull() {
{
if (current === null) {
return null;
}
var owner = current._debugOwner;
if (owner !== null && typeof owner !== 'undefined') {
return getComponentName(owner.type);
}
}
return null;
}
function getCurrentFiberStackInDev() {
{
if (current === null) {
return '';
} // Safe because if current fiber exists, we are reconciling,
// and it is guaranteed to be the work-in-progress version.
return getStackByFiberInDevAndProd(current);
}
}
function resetCurrentFiber() {
{
ReactDebugCurrentFrame.getCurrentStack = null;
current = null;
isRendering = false;
}
}
function setCurrentFiber(fiber) {
{
ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackInDev;
current = fiber;
isRendering = false;
}
}
function setIsRendering(rendering) {
{
isRendering = rendering;
}
}
// Prefix measurements so that it's possible to filter them.
// Longer prefixes are hard to read in DevTools.
var reactEmoji = "\u269B";
var warningEmoji = "\u26D4";
var supportsUserTiming = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function'; // Keep track of current fiber so that we know the path to unwind on pause.
// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them?
var currentFiber = null; // If we're in the middle of user code, which fiber and method is it?
// Reusing `currentFiber` would be confusing for this because user code fiber
// can change during commit phase too, but we don't need to unwind it (since
// lifecycles in the commit phase don't resemble a tree).
var currentPhase = null;
var currentPhaseFiber = null; // Did lifecycle hook schedule an update? This is often a performance problem,
// so we will keep track of it, and include it in the report.
// Track commits caused by cascading updates.
var isCommitting = false;
var hasScheduledUpdateInCurrentCommit = false;
var hasScheduledUpdateInCurrentPhase = false;
var commitCountInCurrentWorkLoop = 0;
var effectCountInCurrentCommit = 0;
// to avoid stretch the commit phase with measurement overhead.
var labelsInCurrentCommit = new Set();
var formatMarkName = function (markName) {
return reactEmoji + " " + markName;
};
var formatLabel = function (label, warning) {
var prefix = warning ? warningEmoji + " " : reactEmoji + " ";
var suffix = warning ? " Warning: " + warning : '';
return "" + prefix + label + suffix;
};
var beginMark = function (markName) {
performance.mark(formatMarkName(markName));
};
var clearMark = function (markName) {
performance.clearMarks(formatMarkName(markName));
};
var endMark = function (label, markName, warning) {
var formattedMarkName = formatMarkName(markName);
var formattedLabel = formatLabel(label, warning);
try {
performance.measure(formattedLabel, formattedMarkName);
} catch (err) {} // If previous mark was missing for some reason, this will throw.
// This could only happen if React crashed in an unexpected place earlier.
// Don't pile on with more errors.
// Clear marks immediately to avoid growing buffer.
performance.clearMarks(formattedMarkName);
performance.clearMeasures(formattedLabel);
};
var getFiberMarkName = function (label, debugID) {
return label + " (#" + debugID + ")";
};
var getFiberLabel = function (componentName, isMounted, phase) {
if (phase === null) {
// These are composite component total time measurements.
return componentName + " [" + (isMounted ? 'update' : 'mount') + "]";
} else {
// Composite component methods.
return componentName + "." + phase;
}
};
var beginFiberMark = function (fiber, phase) {
var componentName = getComponentName(fiber.type) || 'Unknown';
var debugID = fiber._debugID;
var isMounted = fiber.alternate !== null;
var label = getFiberLabel(componentName, isMounted, phase);
if (isCommitting && labelsInCurrentCommit.has(label)) {
// During the commit phase, we don't show duplicate labels because
// there is a fixed overhead for every measurement, and we don't
// want to stretch the commit phase beyond necessary.
return false;
}
labelsInCurrentCommit.add(label);
var markName = getFiberMarkName(label, debugID);
beginMark(markName);
return true;
};
var clearFiberMark = function (fiber, phase) {
var componentName = getComponentName(fiber.type) || 'Unknown';
var debugID = fiber._debugID;
var isMounted = fiber.alternate !== null;
var label = getFiberLabel(componentName, isMounted, phase);
var markName = getFiberMarkName(label, debugID);
clearMark(markName);
};
var endFiberMark = function (fiber, phase, warning) {
var componentName = getComponentName(fiber.type) || 'Unknown';
var debugID = fiber._debugID;
var isMounted = fiber.alternate !== null;
var label = getFiberLabel(componentName, isMounted, phase);
var markName = getFiberMarkName(label, debugID);
endMark(label, markName, warning);
};
var shouldIgnoreFiber = function (fiber) {
// Host components should be skipped in the timeline.
// We could check typeof fiber.type, but does this work with RN?
switch (fiber.tag) {
case HostRoot:
case HostComponent:
case HostText:
case HostPortal:
case Fragment:
case ContextProvider:
case ContextConsumer:
case Mode:
return true;
default:
return false;
}
};
var clearPendingPhaseMeasurement = function () {
if (currentPhase !== null && currentPhaseFiber !== null) {
clearFiberMark(currentPhaseFiber, currentPhase);
}
currentPhaseFiber = null;
currentPhase = null;
hasScheduledUpdateInCurrentPhase = false;
};
var pauseTimers = function () {
// Stops all currently active measurements so that they can be resumed
// if we continue in a later deferred loop from the same unit of work.
var fiber = currentFiber;
while (fiber) {
if (fiber._debugIsCurrentlyTiming) {
endFiberMark(fiber, null, null);
}
fiber = fiber.return;
}
};
var resumeTimersRecursively = function (fiber) {
if (fiber.return !== null) {
resumeTimersRecursively(fiber.return);
}
if (fiber._debugIsCurrentlyTiming) {
beginFiberMark(fiber, null);
}
};
var resumeTimers = function () {
// Resumes all measurements that were active during the last deferred loop.
if (currentFiber !== null) {
resumeTimersRecursively(currentFiber);
}
};
function recordEffect() {
{
effectCountInCurrentCommit++;
}
}
function recordScheduleUpdate() {
{
if (isCommitting) {
hasScheduledUpdateInCurrentCommit = true;
}
if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') {
hasScheduledUpdateInCurrentPhase = true;
}
}
}
function startWorkTimer(fiber) {
{
if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
return;
} // If we pause, this is the fiber to unwind from.
currentFiber = fiber;
if (!beginFiberMark(fiber, null)) {
return;
}
fiber._debugIsCurrentlyTiming = true;
}
}
function cancelWorkTimer(fiber) {
{
if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
return;
} // Remember we shouldn't complete measurement for this fiber.
// Otherwise flamechart will be deep even for small updates.
fiber._debugIsCurrentlyTiming = false;
clearFiberMark(fiber, null);
}
}
function stopWorkTimer(fiber) {
{
if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
return;
} // If we pause, its parent is the fiber to unwind from.
currentFiber = fiber.return;
if (!fiber._debugIsCurrentlyTiming) {
return;
}
fiber._debugIsCurrentlyTiming = false;
endFiberMark(fiber, null, null);
}
}
function stopFailedWorkTimer(fiber) {
{
if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
return;
} // If we pause, its parent is the fiber to unwind from.
currentFiber = fiber.return;
if (!fiber._debugIsCurrentlyTiming) {
return;
}
fiber._debugIsCurrentlyTiming = false;
var warning = fiber.tag === SuspenseComponent ? 'Rendering was suspended' : 'An error was thrown inside this error boundary';
endFiberMark(fiber, null, warning);
}
}
function startPhaseTimer(fiber, phase) {
{
if (!supportsUserTiming) {
return;
}
clearPendingPhaseMeasurement();
if (!beginFiberMark(fiber, phase)) {
return;
}
currentPhaseFiber = fiber;
currentPhase = phase;
}
}
function stopPhaseTimer() {
{
if (!supportsUserTiming) {
return;
}
if (currentPhase !== null && currentPhaseFiber !== null) {
var warning = hasScheduledUpdateInCurrentPhase ? 'Scheduled a cascading update' : null;
endFiberMark(currentPhaseFiber, currentPhase, warning);
}
currentPhase = null;
currentPhaseFiber = null;
}
}
function startWorkLoopTimer(nextUnitOfWork) {
{
currentFiber = nextUnitOfWork;
if (!supportsUserTiming) {
return;
}
commitCountInCurrentWorkLoop = 0; // This is top level call.
// Any other measurements are performed within.
beginMark('(React Tree Reconciliation)'); // Resume any measurements that were in progress during the last loop.
resumeTimers();
}
}
function stopWorkLoopTimer(interruptedBy, didCompleteRoot) {
{
if (!supportsUserTiming) {
return;
}
var warning = null;
if (interruptedBy !== null) {
if (interruptedBy.tag === HostRoot) {
warning = 'A top-level update interrupted the previous render';
} else {
var componentName = getComponentName(interruptedBy.type) || 'Unknown';
warning = "An update to " + componentName + " interrupted the previous render";
}
} else if (commitCountInCurrentWorkLoop > 1) {
warning = 'There were cascading updates';
}
commitCountInCurrentWorkLoop = 0;
var label = didCompleteRoot ? '(React Tree Reconciliation: Completed Root)' : '(React Tree Reconciliation: Yielded)'; // Pause any measurements until the next loop.
pauseTimers();
endMark(label, '(React Tree Reconciliation)', warning);
}
}
function startCommitTimer() {
{
if (!supportsUserTiming) {
return;
}
isCommitting = true;
hasScheduledUpdateInCurrentCommit = false;
labelsInCurrentCommit.clear();
beginMark('(Committing Changes)');
}
}
function stopCommitTimer() {
{
if (!supportsUserTiming) {
return;
}
var warning = null;
if (hasScheduledUpdateInCurrentCommit) {
warning = 'Lifecycle hook scheduled a cascading update';
} else if (commitCountInCurrentWorkLoop > 0) {
warning = 'Caused by a cascading update in earlier commit';
}
hasScheduledUpdateInCurrentCommit = false;
commitCountInCurrentWorkLoop++;
isCommitting = false;
labelsInCurrentCommit.clear();
endMark('(Committing Changes)', '(Committing Changes)', warning);
}
}
function startCommitSnapshotEffectsTimer() {
{
if (!supportsUserTiming) {
return;
}
effectCountInCurrentCommit = 0;
beginMark('(Committing Snapshot Effects)');
}
}
function stopCommitSnapshotEffectsTimer() {
{
if (!supportsUserTiming) {
return;
}
var count = effectCountInCurrentCommit;
effectCountInCurrentCommit = 0;
endMark("(Committing Snapshot Effects: " + count + " Total)", '(Committing Snapshot Effects)', null);
}
}
function startCommitHostEffectsTimer() {
{
if (!supportsUserTiming) {
return;
}
effectCountInCurrentCommit = 0;
beginMark('(Committing Host Effects)');
}
}
function stopCommitHostEffectsTimer() {
{
if (!supportsUserTiming) {
return;
}
var count = effectCountInCurrentCommit;
effectCountInCurrentCommit = 0;
endMark("(Committing Host Effects: " + count + " Total)", '(Committing Host Effects)', null);
}
}
function startCommitLifeCyclesTimer() {
{
if (!supportsUserTiming) {
return;
}
effectCountInCurrentCommit = 0;
beginMark('(Calling Lifecycle Methods)');
}
}
function stopCommitLifeCyclesTimer() {
{
if (!supportsUserTiming) {
return;
}
var count = effectCountInCurrentCommit;
effectCountInCurrentCommit = 0;
endMark("(Calling Lifecycle Methods: " + count + " Total)", '(Calling Lifecycle Methods)', null);
}
}
var valueStack = [];
var fiberStack;
{
fiberStack = [];
}
var index = -1;
function createCursor(defaultValue) {
return {
current: defaultValue
};
}
function pop(cursor, fiber) {
if (index < 0) {
{
error('Unexpected pop.');
}
return;
}
{
if (fiber !== fiberStack[index]) {
error('Unexpected Fiber popped.');
}
}
cursor.current = valueStack[index];
valueStack[index] = null;
{
fiberStack[index] = null;
}
index--;
}
function push(cursor, value, fiber) {
index++;
valueStack[index] = cursor.current;
{
fiberStack[index] = fiber;
}
cursor.current = value;
}
var warnedAboutMissingGetChildContext;
{
warnedAboutMissingGetChildContext = {};
}
var emptyContextObject = {};
{
Object.freeze(emptyContextObject);
} // A cursor to the current merged context object on the stack.
var contextStackCursor = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed.
var didPerformWorkStackCursor = createCursor(false); // Keep track of the previous context object that was on the stack.
// We use this to get access to the parent context after we have already
// pushed the next context provider, and now need to merge their contexts.
var previousContext = emptyContextObject;
function getUnmaskedContext(workInProgress, Component, didPushOwnContextIfProvider) {
{
if (didPushOwnContextIfProvider && isContextProvider(Component)) {
// If the fiber is a context provider itself, when we read its context
// we may have already pushed its own child context on the stack. A context
// provider should not "see" its own child context. Therefore we read the
// previous (parent) context instead for a context provider.
return previousContext;
}
return contextStackCursor.current;
}
}
function cacheContext(workInProgress, unmaskedContext, maskedContext) {
{
var instance = workInProgress.stateNode;
instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
instance.__reactInternalMemoizedMaskedChildContext = maskedContext;
}
}
function getMaskedContext(workInProgress, unmaskedContext) {
{
var type = workInProgress.type;
var contextTypes = type.contextTypes;
if (!contextTypes) {
return emptyContextObject;
} // Avoid recreating masked context unless unmasked context has changed.
// Failing to do this will result in unnecessary calls to componentWillReceiveProps.
// This may trigger infinite loops if componentWillReceiveProps calls setState.
var instance = workInProgress.stateNode;
if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) {
return instance.__reactInternalMemoizedMaskedChildContext;
}
var context = {};
for (var key in contextTypes) {
context[key] = unmaskedContext[key];
}
{
var name = getComponentName(type) || 'Unknown';
checkPropTypes(contextTypes, context, 'context', name, getCurrentFiberStackInDev);
} // Cache unmasked context so we can avoid recreating masked context unless necessary.
// Context is created before the class component is instantiated so check for instance.
if (instance) {
cacheContext(workInProgress, unmaskedContext, context);
}
return context;
}
}
function hasContextChanged() {
{
return didPerformWorkStackCursor.current;
}
}
function isContextProvider(type) {
{
var childContextTypes = type.childContextTypes;
return childContextTypes !== null && childContextTypes !== undefined;
}
}
function popContext(fiber) {
{
pop(didPerformWorkStackCursor, fiber);
pop(contextStackCursor, fiber);
}
}
function popTopLevelContextObject(fiber) {
{
pop(didPerformWorkStackCursor, fiber);
pop(contextStackCursor, fiber);
}
}
function pushTopLevelContextObject(fiber, context, didChange) {
{
if (!(contextStackCursor.current === emptyContextObject)) {
{
throw Error( "Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue." );
}
}
push(contextStackCursor, context, fiber);
push(didPerformWorkStackCursor, didChange, fiber);
}
}
function processChildContext(fiber, type, parentContext) {
{
var instance = fiber.stateNode;
var childContextTypes = type.childContextTypes; // TODO (bvaughn) Replace this behavior with an invariant() in the future.
// It has only been added in Fiber to match the (unintentional) behavior in Stack.
if (typeof instance.getChildContext !== 'function') {
{
var componentName = getComponentName(type) || 'Unknown';
if (!warnedAboutMissingGetChildContext[componentName]) {
warnedAboutMissingGetChildContext[componentName] = true;
error('%s.childContextTypes is specified but there is no getChildContext() method ' + 'on the instance. You can either define getChildContext() on %s or remove ' + 'childContextTypes from it.', componentName, componentName);
}
}
return parentContext;
}
var childContext;
startPhaseTimer(fiber, 'getChildContext');
childContext = instance.getChildContext();
stopPhaseTimer();
for (var contextKey in childContext) {
if (!(contextKey in childContextTypes)) {
{
throw Error( (getComponentName(type) || 'Unknown') + ".getChildContext(): key \"" + contextKey + "\" is not defined in childContextTypes." );
}
}
}
{
var name = getComponentName(type) || 'Unknown';
checkPropTypes(childContextTypes, childContext, 'child context', name, // In practice, there is one case in which we won't get a stack. It's when
// somebody calls unstable_renderSubtreeIntoContainer() and we process
// context from the parent component instance. The stack will be missing
// because it's outside of the reconciliation, and so the pointer has not
// been set. This is rare and doesn't matter. We'll also remove that API.
getCurrentFiberStackInDev);
}
return _assign({}, parentContext, {}, childContext);
}
}
function pushContextProvider(workInProgress) {
{
var instance = workInProgress.stateNode; // We push the context as early as possible to ensure stack integrity.
// If the instance does not exist yet, we will push null at first,
// and replace it on the stack later when invalidating the context.
var memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyContextObject; // Remember the parent context so we can merge with it later.
// Inherit the parent's did-perform-work value to avoid inadvertently blocking updates.
previousContext = contextStackCursor.current;
push(contextStackCursor, memoizedMergedChildContext, workInProgress);
push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress);
return true;
}
}
function invalidateContextProvider(workInProgress, type, didChange) {
{
var instance = workInProgress.stateNode;
if (!instance) {
{
throw Error( "Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue." );
}
}
if (didChange) {
// Merge parent and own context.
// Skip this if we're not updating due to sCU.
// This avoids unnecessarily recomputing memoized values.
var mergedContext = processChildContext(workInProgress, type, previousContext);
instance.__reactInternalMemoizedMergedChildContext = mergedContext; // Replace the old (or empty) context with the new one.
// It is important to unwind the context in the reverse order.
pop(didPerformWorkStackCursor, workInProgress);
pop(contextStackCursor, workInProgress); // Now push the new context and mark that it has changed.
push(contextStackCursor, mergedContext, workInProgress);
push(didPerformWorkStackCursor, didChange, workInProgress);
} else {
pop(didPerformWorkStackCursor, workInProgress);
push(didPerformWorkStackCursor, didChange, workInProgress);
}
}
}
function findCurrentUnmaskedContext(fiber) {
{
// Currently this is only used with renderSubtreeIntoContainer; not sure if it
// makes sense elsewhere
if (!(isFiberMounted(fiber) && fiber.tag === ClassComponent)) {
{
throw Error( "Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue." );
}
}
var node = fiber;
do {
switch (node.tag) {
case HostRoot:
return node.stateNode.context;
case ClassComponent:
{
var Component = node.type;
if (isContextProvider(Component)) {
return node.stateNode.__reactInternalMemoizedMergedChildContext;
}
break;
}
}
node = node.return;
} while (node !== null);
{
{
throw Error( "Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue." );
}
}
}
}
var LegacyRoot = 0;
var BlockingRoot = 1;
var ConcurrentRoot = 2;
var Scheduler_runWithPriority = Scheduler$1.unstable_runWithPriority,
Scheduler_scheduleCallback = Scheduler$1.unstable_scheduleCallback,
Scheduler_cancelCallback = Scheduler$1.unstable_cancelCallback,
Scheduler_shouldYield = Scheduler$1.unstable_shouldYield,
Scheduler_requestPaint = Scheduler$1.unstable_requestPaint,
Scheduler_now = Scheduler$1.unstable_now,
Scheduler_getCurrentPriorityLevel = Scheduler$1.unstable_getCurrentPriorityLevel,
Scheduler_ImmediatePriority = Scheduler$1.unstable_ImmediatePriority,
Scheduler_UserBlockingPriority = Scheduler$1.unstable_UserBlockingPriority,
Scheduler_NormalPriority = Scheduler$1.unstable_NormalPriority,
Scheduler_LowPriority = Scheduler$1.unstable_LowPriority,
Scheduler_IdlePriority = Scheduler$1.unstable_IdlePriority;
{
// Provide explicit error message when production+profiling bundle of e.g.
// react-dom is used with production (non-profiling) bundle of
// scheduler/tracing
if (!(tracing.__interactionsRef != null && tracing.__interactionsRef.current != null)) {
{
throw Error( "It is not supported to run the profiling version of a renderer (for example, `react-dom/profiling`) without also replacing the `scheduler/tracing` module with `scheduler/tracing-profiling`. Your bundler might have a setting for aliasing both modules. Learn more at http://fb.me/react-profiling" );
}
}
}
var fakeCallbackNode = {}; // Except for NoPriority, these correspond to Scheduler priorities. We use
// ascending numbers so we can compare them like numbers. They start at 90 to
// avoid clashing with Scheduler's priorities.
var ImmediatePriority = 99;
var UserBlockingPriority = 98;
var NormalPriority = 97;
var LowPriority = 96;
var IdlePriority = 95; // NoPriority is the absence of priority. Also React-only.
var NoPriority = 90;
var shouldYield = Scheduler_shouldYield;
var requestPaint = // Fall back gracefully if we're running an older version of Scheduler.
Scheduler_requestPaint !== undefined ? Scheduler_requestPaint : function () {};
var syncQueue = null;
var immediateQueueCallbackNode = null;
var isFlushingSyncQueue = false;
var initialTimeMs = Scheduler_now(); // If the initial timestamp is reasonably small, use Scheduler's `now` directly.
// This will be the case for modern browsers that support `performance.now`. In
// older browsers, Scheduler falls back to `Date.now`, which returns a Unix
// timestamp. In that case, subtract the module initialization time to simulate
// the behavior of performance.now and keep our times small enough to fit
// within 32 bits.
// TODO: Consider lifting this into Scheduler.
var now = initialTimeMs < 10000 ? Scheduler_now : function () {
return Scheduler_now() - initialTimeMs;
};
function getCurrentPriorityLevel() {
switch (Scheduler_getCurrentPriorityLevel()) {
case Scheduler_ImmediatePriority:
return ImmediatePriority;
case Scheduler_UserBlockingPriority:
return UserBlockingPriority;
case Scheduler_NormalPriority:
return NormalPriority;
case Scheduler_LowPriority:
return LowPriority;
case Scheduler_IdlePriority:
return IdlePriority;
default:
{
{
throw Error( "Unknown priority level." );
}
}
}
}
function reactPriorityToSchedulerPriority(reactPriorityLevel) {
switch (reactPriorityLevel) {
case ImmediatePriority:
return Scheduler_ImmediatePriority;