summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/vendor/react-test-renderer.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/vendor/react-test-renderer.js')
-rw-r--r--devtools/client/shared/vendor/react-test-renderer.js10580
1 files changed, 10580 insertions, 0 deletions
diff --git a/devtools/client/shared/vendor/react-test-renderer.js b/devtools/client/shared/vendor/react-test-renderer.js
new file mode 100644
index 0000000000..60f98c8a4f
--- /dev/null
+++ b/devtools/client/shared/vendor/react-test-renderer.js
@@ -0,0 +1,10580 @@
+/** @license React v16.8.6
+ * react-test-renderer.production.min.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.
+ */
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require("resource://devtools/client/shared/vendor/react.js")) :
+ typeof define === 'function' && define.amd ? define(['devtools/client/shared/vendor/react'], factory) :
+ (global.ReactTestRenderer = factory(global.React));
+}(this, (function (React) { 'use strict';
+
+/**
+ * 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.
+ */
+
+function invariant(condition, format, a, b, c, d, e, f) {
+ 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.
+/**
+ * WARNING: DO NOT manually require this module.
+ * This is a replacement for `invariant(...)` used by the error code system
+ * and will _only_ be required by the corresponding babel pass.
+ * It always throws.
+ */
+function reactProdInvariant(code) {
+ var argCount = arguments.length - 1;
+ var url = 'https://reactjs.org/docs/error-decoder.html?invariant=' + code;
+ for (var argIdx = 0; argIdx < argCount; argIdx++) {
+ url += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);
+ }
+ // Rename it so that our build transform doesn't attempt
+ // to replace this invariant() call with reactProdInvariant().
+ var i = invariant;
+ i(false,
+ // The error code is intentionally part of the message (and
+ // not the format argument) so that we could deduplicate
+ // different errors in logs based on the code.
+ 'Minified React error #' + code + '; visit %s ' + 'for the full message or use the non-minified dev environment ' + 'for full errors and additional helpful warnings. ', url);
+}
+
+var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+var _assign = ReactInternals.assign;
+
+/**
+ * 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.
+ */
+
+/**
+ * `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.
+ */
+
+/**
+ * This API should be called `delete` but we'd have to make sure to always
+ * transform these to strings for IE support. When this transform is fully
+ * supported we can rename it.
+ */
+
+
+function get(key) {
+ return key._reactInternalFiber;
+}
+
+
+
+function set(key, value) {
+ key._reactInternalFiber = value;
+}
+
+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
+ };
+}
+
+// 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;
+}
+
+var Pending = 0;
+var Resolved = 1;
+var Rejected = 2;
+
+function refineResolvedLazyComponent(lazyComponent) {
+ return lazyComponent._status === Resolved ? lazyComponent._result : null;
+}
+
+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 === 'function') {
+ return type.displayName || type.name || null;
+ }
+ if (typeof type === 'string') {
+ return type;
+ }
+ switch (type) {
+ case REACT_CONCURRENT_MODE_TYPE:
+ return 'ConcurrentMode';
+ 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';
+ }
+ 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_LAZY_TYPE:
+ {
+ var thenable = type;
+ var resolvedThenable = refineResolvedLazyComponent(thenable);
+ if (resolvedThenable) {
+ return getComponentName(resolvedThenable);
+ }
+ }
+ }
+ }
+ return null;
+}
+
+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 DehydratedSuspenseComponent = 18;
+
+// 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;
+
+// Passive & Update & Callback & Ref & Snapshot
+var LifecycleEffectMask = /* */932;
+
+// Union of all host effects
+var HostEffectMask = /* */1023;
+
+var Incomplete = /* */1024;
+var ShouldCapture = /* */2048;
+
+var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
+
+var MOUNTING = 1;
+var MOUNTED = 2;
+var UNMOUNTED = 3;
+
+function isFiberMountedImpl(fiber) {
+ var node = 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.
+ if ((node.effectTag & Placement) !== NoEffect) {
+ return MOUNTING;
+ }
+ while (node.return) {
+ node = node.return;
+ if ((node.effectTag & Placement) !== NoEffect) {
+ return MOUNTING;
+ }
+ }
+ } else {
+ while (node.return) {
+ node = node.return;
+ }
+ }
+ if (node.tag === HostRoot) {
+ // TODO: Check if this was a nested HostRoot when used with
+ // renderContainerIntoSubtree.
+ return MOUNTED;
+ }
+ // If we didn't hit the root, that means that we're in an disconnected tree
+ // that has been unmounted.
+ return UNMOUNTED;
+}
+
+function isFiberMounted(fiber) {
+ return isFiberMountedImpl(fiber) === MOUNTED;
+}
+
+function isMounted(component) {
+ var fiber = get(component);
+ if (!fiber) {
+ return false;
+ }
+ return isFiberMountedImpl(fiber) === MOUNTED;
+}
+
+function assertIsMounted(fiber) {
+ !(isFiberMountedImpl(fiber) === MOUNTED) ? reactProdInvariant('188') : void 0;
+}
+
+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 state = isFiberMountedImpl(fiber);
+ !(state !== UNMOUNTED) ? reactProdInvariant('188') : void 0;
+ if (state === MOUNTING) {
+ 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;
+ var parentB = parentA ? parentA.alternate : null;
+ if (!parentA || !parentB) {
+ // 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.
+ reactProdInvariant('188');
+ }
+
+ 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;
+ }
+ !didFindChild ? reactProdInvariant('189') : void 0;
+ }
+ }
+
+ !(a.alternate === b) ? reactProdInvariant('190') : void 0;
+ }
+ // If the root is not a host container, we're in a disconnected tree. I.e.
+ // unmounted.
+ !(a.tag === HostRoot) ? reactProdInvariant('188') : void 0;
+ 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;
+}
+
+// Current virtual time
+var nowImplementation = function () {
+ return 0;
+};
+var scheduledCallback = null;
+var yieldedValues = [];
+
+var didStop = false;
+var expectedNumberOfYields = -1;
+
+function scheduleDeferredCallback$1(callback, options) {
+ scheduledCallback = callback;
+ var fakeCallbackId = 0;
+ return fakeCallbackId;
+}
+
+function cancelDeferredCallback$1(timeoutID) {
+ scheduledCallback = null;
+}
+
+function setNowImplementation(implementation) {
+ nowImplementation = implementation;
+}
+
+function shouldYield$1() {
+ if (expectedNumberOfYields !== -1 && yieldedValues.length >= expectedNumberOfYields) {
+ // We yielded at least as many values as expected. Stop rendering.
+ didStop = true;
+ return true;
+ }
+ // Keep rendering.
+ return false;
+}
+
+function flushAll() {
+ yieldedValues = [];
+ while (scheduledCallback !== null) {
+ var cb = scheduledCallback;
+ scheduledCallback = null;
+ cb();
+ }
+ var values = yieldedValues;
+ yieldedValues = [];
+ return values;
+}
+
+function flushNumberOfYields(count) {
+ expectedNumberOfYields = count;
+ didStop = false;
+ yieldedValues = [];
+ try {
+ while (scheduledCallback !== null && !didStop) {
+ var cb = scheduledCallback;
+ scheduledCallback = null;
+ cb();
+ }
+ return yieldedValues;
+ } finally {
+ expectedNumberOfYields = -1;
+ didStop = false;
+ yieldedValues = [];
+ }
+}
+
+function yieldValue(value) {
+ yieldedValues.push(value);
+}
+
+function clearYields() {
+ var values = yieldedValues;
+ yieldedValues = [];
+ return values;
+}
+
+// Renderers that don't support persistence
+// can re-export everything from this module.
+
+function shim() {
+ reactProdInvariant('270');
+}
+
+// Persistence (when unsupported)
+var supportsPersistence = false;
+var cloneInstance = shim;
+var createContainerChildSet = shim;
+var appendChildToContainerChildSet = shim;
+var finalizeContainerChildren = shim;
+var replaceContainerChildren = shim;
+var cloneHiddenInstance = shim;
+var cloneUnhiddenInstance = shim;
+var createHiddenTextInstance = shim;
+
+// Renderers that don't support hydration
+// can re-export everything from this module.
+
+function shim$1() {
+ reactProdInvariant('305');
+}
+
+// Hydration (when unsupported)
+
+var supportsHydration = false;
+var canHydrateInstance = shim$1;
+var canHydrateTextInstance = shim$1;
+var canHydrateSuspenseInstance = shim$1;
+var getNextHydratableSibling = shim$1;
+var getFirstHydratableChild = shim$1;
+var hydrateInstance = shim$1;
+var hydrateTextInstance = shim$1;
+var getNextHydratableInstanceAfterSuspenseInstance = shim$1;
+var clearSuspenseBoundary = shim$1;
+var clearSuspenseBoundaryFromContainer = shim$1;
+
+var NO_CONTEXT = {};
+var UPDATE_SIGNAL = {};
+function getPublicInstance(inst) {
+ switch (inst.tag) {
+ case 'INSTANCE':
+ var _createNodeMock = inst.rootContainerInstance.createNodeMock;
+ return _createNodeMock({
+ type: inst.type,
+ props: inst.props
+ });
+ default:
+ return inst;
+ }
+}
+
+function appendChild(parentInstance, child) {
+ 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) {
+ return {
+ type: type,
+ props: props,
+ isHidden: false,
+ children: [],
+ 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 finalizeInitialChildren(testElement, type, props, rootContainerInstance, hostContext) {
+ return false;
+}
+
+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 isPrimaryRenderer = false;
+// This approach enables `now` to be mocked by tests,
+// Even after the reconciler has initialized and read host config values.
+var now = function () {
+ return nowImplementation();
+};
+var scheduleDeferredCallback$$1 = scheduleDeferredCallback$1;
+var cancelDeferredCallback$$1 = cancelDeferredCallback$1;
+var shouldYield$$1 = shouldYield$1;
+
+var scheduleTimeout = setTimeout;
+var cancelTimeout = clearTimeout;
+var noTimeout = -1;
+var schedulePassiveEffects = scheduleDeferredCallback$$1;
+var cancelPassiveEffects = cancelDeferredCallback$$1;
+
+// -------------------
+// Mutation
+// -------------------
+
+var supportsMutation = true;
+
+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;
+}
+
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+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, '');
+ 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 enableUserTimingAPI = false;
+
+
+var enableProfilerTimer = false;
+var enableSchedulerTracing = false;
+var enableSuspenseServerRenderer = false;
+
+
+
+
+
+// Only used in www builds.
+
+// 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;
+var isWaitingForCallback = false;
+// During commits, we only show a measurement once per method name
+// 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() {
+ if (enableUserTimingAPI) {
+ effectCountInCurrentCommit++;
+ }
+}
+
+function recordScheduleUpdate() {
+ if (enableUserTimingAPI) {
+ if (isCommitting) {
+ hasScheduledUpdateInCurrentCommit = true;
+ }
+ if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') {
+ hasScheduledUpdateInCurrentPhase = true;
+ }
+ }
+}
+
+function startRequestCallbackTimer() {
+ if (enableUserTimingAPI) {
+ if (supportsUserTiming && !isWaitingForCallback) {
+ isWaitingForCallback = true;
+ beginMark('(Waiting for async callback...)');
+ }
+ }
+}
+
+function stopRequestCallbackTimer(didExpire, expirationTime) {
+ if (enableUserTimingAPI) {
+ if (supportsUserTiming) {
+ isWaitingForCallback = false;
+ var warning = didExpire ? 'React was blocked by main thread' : null;
+ endMark('(Waiting for async callback... will force flush in ' + expirationTime + ' ms)', '(Waiting for async callback...)', warning);
+ }
+ }
+}
+
+function startWorkTimer(fiber) {
+ if (enableUserTimingAPI) {
+ 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 (enableUserTimingAPI) {
+ 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 (enableUserTimingAPI) {
+ 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 (enableUserTimingAPI) {
+ 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 || fiber.tag === DehydratedSuspenseComponent ? 'Rendering was suspended' : 'An error was thrown inside this error boundary';
+ endFiberMark(fiber, null, warning);
+ }
+}
+
+function startPhaseTimer(fiber, phase) {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ clearPendingPhaseMeasurement();
+ if (!beginFiberMark(fiber, phase)) {
+ return;
+ }
+ currentPhaseFiber = fiber;
+ currentPhase = phase;
+ }
+}
+
+function stopPhaseTimer() {
+ if (enableUserTimingAPI) {
+ 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) {
+ if (enableUserTimingAPI) {
+ 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 (enableUserTimingAPI) {
+ 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 (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ isCommitting = true;
+ hasScheduledUpdateInCurrentCommit = false;
+ labelsInCurrentCommit.clear();
+ beginMark('(Committing Changes)');
+ }
+}
+
+function stopCommitTimer() {
+ if (enableUserTimingAPI) {
+ 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 (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ effectCountInCurrentCommit = 0;
+ beginMark('(Committing Snapshot Effects)');
+ }
+}
+
+function stopCommitSnapshotEffectsTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ var count = effectCountInCurrentCommit;
+ effectCountInCurrentCommit = 0;
+ endMark('(Committing Snapshot Effects: ' + count + ' Total)', '(Committing Snapshot Effects)', null);
+ }
+}
+
+function startCommitHostEffectsTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ effectCountInCurrentCommit = 0;
+ beginMark('(Committing Host Effects)');
+ }
+}
+
+function stopCommitHostEffectsTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ var count = effectCountInCurrentCommit;
+ effectCountInCurrentCommit = 0;
+ endMark('(Committing Host Effects: ' + count + ' Total)', '(Committing Host Effects)', null);
+ }
+}
+
+function startCommitLifeCyclesTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ effectCountInCurrentCommit = 0;
+ beginMark('(Calling Lifecycle Methods)');
+ }
+}
+
+function stopCommitLifeCyclesTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ var count = effectCountInCurrentCommit;
+ effectCountInCurrentCommit = 0;
+ endMark('(Calling Lifecycle Methods: ' + count + ' Total)', '(Calling Lifecycle Methods)', null);
+ }
+}
+
+var valueStack = [];
+
+var index = -1;
+
+function createCursor(defaultValue) {
+ return {
+ current: defaultValue
+ };
+}
+
+function pop(cursor, fiber) {
+ if (index < 0) {
+ return;
+ }
+
+ cursor.current = valueStack[index];
+
+ valueStack[index] = null;
+
+ index--;
+}
+
+function push(cursor, value, fiber) {
+ index++;
+
+ valueStack[index] = cursor.current;
+
+ cursor.current = value;
+}
+
+var 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];
+ }
+
+ 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) {
+ !(contextStackCursor.current === emptyContextObject) ? reactProdInvariant('168') : void 0;
+
+ 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') {
+ return parentContext;
+ }
+
+ var childContext = void 0;
+ startPhaseTimer(fiber, 'getChildContext');
+ childContext = instance.getChildContext();
+ stopPhaseTimer();
+ for (var contextKey in childContext) {
+ !(contextKey in childContextTypes) ? reactProdInvariant('108', getComponentName(type) || 'Unknown', contextKey) : void 0;
+ }
+ 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;
+ !instance ? reactProdInvariant('169') : void 0;
+
+ 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
+ !(isFiberMounted(fiber) && fiber.tag === ClassComponent) ? reactProdInvariant('170') : void 0;
+
+ 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);
+ reactProdInvariant('171');
+}
+
+var onCommitFiberRoot = null;
+var onCommitFiberUnmount = null;
+function catchErrors(fn) {
+ return function (arg) {
+ try {
+ return fn(arg);
+ } catch (err) {
+
+ }
+ };
+}
+
+var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined';
+
+function injectInternals(internals) {
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
+ // No DevTools
+ return false;
+ }
+ var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;
+ if (hook.isDisabled) {
+ // This isn't a real property on the hook, but it can be set to opt out
+ // of DevTools integration and associated warnings and logs.
+ // https://github.com/facebook/react/issues/3877
+ return true;
+ }
+ if (!hook.supportsFiber) {
+ return true;
+ }
+ try {
+ var rendererID = hook.inject(internals);
+ // We have successfully injected, so now it is safe to set up hooks.
+ onCommitFiberRoot = catchErrors(function (root) {
+ return hook.onCommitFiberRoot(rendererID, root);
+ });
+ onCommitFiberUnmount = catchErrors(function (fiber) {
+ return hook.onCommitFiberUnmount(rendererID, fiber);
+ });
+ } catch (err) {
+ // Catch all errors because it is unsafe to throw during initialization.
+
+ }
+ // DevTools exists
+ return true;
+}
+
+function onCommitRoot(root) {
+ if (typeof onCommitFiberRoot === 'function') {
+ onCommitFiberRoot(root);
+ }
+}
+
+function onCommitUnmount(fiber) {
+ if (typeof onCommitFiberUnmount === 'function') {
+ onCommitFiberUnmount(fiber);
+ }
+}
+
+// Max 31 bit integer. The max integer size in V8 for 32-bit systems.
+// Math.pow(2, 30) - 1
+// 0b111111111111111111111111111111
+var maxSigned31BitInt = 1073741823;
+
+var NoWork = 0;
+var Never = 1;
+var Sync = maxSigned31BitInt;
+
+var UNIT_SIZE = 10;
+var MAGIC_NUMBER_OFFSET = maxSigned31BitInt - 1;
+
+// 1 unit of expiration time represents 10ms.
+function msToExpirationTime(ms) {
+ // Always add an offset so that we don't clash with the magic number for NoWork.
+ return MAGIC_NUMBER_OFFSET - (ms / UNIT_SIZE | 0);
+}
+
+function expirationTimeToMs(expirationTime) {
+ return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE;
+}
+
+function ceiling(num, precision) {
+ return ((num / precision | 0) + 1) * precision;
+}
+
+function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) {
+ return MAGIC_NUMBER_OFFSET - ceiling(MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE, bucketSizeMs / UNIT_SIZE);
+}
+
+var LOW_PRIORITY_EXPIRATION = 5000;
+var LOW_PRIORITY_BATCH_SIZE = 250;
+
+function computeAsyncExpiration(currentTime) {
+ return computeExpirationBucket(currentTime, LOW_PRIORITY_EXPIRATION, LOW_PRIORITY_BATCH_SIZE);
+}
+
+// We intentionally set a higher expiration time for interactive updates in
+// dev than in production.
+//
+// If the main thread is being blocked so long that you hit the expiration,
+// it's a problem that could be solved with better scheduling.
+//
+// People will be more likely to notice this and fix it with the long
+// expiration time in development.
+//
+// In production we opt for better UX at the risk of masking scheduling
+// problems, by expiring fast.
+var HIGH_PRIORITY_EXPIRATION = 150;
+var HIGH_PRIORITY_BATCH_SIZE = 100;
+
+function computeInteractiveExpiration(currentTime) {
+ return computeExpirationBucket(currentTime, HIGH_PRIORITY_EXPIRATION, HIGH_PRIORITY_BATCH_SIZE);
+}
+
+var NoContext = 0;
+var ConcurrentMode = 1;
+var StrictMode = 2;
+var ProfileMode = 4;
+
+function FiberNode(tag, pendingProps, key, mode) {
+ // Instance
+ this.tag = tag;
+ this.key = key;
+ this.elementType = null;
+ this.type = null;
+ this.stateNode = null;
+
+ // Fiber
+ this.return = null;
+ this.child = null;
+ this.sibling = null;
+ this.index = 0;
+
+ this.ref = null;
+
+ this.pendingProps = pendingProps;
+ this.memoizedProps = null;
+ this.updateQueue = null;
+ this.memoizedState = null;
+ this.contextDependencies = null;
+
+ this.mode = mode;
+
+ // Effects
+ this.effectTag = NoEffect;
+ this.nextEffect = null;
+
+ this.firstEffect = null;
+ this.lastEffect = null;
+
+ this.expirationTime = NoWork;
+ this.childExpirationTime = NoWork;
+
+ this.alternate = null;
+
+ if (enableProfilerTimer) {
+ // Note: The following is done to avoid a v8 performance cliff.
+ //
+ // Initializing the fields below to smis and later updating them with
+ // double values will cause Fibers to end up having separate shapes.
+ // This behavior/bug has something to do with Object.preventExtension().
+ // Fortunately this only impacts DEV builds.
+ // Unfortunately it makes React unusably slow for some applications.
+ // To work around this, initialize the fields below with doubles.
+ //
+ // Learn more about this here:
+ // https://github.com/facebook/react/issues/14365
+ // https://bugs.chromium.org/p/v8/issues/detail?id=8538
+ this.actualDuration = Number.NaN;
+ this.actualStartTime = Number.NaN;
+ this.selfBaseDuration = Number.NaN;
+ this.treeBaseDuration = Number.NaN;
+
+ // It's okay to replace the initial doubles with smis after initialization.
+ // This won't trigger the performance cliff mentioned above,
+ // and it simplifies other profiler code (including DevTools).
+ this.actualDuration = 0;
+ this.actualStartTime = -1;
+ this.selfBaseDuration = 0;
+ this.treeBaseDuration = 0;
+ }
+
+
+}
+
+// This is a constructor function, rather than a POJO constructor, still
+// please ensure we do the following:
+// 1) Nobody should add any instance methods on this. Instance methods can be
+// more difficult to predict when they get optimized and they are almost
+// never inlined properly in static compilers.
+// 2) Nobody should rely on `instanceof Fiber` for type testing. We should
+// always know when it is a fiber.
+// 3) We might want to experiment with using numeric keys since they are easier
+// to optimize in a non-JIT environment.
+// 4) We can easily go from a constructor to a createFiber object literal if that
+// is faster.
+// 5) It should be easy to port this to a C struct and keep a C implementation
+// compatible.
+var createFiber = function (tag, pendingProps, key, mode) {
+ // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
+ return new FiberNode(tag, pendingProps, key, mode);
+};
+
+function shouldConstruct(Component) {
+ var prototype = Component.prototype;
+ return !!(prototype && prototype.isReactComponent);
+}
+
+function isSimpleFunctionComponent(type) {
+ return typeof type === 'function' && !shouldConstruct(type) && type.defaultProps === undefined;
+}
+
+function resolveLazyComponentTag(Component) {
+ if (typeof Component === 'function') {
+ return shouldConstruct(Component) ? ClassComponent : FunctionComponent;
+ } else if (Component !== undefined && Component !== null) {
+ var $$typeof = Component.$$typeof;
+ if ($$typeof === REACT_FORWARD_REF_TYPE) {
+ return ForwardRef;
+ }
+ if ($$typeof === REACT_MEMO_TYPE) {
+ return MemoComponent;
+ }
+ }
+ return IndeterminateComponent;
+}
+
+// This is used to create an alternate fiber to do work on.
+function createWorkInProgress(current, pendingProps, expirationTime) {
+ var workInProgress = current.alternate;
+ if (workInProgress === null) {
+ // We use a double buffering pooling technique because we know that we'll
+ // only ever need at most two versions of a tree. We pool the "other" unused
+ // node that we're free to reuse. This is lazily created to avoid allocating
+ // extra objects for things that are never updated. It also allow us to
+ // reclaim the extra memory if needed.
+ workInProgress = createFiber(current.tag, pendingProps, current.key, current.mode);
+ workInProgress.elementType = current.elementType;
+ workInProgress.type = current.type;
+ workInProgress.stateNode = current.stateNode;
+
+ workInProgress.alternate = current;
+ current.alternate = workInProgress;
+ } else {
+ workInProgress.pendingProps = pendingProps;
+
+ // We already have an alternate.
+ // Reset the effect tag.
+ workInProgress.effectTag = NoEffect;
+
+ // The effect list is no longer valid.
+ workInProgress.nextEffect = null;
+ workInProgress.firstEffect = null;
+ workInProgress.lastEffect = null;
+
+ if (enableProfilerTimer) {
+ // We intentionally reset, rather than copy, actualDuration & actualStartTime.
+ // This prevents time from endlessly accumulating in new commits.
+ // This has the downside of resetting values for different priority renders,
+ // But works for yielding (the common case) and should support resuming.
+ workInProgress.actualDuration = 0;
+ workInProgress.actualStartTime = -1;
+ }
+ }
+
+ workInProgress.childExpirationTime = current.childExpirationTime;
+ workInProgress.expirationTime = current.expirationTime;
+
+ workInProgress.child = current.child;
+ workInProgress.memoizedProps = current.memoizedProps;
+ workInProgress.memoizedState = current.memoizedState;
+ workInProgress.updateQueue = current.updateQueue;
+ workInProgress.contextDependencies = current.contextDependencies;
+
+ // These will be overridden during the parent's reconciliation
+ workInProgress.sibling = current.sibling;
+ workInProgress.index = current.index;
+ workInProgress.ref = current.ref;
+
+ if (enableProfilerTimer) {
+ workInProgress.selfBaseDuration = current.selfBaseDuration;
+ workInProgress.treeBaseDuration = current.treeBaseDuration;
+ }
+
+ return workInProgress;
+}
+
+function createHostRootFiber(isConcurrent) {
+ var mode = isConcurrent ? ConcurrentMode | StrictMode : NoContext;
+
+ if (enableProfilerTimer && isDevToolsPresent) {
+ // Always collect profile timings when DevTools are present.
+ // This enables DevTools to start capturing timing at any point–
+ // Without some nodes in the tree having empty base times.
+ mode |= ProfileMode;
+ }
+
+ return createFiber(HostRoot, null, null, mode);
+}
+
+function createFiberFromTypeAndProps(type, // React$ElementType
+key, pendingProps, owner, mode, expirationTime) {
+ var fiber = void 0;
+
+ var fiberTag = IndeterminateComponent;
+ // The resolved type is set if we know what the final type will be. I.e. it's not lazy.
+ var resolvedType = type;
+ if (typeof type === 'function') {
+ if (shouldConstruct(type)) {
+ fiberTag = ClassComponent;
+ }
+ } else if (typeof type === 'string') {
+ fiberTag = HostComponent;
+ } else {
+ getTag: switch (type) {
+ case REACT_FRAGMENT_TYPE:
+ return createFiberFromFragment(pendingProps.children, mode, expirationTime, key);
+ case REACT_CONCURRENT_MODE_TYPE:
+ return createFiberFromMode(pendingProps, mode | ConcurrentMode | StrictMode, expirationTime, key);
+ case REACT_STRICT_MODE_TYPE:
+ return createFiberFromMode(pendingProps, mode | StrictMode, expirationTime, key);
+ case REACT_PROFILER_TYPE:
+ return createFiberFromProfiler(pendingProps, mode, expirationTime, key);
+ case REACT_SUSPENSE_TYPE:
+ return createFiberFromSuspense(pendingProps, mode, expirationTime, key);
+ default:
+ {
+ if (typeof type === 'object' && type !== null) {
+ switch (type.$$typeof) {
+ case REACT_PROVIDER_TYPE:
+ fiberTag = ContextProvider;
+ break getTag;
+ case REACT_CONTEXT_TYPE:
+ // This is a consumer
+ fiberTag = ContextConsumer;
+ break getTag;
+ case REACT_FORWARD_REF_TYPE:
+ fiberTag = ForwardRef;
+ break getTag;
+ case REACT_MEMO_TYPE:
+ fiberTag = MemoComponent;
+ break getTag;
+ case REACT_LAZY_TYPE:
+ fiberTag = LazyComponent;
+ resolvedType = null;
+ break getTag;
+ }
+ }
+ var info = '';
+ reactProdInvariant('130', type == null ? type : typeof type, info);
+ }
+ }
+ }
+
+ fiber = createFiber(fiberTag, pendingProps, key, mode);
+ fiber.elementType = type;
+ fiber.type = resolvedType;
+ fiber.expirationTime = expirationTime;
+
+ return fiber;
+}
+
+function createFiberFromElement(element, mode, expirationTime) {
+ var owner = null;
+ var type = element.type;
+ var key = element.key;
+ var pendingProps = element.props;
+ var fiber = createFiberFromTypeAndProps(type, key, pendingProps, owner, mode, expirationTime);
+ return fiber;
+}
+
+function createFiberFromFragment(elements, mode, expirationTime, key) {
+ var fiber = createFiber(Fragment, elements, key, mode);
+ fiber.expirationTime = expirationTime;
+ return fiber;
+}
+
+function createFiberFromProfiler(pendingProps, mode, expirationTime, key) {
+ var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode);
+ // TODO: The Profiler fiber shouldn't have a type. It has a tag.
+ fiber.elementType = REACT_PROFILER_TYPE;
+ fiber.type = REACT_PROFILER_TYPE;
+ fiber.expirationTime = expirationTime;
+
+ return fiber;
+}
+
+function createFiberFromMode(pendingProps, mode, expirationTime, key) {
+ var fiber = createFiber(Mode, pendingProps, key, mode);
+
+ // TODO: The Mode fiber shouldn't have a type. It has a tag.
+ var type = (mode & ConcurrentMode) === NoContext ? REACT_STRICT_MODE_TYPE : REACT_CONCURRENT_MODE_TYPE;
+ fiber.elementType = type;
+ fiber.type = type;
+
+ fiber.expirationTime = expirationTime;
+ return fiber;
+}
+
+function createFiberFromSuspense(pendingProps, mode, expirationTime, key) {
+ var fiber = createFiber(SuspenseComponent, pendingProps, key, mode);
+
+ // TODO: The SuspenseComponent fiber shouldn't have a type. It has a tag.
+ var type = REACT_SUSPENSE_TYPE;
+ fiber.elementType = type;
+ fiber.type = type;
+
+ fiber.expirationTime = expirationTime;
+ return fiber;
+}
+
+function createFiberFromText(content, mode, expirationTime) {
+ var fiber = createFiber(HostText, content, null, mode);
+ fiber.expirationTime = expirationTime;
+ return fiber;
+}
+
+function createFiberFromHostInstanceForDeletion() {
+ var fiber = createFiber(HostComponent, null, null, NoContext);
+ // TODO: These should not need a type.
+ fiber.elementType = 'DELETED';
+ fiber.type = 'DELETED';
+ return fiber;
+}
+
+function createFiberFromPortal(portal, mode, expirationTime) {
+ var pendingProps = portal.children !== null ? portal.children : [];
+ var fiber = createFiber(HostPortal, pendingProps, portal.key, mode);
+ fiber.expirationTime = expirationTime;
+ fiber.stateNode = {
+ containerInfo: portal.containerInfo,
+ pendingChildren: null, // Used by persistent updates
+ implementation: portal.implementation
+ };
+ return fiber;
+}
+
+// Used for stashing WIP properties to replay failed work in DEV.
+
+var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+var _ReactInternals$Sched = ReactInternals$1.SchedulerTracing;
+var __interactionsRef = _ReactInternals$Sched.__interactionsRef;
+var __subscriberRef = _ReactInternals$Sched.__subscriberRef;
+var unstable_clear = _ReactInternals$Sched.unstable_clear;
+var unstable_getCurrent = _ReactInternals$Sched.unstable_getCurrent;
+var unstable_getThreadID = _ReactInternals$Sched.unstable_getThreadID;
+var unstable_subscribe = _ReactInternals$Sched.unstable_subscribe;
+var unstable_trace = _ReactInternals$Sched.unstable_trace;
+var unstable_unsubscribe = _ReactInternals$Sched.unstable_unsubscribe;
+var unstable_wrap = _ReactInternals$Sched.unstable_wrap;
+
+// TODO: This should be lifted into the renderer.
+
+
+// The following attributes are only used by interaction tracing builds.
+// They enable interactions to be associated with their async work,
+// And expose interaction metadata to the React DevTools Profiler plugin.
+// Note that these attributes are only defined when the enableSchedulerTracing flag is enabled.
+
+
+// Exported FiberRoot type includes all properties,
+// To avoid requiring potentially error-prone :any casts throughout the project.
+// Profiling properties are only safe to access in profiling builds (when enableSchedulerTracing is true).
+// The types are defined separately within this file to ensure they stay in sync.
+// (We don't have to use an inline :any cast when enableSchedulerTracing is disabled.)
+
+
+function createFiberRoot(containerInfo, isConcurrent, hydrate) {
+ // Cyclic construction. This cheats the type system right now because
+ // stateNode is any.
+ var uninitializedFiber = createHostRootFiber(isConcurrent);
+
+ var root = void 0;
+ if (enableSchedulerTracing) {
+ root = {
+ current: uninitializedFiber,
+ containerInfo: containerInfo,
+ pendingChildren: null,
+
+ earliestPendingTime: NoWork,
+ latestPendingTime: NoWork,
+ earliestSuspendedTime: NoWork,
+ latestSuspendedTime: NoWork,
+ latestPingedTime: NoWork,
+
+ pingCache: null,
+
+ didError: false,
+
+ pendingCommitExpirationTime: NoWork,
+ finishedWork: null,
+ timeoutHandle: noTimeout,
+ context: null,
+ pendingContext: null,
+ hydrate: hydrate,
+ nextExpirationTimeToWorkOn: NoWork,
+ expirationTime: NoWork,
+ firstBatch: null,
+ nextScheduledRoot: null,
+
+ interactionThreadID: unstable_getThreadID(),
+ memoizedInteractions: new Set(),
+ pendingInteractionMap: new Map()
+ };
+ } else {
+ root = {
+ current: uninitializedFiber,
+ containerInfo: containerInfo,
+ pendingChildren: null,
+
+ pingCache: null,
+
+ earliestPendingTime: NoWork,
+ latestPendingTime: NoWork,
+ earliestSuspendedTime: NoWork,
+ latestSuspendedTime: NoWork,
+ latestPingedTime: NoWork,
+
+ didError: false,
+
+ pendingCommitExpirationTime: NoWork,
+ finishedWork: null,
+ timeoutHandle: noTimeout,
+ context: null,
+ pendingContext: null,
+ hydrate: hydrate,
+ nextExpirationTimeToWorkOn: NoWork,
+ expirationTime: NoWork,
+ firstBatch: null,
+ nextScheduledRoot: null
+ };
+ }
+
+ uninitializedFiber.stateNode = root;
+
+ // The reason for the way the Flow types are structured in this file,
+ // Is to avoid needing :any casts everywhere interaction tracing fields are used.
+ // Unfortunately that requires an :any cast for non-interaction tracing capable builds.
+ // $FlowFixMe Remove this :any cast and replace it with something better.
+ return root;
+}
+
+var ReactInternals$2 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+var _ReactInternals$Sched$1 = ReactInternals$2.Scheduler;
+var unstable_cancelCallback = _ReactInternals$Sched$1.unstable_cancelCallback;
+var unstable_now = _ReactInternals$Sched$1.unstable_now;
+var unstable_scheduleCallback = _ReactInternals$Sched$1.unstable_scheduleCallback;
+var unstable_shouldYield = _ReactInternals$Sched$1.unstable_shouldYield;
+var unstable_getFirstCallbackNode = _ReactInternals$Sched$1.unstable_getFirstCallbackNode;
+var unstable_runWithPriority = _ReactInternals$Sched$1.unstable_runWithPriority;
+var unstable_next = _ReactInternals$Sched$1.unstable_next;
+var unstable_continueExecution = _ReactInternals$Sched$1.unstable_continueExecution;
+var unstable_pauseExecution = _ReactInternals$Sched$1.unstable_pauseExecution;
+var unstable_getCurrentPriorityLevel = _ReactInternals$Sched$1.unstable_getCurrentPriorityLevel;
+var unstable_ImmediatePriority = _ReactInternals$Sched$1.unstable_ImmediatePriority;
+var unstable_UserBlockingPriority = _ReactInternals$Sched$1.unstable_UserBlockingPriority;
+var unstable_NormalPriority = _ReactInternals$Sched$1.unstable_NormalPriority;
+var unstable_LowPriority = _ReactInternals$Sched$1.unstable_LowPriority;
+var unstable_IdlePriority = _ReactInternals$Sched$1.unstable_IdlePriority;
+
+/**
+ * Call a function while guarding against errors that happens within it.
+ * Returns an error if it throws, otherwise null.
+ *
+ * In production, this is implemented using a try-catch. The reason we don't
+ * use a try-catch directly is so that we can swap out a different
+ * implementation in DEV mode.
+ *
+ * @param {String} name of the guard to use for logging or debugging
+ * @param {Function} func The function to invoke
+ * @param {*} context The context to use when calling the function
+ * @param {...*} args Arguments for function
+ */
+
+
+/**
+ * Same as invokeGuardedCallback, but instead of returning an error, it stores
+ * it in a global so it can be rethrown by `rethrowCaughtError` later.
+ * TODO: See if caughtError and rethrowError can be unified.
+ *
+ * @param {String} name of the guard to use for logging or debugging
+ * @param {Function} func The function to invoke
+ * @param {*} context The context to use when calling the function
+ * @param {...*} args Arguments for function
+ */
+
+
+/**
+ * During execution of guarded functions we will capture the first error which
+ * we will rethrow to be handled by the top level error handler.
+ */
+
+/**
+ * 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.
+ */
+
+// This lets us hook into Fiber to debug what it's doing.
+// See https://github.com/facebook/react/pull/8033.
+// This is not part of the public API, not even for React DevTools.
+// You may only inject a debugTool if you work on React Fiber itself.
+
+// TODO: Offscreen updates should never suspend. However, a promise that
+// suspended inside an offscreen subtree should be able to ping at the priority
+// of the outer render.
+
+function markPendingPriorityLevel(root, expirationTime) {
+ // If there's a gap between completing a failed root and retrying it,
+ // additional updates may be scheduled. Clear `didError`, in case the update
+ // is sufficient to fix the error.
+ root.didError = false;
+
+ // Update the latest and earliest pending times
+ var earliestPendingTime = root.earliestPendingTime;
+ if (earliestPendingTime === NoWork) {
+ // No other pending updates.
+ root.earliestPendingTime = root.latestPendingTime = expirationTime;
+ } else {
+ if (earliestPendingTime < expirationTime) {
+ // This is the earliest pending update.
+ root.earliestPendingTime = expirationTime;
+ } else {
+ var latestPendingTime = root.latestPendingTime;
+ if (latestPendingTime > expirationTime) {
+ // This is the latest pending update
+ root.latestPendingTime = expirationTime;
+ }
+ }
+ }
+ findNextExpirationTimeToWorkOn(expirationTime, root);
+}
+
+function markCommittedPriorityLevels(root, earliestRemainingTime) {
+ root.didError = false;
+
+ if (earliestRemainingTime === NoWork) {
+ // Fast path. There's no remaining work. Clear everything.
+ root.earliestPendingTime = NoWork;
+ root.latestPendingTime = NoWork;
+ root.earliestSuspendedTime = NoWork;
+ root.latestSuspendedTime = NoWork;
+ root.latestPingedTime = NoWork;
+ findNextExpirationTimeToWorkOn(NoWork, root);
+ return;
+ }
+
+ if (earliestRemainingTime < root.latestPingedTime) {
+ root.latestPingedTime = NoWork;
+ }
+
+ // Let's see if the previous latest known pending level was just flushed.
+ var latestPendingTime = root.latestPendingTime;
+ if (latestPendingTime !== NoWork) {
+ if (latestPendingTime > earliestRemainingTime) {
+ // We've flushed all the known pending levels.
+ root.earliestPendingTime = root.latestPendingTime = NoWork;
+ } else {
+ var earliestPendingTime = root.earliestPendingTime;
+ if (earliestPendingTime > earliestRemainingTime) {
+ // We've flushed the earliest known pending level. Set this to the
+ // latest pending time.
+ root.earliestPendingTime = root.latestPendingTime;
+ }
+ }
+ }
+
+ // Now let's handle the earliest remaining level in the whole tree. We need to
+ // decide whether to treat it as a pending level or as suspended. Check
+ // it falls within the range of known suspended levels.
+
+ var earliestSuspendedTime = root.earliestSuspendedTime;
+ if (earliestSuspendedTime === NoWork) {
+ // There's no suspended work. Treat the earliest remaining level as a
+ // pending level.
+ markPendingPriorityLevel(root, earliestRemainingTime);
+ findNextExpirationTimeToWorkOn(NoWork, root);
+ return;
+ }
+
+ var latestSuspendedTime = root.latestSuspendedTime;
+ if (earliestRemainingTime < latestSuspendedTime) {
+ // The earliest remaining level is later than all the suspended work. That
+ // means we've flushed all the suspended work.
+ root.earliestSuspendedTime = NoWork;
+ root.latestSuspendedTime = NoWork;
+ root.latestPingedTime = NoWork;
+
+ // There's no suspended work. Treat the earliest remaining level as a
+ // pending level.
+ markPendingPriorityLevel(root, earliestRemainingTime);
+ findNextExpirationTimeToWorkOn(NoWork, root);
+ return;
+ }
+
+ if (earliestRemainingTime > earliestSuspendedTime) {
+ // The earliest remaining time is earlier than all the suspended work.
+ // Treat it as a pending update.
+ markPendingPriorityLevel(root, earliestRemainingTime);
+ findNextExpirationTimeToWorkOn(NoWork, root);
+ return;
+ }
+
+ // The earliest remaining time falls within the range of known suspended
+ // levels. We should treat this as suspended work.
+ findNextExpirationTimeToWorkOn(NoWork, root);
+}
+
+function hasLowerPriorityWork(root, erroredExpirationTime) {
+ var latestPendingTime = root.latestPendingTime;
+ var latestSuspendedTime = root.latestSuspendedTime;
+ var latestPingedTime = root.latestPingedTime;
+ return latestPendingTime !== NoWork && latestPendingTime < erroredExpirationTime || latestSuspendedTime !== NoWork && latestSuspendedTime < erroredExpirationTime || latestPingedTime !== NoWork && latestPingedTime < erroredExpirationTime;
+}
+
+function isPriorityLevelSuspended(root, expirationTime) {
+ var earliestSuspendedTime = root.earliestSuspendedTime;
+ var latestSuspendedTime = root.latestSuspendedTime;
+ return earliestSuspendedTime !== NoWork && expirationTime <= earliestSuspendedTime && expirationTime >= latestSuspendedTime;
+}
+
+function markSuspendedPriorityLevel(root, suspendedTime) {
+ root.didError = false;
+ clearPing(root, suspendedTime);
+
+ // First, check the known pending levels and update them if needed.
+ var earliestPendingTime = root.earliestPendingTime;
+ var latestPendingTime = root.latestPendingTime;
+ if (earliestPendingTime === suspendedTime) {
+ if (latestPendingTime === suspendedTime) {
+ // Both known pending levels were suspended. Clear them.
+ root.earliestPendingTime = root.latestPendingTime = NoWork;
+ } else {
+ // The earliest pending level was suspended. Clear by setting it to the
+ // latest pending level.
+ root.earliestPendingTime = latestPendingTime;
+ }
+ } else if (latestPendingTime === suspendedTime) {
+ // The latest pending level was suspended. Clear by setting it to the
+ // latest pending level.
+ root.latestPendingTime = earliestPendingTime;
+ }
+
+ // Finally, update the known suspended levels.
+ var earliestSuspendedTime = root.earliestSuspendedTime;
+ var latestSuspendedTime = root.latestSuspendedTime;
+ if (earliestSuspendedTime === NoWork) {
+ // No other suspended levels.
+ root.earliestSuspendedTime = root.latestSuspendedTime = suspendedTime;
+ } else {
+ if (earliestSuspendedTime < suspendedTime) {
+ // This is the earliest suspended level.
+ root.earliestSuspendedTime = suspendedTime;
+ } else if (latestSuspendedTime > suspendedTime) {
+ // This is the latest suspended level
+ root.latestSuspendedTime = suspendedTime;
+ }
+ }
+
+ findNextExpirationTimeToWorkOn(suspendedTime, root);
+}
+
+function markPingedPriorityLevel(root, pingedTime) {
+ root.didError = false;
+
+ // TODO: When we add back resuming, we need to ensure the progressed work
+ // is thrown out and not reused during the restarted render. One way to
+ // invalidate the progressed work is to restart at expirationTime + 1.
+ var latestPingedTime = root.latestPingedTime;
+ if (latestPingedTime === NoWork || latestPingedTime > pingedTime) {
+ root.latestPingedTime = pingedTime;
+ }
+ findNextExpirationTimeToWorkOn(pingedTime, root);
+}
+
+function clearPing(root, completedTime) {
+ var latestPingedTime = root.latestPingedTime;
+ if (latestPingedTime >= completedTime) {
+ root.latestPingedTime = NoWork;
+ }
+}
+
+function findEarliestOutstandingPriorityLevel(root, renderExpirationTime) {
+ var earliestExpirationTime = renderExpirationTime;
+
+ var earliestPendingTime = root.earliestPendingTime;
+ var earliestSuspendedTime = root.earliestSuspendedTime;
+ if (earliestPendingTime > earliestExpirationTime) {
+ earliestExpirationTime = earliestPendingTime;
+ }
+ if (earliestSuspendedTime > earliestExpirationTime) {
+ earliestExpirationTime = earliestSuspendedTime;
+ }
+ return earliestExpirationTime;
+}
+
+function didExpireAtExpirationTime(root, currentTime) {
+ var expirationTime = root.expirationTime;
+ if (expirationTime !== NoWork && currentTime <= expirationTime) {
+ // The root has expired. Flush all work up to the current time.
+ root.nextExpirationTimeToWorkOn = currentTime;
+ }
+}
+
+function findNextExpirationTimeToWorkOn(completedExpirationTime, root) {
+ var earliestSuspendedTime = root.earliestSuspendedTime;
+ var latestSuspendedTime = root.latestSuspendedTime;
+ var earliestPendingTime = root.earliestPendingTime;
+ var latestPingedTime = root.latestPingedTime;
+
+ // Work on the earliest pending time. Failing that, work on the latest
+ // pinged time.
+ var nextExpirationTimeToWorkOn = earliestPendingTime !== NoWork ? earliestPendingTime : latestPingedTime;
+
+ // If there is no pending or pinged work, check if there's suspended work
+ // that's lower priority than what we just completed.
+ if (nextExpirationTimeToWorkOn === NoWork && (completedExpirationTime === NoWork || latestSuspendedTime < completedExpirationTime)) {
+ // The lowest priority suspended work is the work most likely to be
+ // committed next. Let's start rendering it again, so that if it times out,
+ // it's ready to commit.
+ nextExpirationTimeToWorkOn = latestSuspendedTime;
+ }
+
+ var expirationTime = nextExpirationTimeToWorkOn;
+ if (expirationTime !== NoWork && earliestSuspendedTime > expirationTime) {
+ // Expire using the earliest known expiration time.
+ expirationTime = earliestSuspendedTime;
+ }
+
+ root.nextExpirationTimeToWorkOn = nextExpirationTimeToWorkOn;
+ root.expirationTime = expirationTime;
+}
+
+/**
+ * inlined Object.is polyfill to avoid requiring consumers ship their own
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
+ */
+function is(x, y) {
+ return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
+ ;
+}
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+/**
+ * Performs equality by iterating through keys on an object and returning false
+ * when any key has values which are not strictly equal between the arguments.
+ * Returns true when the values of all keys are strictly equal.
+ */
+function shallowEqual(objA, objB) {
+ if (is(objA, objB)) {
+ return true;
+ }
+
+ if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
+ return false;
+ }
+
+ var keysA = Object.keys(objA);
+ var keysB = Object.keys(objB);
+
+ if (keysA.length !== keysB.length) {
+ return false;
+ }
+
+ // Test for A's keys different from B.
+ for (var i = 0; i < keysA.length; i++) {
+ if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function resolveDefaultProps(Component, baseProps) {
+ if (Component && Component.defaultProps) {
+ // Resolve default props. Taken from ReactElement
+ var props = _assign({}, baseProps);
+ var defaultProps = Component.defaultProps;
+ for (var propName in defaultProps) {
+ if (props[propName] === undefined) {
+ props[propName] = defaultProps[propName];
+ }
+ }
+ return props;
+ }
+ return baseProps;
+}
+
+function readLazyComponentType(lazyComponent) {
+ var status = lazyComponent._status;
+ var result = lazyComponent._result;
+ switch (status) {
+ case Resolved:
+ {
+ var Component = result;
+ return Component;
+ }
+ case Rejected:
+ {
+ var error = result;
+ throw error;
+ }
+ case Pending:
+ {
+ var thenable = result;
+ throw thenable;
+ }
+ default:
+ {
+ lazyComponent._status = Pending;
+ var ctor = lazyComponent._ctor;
+ var _thenable = ctor();
+ _thenable.then(function (moduleObject) {
+ if (lazyComponent._status === Pending) {
+ var defaultExport = moduleObject.default;
+ lazyComponent._status = Resolved;
+ lazyComponent._result = defaultExport;
+ }
+ }, function (error) {
+ if (lazyComponent._status === Pending) {
+ lazyComponent._status = Rejected;
+ lazyComponent._result = error;
+ }
+ });
+ // Handle synchronous thenables.
+ switch (lazyComponent._status) {
+ case Resolved:
+ return lazyComponent._result;
+ case Rejected:
+ throw lazyComponent._result;
+ }
+ lazyComponent._result = _thenable;
+ throw _thenable;
+ }
+ }
+}
+
+// React.Component uses a shared frozen object by default.
+// We'll use it to determine whether we need to initialize legacy refs.
+var emptyRefsObject = new React.Component().refs;
+
+function applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, nextProps) {
+ var prevState = workInProgress.memoizedState;
+
+ var partialState = getDerivedStateFromProps(nextProps, prevState);
+
+ var memoizedState = partialState === null || partialState === undefined ? prevState : _assign({}, prevState, partialState);
+ workInProgress.memoizedState = memoizedState;
+
+ // Once the update queue is empty, persist the derived state onto the
+ // base state.
+ var updateQueue = workInProgress.updateQueue;
+ if (updateQueue !== null && workInProgress.expirationTime === NoWork) {
+ updateQueue.baseState = memoizedState;
+ }
+}
+
+var classComponentUpdater = {
+ isMounted: isMounted,
+ enqueueSetState: function (inst, payload, callback) {
+ var fiber = get(inst);
+ var currentTime = requestCurrentTime();
+ var expirationTime = computeExpirationForFiber(currentTime, fiber);
+
+ var update = createUpdate(expirationTime);
+ update.payload = payload;
+ if (callback !== undefined && callback !== null) {
+ update.callback = callback;
+ }
+
+ flushPassiveEffects$1();
+ enqueueUpdate(fiber, update);
+ scheduleWork(fiber, expirationTime);
+ },
+ enqueueReplaceState: function (inst, payload, callback) {
+ var fiber = get(inst);
+ var currentTime = requestCurrentTime();
+ var expirationTime = computeExpirationForFiber(currentTime, fiber);
+
+ var update = createUpdate(expirationTime);
+ update.tag = ReplaceState;
+ update.payload = payload;
+
+ if (callback !== undefined && callback !== null) {
+ update.callback = callback;
+ }
+
+ flushPassiveEffects$1();
+ enqueueUpdate(fiber, update);
+ scheduleWork(fiber, expirationTime);
+ },
+ enqueueForceUpdate: function (inst, callback) {
+ var fiber = get(inst);
+ var currentTime = requestCurrentTime();
+ var expirationTime = computeExpirationForFiber(currentTime, fiber);
+
+ var update = createUpdate(expirationTime);
+ update.tag = ForceUpdate;
+
+ if (callback !== undefined && callback !== null) {
+ update.callback = callback;
+ }
+
+ flushPassiveEffects$1();
+ enqueueUpdate(fiber, update);
+ scheduleWork(fiber, expirationTime);
+ }
+};
+
+function checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext) {
+ var instance = workInProgress.stateNode;
+ if (typeof instance.shouldComponentUpdate === 'function') {
+ startPhaseTimer(workInProgress, 'shouldComponentUpdate');
+ var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, nextContext);
+ stopPhaseTimer();
+
+ return shouldUpdate;
+ }
+
+ if (ctor.prototype && ctor.prototype.isPureReactComponent) {
+ return !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState);
+ }
+
+ return true;
+}
+
+function adoptClassInstance(workInProgress, instance) {
+ instance.updater = classComponentUpdater;
+ workInProgress.stateNode = instance;
+ // The instance needs access to the fiber so that it can schedule updates
+ set(instance, workInProgress);
+
+}
+
+function constructClassInstance(workInProgress, ctor, props, renderExpirationTime) {
+ var isLegacyContextConsumer = false;
+ var unmaskedContext = emptyContextObject;
+ var context = null;
+ var contextType = ctor.contextType;
+
+ if (typeof contextType === 'object' && contextType !== null) {
+ context = readContext(contextType);
+ } else {
+ unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
+ var contextTypes = ctor.contextTypes;
+ isLegacyContextConsumer = contextTypes !== null && contextTypes !== undefined;
+ context = isLegacyContextConsumer ? getMaskedContext(workInProgress, unmaskedContext) : emptyContextObject;
+ }
+
+ // Instantiate twice to help detect side-effects.
+ var instance = new ctor(props, context);
+ var state = workInProgress.memoizedState = instance.state !== null && instance.state !== undefined ? instance.state : null;
+ adoptClassInstance(workInProgress, instance);
+
+ if (isLegacyContextConsumer) {
+ cacheContext(workInProgress, unmaskedContext, context);
+ }
+
+ return instance;
+}
+
+function callComponentWillMount(workInProgress, instance) {
+ startPhaseTimer(workInProgress, 'componentWillMount');
+ var oldState = instance.state;
+
+ if (typeof instance.componentWillMount === 'function') {
+ instance.componentWillMount();
+ }
+ if (typeof instance.UNSAFE_componentWillMount === 'function') {
+ instance.UNSAFE_componentWillMount();
+ }
+
+ stopPhaseTimer();
+
+ if (oldState !== instance.state) {
+ classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
+ }
+}
+
+function callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext) {
+ var oldState = instance.state;
+ startPhaseTimer(workInProgress, 'componentWillReceiveProps');
+ if (typeof instance.componentWillReceiveProps === 'function') {
+ instance.componentWillReceiveProps(newProps, nextContext);
+ }
+ if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') {
+ instance.UNSAFE_componentWillReceiveProps(newProps, nextContext);
+ }
+ stopPhaseTimer();
+
+ if (instance.state !== oldState) {
+ classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
+ }
+}
+
+// Invokes the mount life-cycles on a previously never rendered instance.
+function mountClassInstance(workInProgress, ctor, newProps, renderExpirationTime) {
+ var instance = workInProgress.stateNode;
+ instance.props = newProps;
+ instance.state = workInProgress.memoizedState;
+ instance.refs = emptyRefsObject;
+
+ var contextType = ctor.contextType;
+ if (typeof contextType === 'object' && contextType !== null) {
+ instance.context = readContext(contextType);
+ } else {
+ var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
+ instance.context = getMaskedContext(workInProgress, unmaskedContext);
+ }
+
+ var updateQueue = workInProgress.updateQueue;
+ if (updateQueue !== null) {
+ processUpdateQueue(workInProgress, updateQueue, newProps, instance, renderExpirationTime);
+ instance.state = workInProgress.memoizedState;
+ }
+
+ var getDerivedStateFromProps = ctor.getDerivedStateFromProps;
+ if (typeof getDerivedStateFromProps === 'function') {
+ applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps);
+ instance.state = workInProgress.memoizedState;
+ }
+
+ // In order to support react-lifecycles-compat polyfilled components,
+ // Unsafe lifecycles should not be invoked for components using the new APIs.
+ if (typeof ctor.getDerivedStateFromProps !== 'function' && typeof instance.getSnapshotBeforeUpdate !== 'function' && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) {
+ callComponentWillMount(workInProgress, instance);
+ // If we had additional state updates during this life-cycle, let's
+ // process them now.
+ updateQueue = workInProgress.updateQueue;
+ if (updateQueue !== null) {
+ processUpdateQueue(workInProgress, updateQueue, newProps, instance, renderExpirationTime);
+ instance.state = workInProgress.memoizedState;
+ }
+ }
+
+ if (typeof instance.componentDidMount === 'function') {
+ workInProgress.effectTag |= Update;
+ }
+}
+
+function resumeMountClassInstance(workInProgress, ctor, newProps, renderExpirationTime) {
+ var instance = workInProgress.stateNode;
+
+ var oldProps = workInProgress.memoizedProps;
+ instance.props = oldProps;
+
+ var oldContext = instance.context;
+ var contextType = ctor.contextType;
+ var nextContext = void 0;
+ if (typeof contextType === 'object' && contextType !== null) {
+ nextContext = readContext(contextType);
+ } else {
+ var nextLegacyUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
+ nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext);
+ }
+
+ var getDerivedStateFromProps = ctor.getDerivedStateFromProps;
+ var hasNewLifecycles = typeof getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function';
+
+ // Note: During these life-cycles, instance.props/instance.state are what
+ // ever the previously attempted to render - not the "current". However,
+ // during componentDidUpdate we pass the "current" props.
+
+ // In order to support react-lifecycles-compat polyfilled components,
+ // Unsafe lifecycles should not be invoked for components using the new APIs.
+ if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === 'function' || typeof instance.componentWillReceiveProps === 'function')) {
+ if (oldProps !== newProps || oldContext !== nextContext) {
+ callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext);
+ }
+ }
+
+ resetHasForceUpdateBeforeProcessing();
+
+ var oldState = workInProgress.memoizedState;
+ var newState = instance.state = oldState;
+ var updateQueue = workInProgress.updateQueue;
+ if (updateQueue !== null) {
+ processUpdateQueue(workInProgress, updateQueue, newProps, instance, renderExpirationTime);
+ newState = workInProgress.memoizedState;
+ }
+ if (oldProps === newProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing()) {
+ // If an update was already in progress, we should schedule an Update
+ // effect even though we're bailing out, so that cWU/cDU are called.
+ if (typeof instance.componentDidMount === 'function') {
+ workInProgress.effectTag |= Update;
+ }
+ return false;
+ }
+
+ if (typeof getDerivedStateFromProps === 'function') {
+ applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps);
+ newState = workInProgress.memoizedState;
+ }
+
+ var shouldUpdate = checkHasForceUpdateAfterProcessing() || checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext);
+
+ if (shouldUpdate) {
+ // In order to support react-lifecycles-compat polyfilled components,
+ // Unsafe lifecycles should not be invoked for components using the new APIs.
+ if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) {
+ startPhaseTimer(workInProgress, 'componentWillMount');
+ if (typeof instance.componentWillMount === 'function') {
+ instance.componentWillMount();
+ }
+ if (typeof instance.UNSAFE_componentWillMount === 'function') {
+ instance.UNSAFE_componentWillMount();
+ }
+ stopPhaseTimer();
+ }
+ if (typeof instance.componentDidMount === 'function') {
+ workInProgress.effectTag |= Update;
+ }
+ } else {
+ // If an update was already in progress, we should schedule an Update
+ // effect even though we're bailing out, so that cWU/cDU are called.
+ if (typeof instance.componentDidMount === 'function') {
+ workInProgress.effectTag |= Update;
+ }
+
+ // If shouldComponentUpdate returned false, we should still update the
+ // memoized state to indicate that this work can be reused.
+ workInProgress.memoizedProps = newProps;
+ workInProgress.memoizedState = newState;
+ }
+
+ // Update the existing instance's state, props, and context pointers even
+ // if shouldComponentUpdate returns false.
+ instance.props = newProps;
+ instance.state = newState;
+ instance.context = nextContext;
+
+ return shouldUpdate;
+}
+
+// Invokes the update life-cycles and returns false if it shouldn't rerender.
+function updateClassInstance(current, workInProgress, ctor, newProps, renderExpirationTime) {
+ var instance = workInProgress.stateNode;
+
+ var oldProps = workInProgress.memoizedProps;
+ instance.props = workInProgress.type === workInProgress.elementType ? oldProps : resolveDefaultProps(workInProgress.type, oldProps);
+
+ var oldContext = instance.context;
+ var contextType = ctor.contextType;
+ var nextContext = void 0;
+ if (typeof contextType === 'object' && contextType !== null) {
+ nextContext = readContext(contextType);
+ } else {
+ var nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
+ nextContext = getMaskedContext(workInProgress, nextUnmaskedContext);
+ }
+
+ var getDerivedStateFromProps = ctor.getDerivedStateFromProps;
+ var hasNewLifecycles = typeof getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function';
+
+ // Note: During these life-cycles, instance.props/instance.state are what
+ // ever the previously attempted to render - not the "current". However,
+ // during componentDidUpdate we pass the "current" props.
+
+ // In order to support react-lifecycles-compat polyfilled components,
+ // Unsafe lifecycles should not be invoked for components using the new APIs.
+ if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === 'function' || typeof instance.componentWillReceiveProps === 'function')) {
+ if (oldProps !== newProps || oldContext !== nextContext) {
+ callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext);
+ }
+ }
+
+ resetHasForceUpdateBeforeProcessing();
+
+ var oldState = workInProgress.memoizedState;
+ var newState = instance.state = oldState;
+ var updateQueue = workInProgress.updateQueue;
+ if (updateQueue !== null) {
+ processUpdateQueue(workInProgress, updateQueue, newProps, instance, renderExpirationTime);
+ newState = workInProgress.memoizedState;
+ }
+
+ if (oldProps === newProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing()) {
+ // If an update was already in progress, we should schedule an Update
+ // effect even though we're bailing out, so that cWU/cDU are called.
+ if (typeof instance.componentDidUpdate === 'function') {
+ if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
+ workInProgress.effectTag |= Update;
+ }
+ }
+ if (typeof instance.getSnapshotBeforeUpdate === 'function') {
+ if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
+ workInProgress.effectTag |= Snapshot;
+ }
+ }
+ return false;
+ }
+
+ if (typeof getDerivedStateFromProps === 'function') {
+ applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps);
+ newState = workInProgress.memoizedState;
+ }
+
+ var shouldUpdate = checkHasForceUpdateAfterProcessing() || checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext);
+
+ if (shouldUpdate) {
+ // In order to support react-lifecycles-compat polyfilled components,
+ // Unsafe lifecycles should not be invoked for components using the new APIs.
+ if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillUpdate === 'function' || typeof instance.componentWillUpdate === 'function')) {
+ startPhaseTimer(workInProgress, 'componentWillUpdate');
+ if (typeof instance.componentWillUpdate === 'function') {
+ instance.componentWillUpdate(newProps, newState, nextContext);
+ }
+ if (typeof instance.UNSAFE_componentWillUpdate === 'function') {
+ instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext);
+ }
+ stopPhaseTimer();
+ }
+ if (typeof instance.componentDidUpdate === 'function') {
+ workInProgress.effectTag |= Update;
+ }
+ if (typeof instance.getSnapshotBeforeUpdate === 'function') {
+ workInProgress.effectTag |= Snapshot;
+ }
+ } else {
+ // If an update was already in progress, we should schedule an Update
+ // effect even though we're bailing out, so that cWU/cDU are called.
+ if (typeof instance.componentDidUpdate === 'function') {
+ if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
+ workInProgress.effectTag |= Update;
+ }
+ }
+ if (typeof instance.getSnapshotBeforeUpdate === 'function') {
+ if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
+ workInProgress.effectTag |= Snapshot;
+ }
+ }
+
+ // If shouldComponentUpdate returned false, we should still update the
+ // memoized props/state to indicate that this work can be reused.
+ workInProgress.memoizedProps = newProps;
+ workInProgress.memoizedState = newState;
+ }
+
+ // Update the existing instance's state, props, and context pointers even
+ // if shouldComponentUpdate returns false.
+ instance.props = newProps;
+ instance.state = newState;
+ instance.context = nextContext;
+
+ return shouldUpdate;
+}
+
+var isArray = Array.isArray;
+
+function coerceRef(returnFiber, current$$1, element) {
+ var mixedRef = element.ref;
+ if (mixedRef !== null && typeof mixedRef !== 'function' && typeof mixedRef !== 'object') {
+ if (element._owner) {
+ var owner = element._owner;
+ var inst = void 0;
+ if (owner) {
+ var ownerFiber = owner;
+ !(ownerFiber.tag === ClassComponent) ? reactProdInvariant('309') : void 0;
+ inst = ownerFiber.stateNode;
+ }
+ !inst ? reactProdInvariant('147', mixedRef) : void 0;
+ var stringRef = '' + mixedRef;
+ // Check if previous string ref matches new string ref
+ if (current$$1 !== null && current$$1.ref !== null && typeof current$$1.ref === 'function' && current$$1.ref._stringRef === stringRef) {
+ return current$$1.ref;
+ }
+ var ref = function (value) {
+ var refs = inst.refs;
+ if (refs === emptyRefsObject) {
+ // This is a lazy pooled frozen object, so we need to initialize.
+ refs = inst.refs = {};
+ }
+ if (value === null) {
+ delete refs[stringRef];
+ } else {
+ refs[stringRef] = value;
+ }
+ };
+ ref._stringRef = stringRef;
+ return ref;
+ } else {
+ !(typeof mixedRef === 'string') ? reactProdInvariant('284') : void 0;
+ !element._owner ? reactProdInvariant('290', mixedRef) : void 0;
+ }
+ }
+ return mixedRef;
+}
+
+function throwOnInvalidObjectType(returnFiber, newChild) {
+ if (returnFiber.type !== 'textarea') {
+ var addendum = '';
+ reactProdInvariant('31', Object.prototype.toString.call(newChild) === '[object Object]' ? 'object with keys {' + Object.keys(newChild).join(', ') + '}' : newChild, addendum);
+ }
+}
+
+// This wrapper function exists because I expect to clone the code in each path
+// to be able to optimize each path individually by branching early. This needs
+// a compiler or we can do it manually. Helpers that don't need this branching
+// live outside of this function.
+function ChildReconciler(shouldTrackSideEffects) {
+ function deleteChild(returnFiber, childToDelete) {
+ if (!shouldTrackSideEffects) {
+ // Noop.
+ return;
+ }
+ // Deletions are added in reversed order so we add it to the front.
+ // At this point, the return fiber's effect list is empty except for
+ // deletions, so we can just append the deletion to the list. The remaining
+ // effects aren't added until the complete phase. Once we implement
+ // resuming, this may not be true.
+ var last = returnFiber.lastEffect;
+ if (last !== null) {
+ last.nextEffect = childToDelete;
+ returnFiber.lastEffect = childToDelete;
+ } else {
+ returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
+ }
+ childToDelete.nextEffect = null;
+ childToDelete.effectTag = Deletion;
+ }
+
+ function deleteRemainingChildren(returnFiber, currentFirstChild) {
+ if (!shouldTrackSideEffects) {
+ // Noop.
+ return null;
+ }
+
+ // TODO: For the shouldClone case, this could be micro-optimized a bit by
+ // assuming that after the first child we've already added everything.
+ var childToDelete = currentFirstChild;
+ while (childToDelete !== null) {
+ deleteChild(returnFiber, childToDelete);
+ childToDelete = childToDelete.sibling;
+ }
+ return null;
+ }
+
+ function mapRemainingChildren(returnFiber, currentFirstChild) {
+ // Add the remaining children to a temporary map so that we can find them by
+ // keys quickly. Implicit (null) keys get added to this set with their index
+ var existingChildren = new Map();
+
+ var existingChild = currentFirstChild;
+ while (existingChild !== null) {
+ if (existingChild.key !== null) {
+ existingChildren.set(existingChild.key, existingChild);
+ } else {
+ existingChildren.set(existingChild.index, existingChild);
+ }
+ existingChild = existingChild.sibling;
+ }
+ return existingChildren;
+ }
+
+ function useFiber(fiber, pendingProps, expirationTime) {
+ // We currently set sibling to null and index to 0 here because it is easy
+ // to forget to do before returning it. E.g. for the single child case.
+ var clone = createWorkInProgress(fiber, pendingProps, expirationTime);
+ clone.index = 0;
+ clone.sibling = null;
+ return clone;
+ }
+
+ function placeChild(newFiber, lastPlacedIndex, newIndex) {
+ newFiber.index = newIndex;
+ if (!shouldTrackSideEffects) {
+ // Noop.
+ return lastPlacedIndex;
+ }
+ var current$$1 = newFiber.alternate;
+ if (current$$1 !== null) {
+ var oldIndex = current$$1.index;
+ if (oldIndex < lastPlacedIndex) {
+ // This is a move.
+ newFiber.effectTag = Placement;
+ return lastPlacedIndex;
+ } else {
+ // This item can stay in place.
+ return oldIndex;
+ }
+ } else {
+ // This is an insertion.
+ newFiber.effectTag = Placement;
+ return lastPlacedIndex;
+ }
+ }
+
+ function placeSingleChild(newFiber) {
+ // This is simpler for the single child case. We only need to do a
+ // placement for inserting new children.
+ if (shouldTrackSideEffects && newFiber.alternate === null) {
+ newFiber.effectTag = Placement;
+ }
+ return newFiber;
+ }
+
+ function updateTextNode(returnFiber, current$$1, textContent, expirationTime) {
+ if (current$$1 === null || current$$1.tag !== HostText) {
+ // Insert
+ var created = createFiberFromText(textContent, returnFiber.mode, expirationTime);
+ created.return = returnFiber;
+ return created;
+ } else {
+ // Update
+ var existing = useFiber(current$$1, textContent, expirationTime);
+ existing.return = returnFiber;
+ return existing;
+ }
+ }
+
+ function updateElement(returnFiber, current$$1, element, expirationTime) {
+ if (current$$1 !== null && current$$1.elementType === element.type) {
+ // Move based on index
+ var existing = useFiber(current$$1, element.props, expirationTime);
+ existing.ref = coerceRef(returnFiber, current$$1, element);
+ existing.return = returnFiber;
+ return existing;
+ } else {
+ // Insert
+ var created = createFiberFromElement(element, returnFiber.mode, expirationTime);
+ created.ref = coerceRef(returnFiber, current$$1, element);
+ created.return = returnFiber;
+ return created;
+ }
+ }
+
+ function updatePortal(returnFiber, current$$1, portal, expirationTime) {
+ if (current$$1 === null || current$$1.tag !== HostPortal || current$$1.stateNode.containerInfo !== portal.containerInfo || current$$1.stateNode.implementation !== portal.implementation) {
+ // Insert
+ var created = createFiberFromPortal(portal, returnFiber.mode, expirationTime);
+ created.return = returnFiber;
+ return created;
+ } else {
+ // Update
+ var existing = useFiber(current$$1, portal.children || [], expirationTime);
+ existing.return = returnFiber;
+ return existing;
+ }
+ }
+
+ function updateFragment(returnFiber, current$$1, fragment, expirationTime, key) {
+ if (current$$1 === null || current$$1.tag !== Fragment) {
+ // Insert
+ var created = createFiberFromFragment(fragment, returnFiber.mode, expirationTime, key);
+ created.return = returnFiber;
+ return created;
+ } else {
+ // Update
+ var existing = useFiber(current$$1, fragment, expirationTime);
+ existing.return = returnFiber;
+ return existing;
+ }
+ }
+
+ function createChild(returnFiber, newChild, expirationTime) {
+ if (typeof newChild === 'string' || typeof newChild === 'number') {
+ // Text nodes don't have keys. If the previous node is implicitly keyed
+ // we can continue to replace it without aborting even if it is not a text
+ // node.
+ var created = createFiberFromText('' + newChild, returnFiber.mode, expirationTime);
+ created.return = returnFiber;
+ return created;
+ }
+
+ if (typeof newChild === 'object' && newChild !== null) {
+ switch (newChild.$$typeof) {
+ case REACT_ELEMENT_TYPE:
+ {
+ var _created = createFiberFromElement(newChild, returnFiber.mode, expirationTime);
+ _created.ref = coerceRef(returnFiber, null, newChild);
+ _created.return = returnFiber;
+ return _created;
+ }
+ case REACT_PORTAL_TYPE:
+ {
+ var _created2 = createFiberFromPortal(newChild, returnFiber.mode, expirationTime);
+ _created2.return = returnFiber;
+ return _created2;
+ }
+ }
+
+ if (isArray(newChild) || getIteratorFn(newChild)) {
+ var _created3 = createFiberFromFragment(newChild, returnFiber.mode, expirationTime, null);
+ _created3.return = returnFiber;
+ return _created3;
+ }
+
+ throwOnInvalidObjectType(returnFiber, newChild);
+ }
+
+ return null;
+ }
+
+ function updateSlot(returnFiber, oldFiber, newChild, expirationTime) {
+ // Update the fiber if the keys match, otherwise return null.
+
+ var key = oldFiber !== null ? oldFiber.key : null;
+
+ if (typeof newChild === 'string' || typeof newChild === 'number') {
+ // Text nodes don't have keys. If the previous node is implicitly keyed
+ // we can continue to replace it without aborting even if it is not a text
+ // node.
+ if (key !== null) {
+ return null;
+ }
+ return updateTextNode(returnFiber, oldFiber, '' + newChild, expirationTime);
+ }
+
+ if (typeof newChild === 'object' && newChild !== null) {
+ switch (newChild.$$typeof) {
+ case REACT_ELEMENT_TYPE:
+ {
+ if (newChild.key === key) {
+ if (newChild.type === REACT_FRAGMENT_TYPE) {
+ return updateFragment(returnFiber, oldFiber, newChild.props.children, expirationTime, key);
+ }
+ return updateElement(returnFiber, oldFiber, newChild, expirationTime);
+ } else {
+ return null;
+ }
+ }
+ case REACT_PORTAL_TYPE:
+ {
+ if (newChild.key === key) {
+ return updatePortal(returnFiber, oldFiber, newChild, expirationTime);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ if (isArray(newChild) || getIteratorFn(newChild)) {
+ if (key !== null) {
+ return null;
+ }
+
+ return updateFragment(returnFiber, oldFiber, newChild, expirationTime, null);
+ }
+
+ throwOnInvalidObjectType(returnFiber, newChild);
+ }
+
+ return null;
+ }
+
+ function updateFromMap(existingChildren, returnFiber, newIdx, newChild, expirationTime) {
+ if (typeof newChild === 'string' || typeof newChild === 'number') {
+ // Text nodes don't have keys, so we neither have to check the old nor
+ // new node for the key. If both are text nodes, they match.
+ var matchedFiber = existingChildren.get(newIdx) || null;
+ return updateTextNode(returnFiber, matchedFiber, '' + newChild, expirationTime);
+ }
+
+ if (typeof newChild === 'object' && newChild !== null) {
+ switch (newChild.$$typeof) {
+ case REACT_ELEMENT_TYPE:
+ {
+ var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
+ if (newChild.type === REACT_FRAGMENT_TYPE) {
+ return updateFragment(returnFiber, _matchedFiber, newChild.props.children, expirationTime, newChild.key);
+ }
+ return updateElement(returnFiber, _matchedFiber, newChild, expirationTime);
+ }
+ case REACT_PORTAL_TYPE:
+ {
+ var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
+ return updatePortal(returnFiber, _matchedFiber2, newChild, expirationTime);
+ }
+ }
+
+ if (isArray(newChild) || getIteratorFn(newChild)) {
+ var _matchedFiber3 = existingChildren.get(newIdx) || null;
+ return updateFragment(returnFiber, _matchedFiber3, newChild, expirationTime, null);
+ }
+
+ throwOnInvalidObjectType(returnFiber, newChild);
+ }
+
+ return null;
+ }
+
+ /**
+ * Warns if there is a duplicate or missing key
+ */
+ function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, expirationTime) {
+ // This algorithm can't optimize by searching from both ends since we
+ // don't have backpointers on fibers. I'm trying to see how far we can get
+ // with that model. If it ends up not being worth the tradeoffs, we can
+ // add it later.
+
+ // Even with a two ended optimization, we'd want to optimize for the case
+ // where there are few changes and brute force the comparison instead of
+ // going for the Map. It'd like to explore hitting that path first in
+ // forward-only mode and only go for the Map once we notice that we need
+ // lots of look ahead. This doesn't handle reversal as well as two ended
+ // search but that's unusual. Besides, for the two ended optimization to
+ // work on Iterables, we'd need to copy the whole set.
+
+ // In this first iteration, we'll just live with hitting the bad case
+ // (adding everything to a Map) in for every insert/move.
+
+ // If you change this code, also update reconcileChildrenIterator() which
+ // uses the same algorithm.
+
+ var resultingFirstChild = null;
+ var previousNewFiber = null;
+
+ var oldFiber = currentFirstChild;
+ var lastPlacedIndex = 0;
+ var newIdx = 0;
+ var nextOldFiber = null;
+ for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) {
+ if (oldFiber.index > newIdx) {
+ nextOldFiber = oldFiber;
+ oldFiber = null;
+ } else {
+ nextOldFiber = oldFiber.sibling;
+ }
+ var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], expirationTime);
+ if (newFiber === null) {
+ // TODO: This breaks on empty slots like null children. That's
+ // unfortunate because it triggers the slow path all the time. We need
+ // a better way to communicate whether this was a miss or null,
+ // boolean, undefined, etc.
+ if (oldFiber === null) {
+ oldFiber = nextOldFiber;
+ }
+ break;
+ }
+ if (shouldTrackSideEffects) {
+ if (oldFiber && newFiber.alternate === null) {
+ // We matched the slot, but we didn't reuse the existing fiber, so we
+ // need to delete the existing child.
+ deleteChild(returnFiber, oldFiber);
+ }
+ }
+ lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
+ if (previousNewFiber === null) {
+ // TODO: Move out of the loop. This only happens for the first run.
+ resultingFirstChild = newFiber;
+ } else {
+ // TODO: Defer siblings if we're not at the right index for this slot.
+ // I.e. if we had null values before, then we want to defer this
+ // for each null value. However, we also don't want to call updateSlot
+ // with the previous one.
+ previousNewFiber.sibling = newFiber;
+ }
+ previousNewFiber = newFiber;
+ oldFiber = nextOldFiber;
+ }
+
+ if (newIdx === newChildren.length) {
+ // We've reached the end of the new children. We can delete the rest.
+ deleteRemainingChildren(returnFiber, oldFiber);
+ return resultingFirstChild;
+ }
+
+ if (oldFiber === null) {
+ // If we don't have any more existing children we can choose a fast path
+ // since the rest will all be insertions.
+ for (; newIdx < newChildren.length; newIdx++) {
+ var _newFiber = createChild(returnFiber, newChildren[newIdx], expirationTime);
+ if (!_newFiber) {
+ continue;
+ }
+ lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx);
+ if (previousNewFiber === null) {
+ // TODO: Move out of the loop. This only happens for the first run.
+ resultingFirstChild = _newFiber;
+ } else {
+ previousNewFiber.sibling = _newFiber;
+ }
+ previousNewFiber = _newFiber;
+ }
+ return resultingFirstChild;
+ }
+
+ // Add all children to a key map for quick lookups.
+ var existingChildren = mapRemainingChildren(returnFiber, oldFiber);
+
+ // Keep scanning and use the map to restore deleted items as moves.
+ for (; newIdx < newChildren.length; newIdx++) {
+ var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], expirationTime);
+ if (_newFiber2) {
+ if (shouldTrackSideEffects) {
+ if (_newFiber2.alternate !== null) {
+ // The new fiber is a work in progress, but if there exists a
+ // current, that means that we reused the fiber. We need to delete
+ // it from the child list so that we don't add it to the deletion
+ // list.
+ existingChildren.delete(_newFiber2.key === null ? newIdx : _newFiber2.key);
+ }
+ }
+ lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx);
+ if (previousNewFiber === null) {
+ resultingFirstChild = _newFiber2;
+ } else {
+ previousNewFiber.sibling = _newFiber2;
+ }
+ previousNewFiber = _newFiber2;
+ }
+ }
+
+ if (shouldTrackSideEffects) {
+ // Any existing children that weren't consumed above were deleted. We need
+ // to add them to the deletion list.
+ existingChildren.forEach(function (child) {
+ return deleteChild(returnFiber, child);
+ });
+ }
+
+ return resultingFirstChild;
+ }
+
+ function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, expirationTime) {
+ // This is the same implementation as reconcileChildrenArray(),
+ // but using the iterator instead.
+
+ var iteratorFn = getIteratorFn(newChildrenIterable);
+ !(typeof iteratorFn === 'function') ? reactProdInvariant('150') : void 0;
+
+ var newChildren = iteratorFn.call(newChildrenIterable);
+ !(newChildren != null) ? reactProdInvariant('151') : void 0;
+
+ var resultingFirstChild = null;
+ var previousNewFiber = null;
+
+ var oldFiber = currentFirstChild;
+ var lastPlacedIndex = 0;
+ var newIdx = 0;
+ var nextOldFiber = null;
+
+ var step = newChildren.next();
+ for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) {
+ if (oldFiber.index > newIdx) {
+ nextOldFiber = oldFiber;
+ oldFiber = null;
+ } else {
+ nextOldFiber = oldFiber.sibling;
+ }
+ var newFiber = updateSlot(returnFiber, oldFiber, step.value, expirationTime);
+ if (newFiber === null) {
+ // TODO: This breaks on empty slots like null children. That's
+ // unfortunate because it triggers the slow path all the time. We need
+ // a better way to communicate whether this was a miss or null,
+ // boolean, undefined, etc.
+ if (!oldFiber) {
+ oldFiber = nextOldFiber;
+ }
+ break;
+ }
+ if (shouldTrackSideEffects) {
+ if (oldFiber && newFiber.alternate === null) {
+ // We matched the slot, but we didn't reuse the existing fiber, so we
+ // need to delete the existing child.
+ deleteChild(returnFiber, oldFiber);
+ }
+ }
+ lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
+ if (previousNewFiber === null) {
+ // TODO: Move out of the loop. This only happens for the first run.
+ resultingFirstChild = newFiber;
+ } else {
+ // TODO: Defer siblings if we're not at the right index for this slot.
+ // I.e. if we had null values before, then we want to defer this
+ // for each null value. However, we also don't want to call updateSlot
+ // with the previous one.
+ previousNewFiber.sibling = newFiber;
+ }
+ previousNewFiber = newFiber;
+ oldFiber = nextOldFiber;
+ }
+
+ if (step.done) {
+ // We've reached the end of the new children. We can delete the rest.
+ deleteRemainingChildren(returnFiber, oldFiber);
+ return resultingFirstChild;
+ }
+
+ if (oldFiber === null) {
+ // If we don't have any more existing children we can choose a fast path
+ // since the rest will all be insertions.
+ for (; !step.done; newIdx++, step = newChildren.next()) {
+ var _newFiber3 = createChild(returnFiber, step.value, expirationTime);
+ if (_newFiber3 === null) {
+ continue;
+ }
+ lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx);
+ if (previousNewFiber === null) {
+ // TODO: Move out of the loop. This only happens for the first run.
+ resultingFirstChild = _newFiber3;
+ } else {
+ previousNewFiber.sibling = _newFiber3;
+ }
+ previousNewFiber = _newFiber3;
+ }
+ return resultingFirstChild;
+ }
+
+ // Add all children to a key map for quick lookups.
+ var existingChildren = mapRemainingChildren(returnFiber, oldFiber);
+
+ // Keep scanning and use the map to restore deleted items as moves.
+ for (; !step.done; newIdx++, step = newChildren.next()) {
+ var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, expirationTime);
+ if (_newFiber4 !== null) {
+ if (shouldTrackSideEffects) {
+ if (_newFiber4.alternate !== null) {
+ // The new fiber is a work in progress, but if there exists a
+ // current, that means that we reused the fiber. We need to delete
+ // it from the child list so that we don't add it to the deletion
+ // list.
+ existingChildren.delete(_newFiber4.key === null ? newIdx : _newFiber4.key);
+ }
+ }
+ lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx);
+ if (previousNewFiber === null) {
+ resultingFirstChild = _newFiber4;
+ } else {
+ previousNewFiber.sibling = _newFiber4;
+ }
+ previousNewFiber = _newFiber4;
+ }
+ }
+
+ if (shouldTrackSideEffects) {
+ // Any existing children that weren't consumed above were deleted. We need
+ // to add them to the deletion list.
+ existingChildren.forEach(function (child) {
+ return deleteChild(returnFiber, child);
+ });
+ }
+
+ return resultingFirstChild;
+ }
+
+ function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, expirationTime) {
+ // There's no need to check for keys on text nodes since we don't have a
+ // way to define them.
+ if (currentFirstChild !== null && currentFirstChild.tag === HostText) {
+ // We already have an existing node so let's just update it and delete
+ // the rest.
+ deleteRemainingChildren(returnFiber, currentFirstChild.sibling);
+ var existing = useFiber(currentFirstChild, textContent, expirationTime);
+ existing.return = returnFiber;
+ return existing;
+ }
+ // The existing first child is not a text node so we need to create one
+ // and delete the existing ones.
+ deleteRemainingChildren(returnFiber, currentFirstChild);
+ var created = createFiberFromText(textContent, returnFiber.mode, expirationTime);
+ created.return = returnFiber;
+ return created;
+ }
+
+ function reconcileSingleElement(returnFiber, currentFirstChild, element, expirationTime) {
+ var key = element.key;
+ var child = currentFirstChild;
+ while (child !== null) {
+ // TODO: If key === null and child.key === null, then this only applies to
+ // the first item in the list.
+ if (child.key === key) {
+ if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.elementType === element.type) {
+ deleteRemainingChildren(returnFiber, child.sibling);
+ var existing = useFiber(child, element.type === REACT_FRAGMENT_TYPE ? element.props.children : element.props, expirationTime);
+ existing.ref = coerceRef(returnFiber, child, element);
+ existing.return = returnFiber;
+ return existing;
+ } else {
+ deleteRemainingChildren(returnFiber, child);
+ break;
+ }
+ } else {
+ deleteChild(returnFiber, child);
+ }
+ child = child.sibling;
+ }
+
+ if (element.type === REACT_FRAGMENT_TYPE) {
+ var created = createFiberFromFragment(element.props.children, returnFiber.mode, expirationTime, element.key);
+ created.return = returnFiber;
+ return created;
+ } else {
+ var _created4 = createFiberFromElement(element, returnFiber.mode, expirationTime);
+ _created4.ref = coerceRef(returnFiber, currentFirstChild, element);
+ _created4.return = returnFiber;
+ return _created4;
+ }
+ }
+
+ function reconcileSinglePortal(returnFiber, currentFirstChild, portal, expirationTime) {
+ var key = portal.key;
+ var child = currentFirstChild;
+ while (child !== null) {
+ // TODO: If key === null and child.key === null, then this only applies to
+ // the first item in the list.
+ if (child.key === key) {
+ if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) {
+ deleteRemainingChildren(returnFiber, child.sibling);
+ var existing = useFiber(child, portal.children || [], expirationTime);
+ existing.return = returnFiber;
+ return existing;
+ } else {
+ deleteRemainingChildren(returnFiber, child);
+ break;
+ }
+ } else {
+ deleteChild(returnFiber, child);
+ }
+ child = child.sibling;
+ }
+
+ var created = createFiberFromPortal(portal, returnFiber.mode, expirationTime);
+ created.return = returnFiber;
+ return created;
+ }
+
+ // This API will tag the children with the side-effect of the reconciliation
+ // itself. They will be added to the side-effect list as we pass through the
+ // children and the parent.
+ function reconcileChildFibers(returnFiber, currentFirstChild, newChild, expirationTime) {
+ // This function is not recursive.
+ // If the top level item is an array, we treat it as a set of children,
+ // not as a fragment. Nested arrays on the other hand will be treated as
+ // fragment nodes. Recursion happens at the normal flow.
+
+ // Handle top level unkeyed fragments as if they were arrays.
+ // This leads to an ambiguity between <>{[...]}</> and <>...</>.
+ // We treat the ambiguous cases above the same.
+ var isUnkeyedTopLevelFragment = typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null;
+ if (isUnkeyedTopLevelFragment) {
+ newChild = newChild.props.children;
+ }
+
+ // Handle object types
+ var isObject = typeof newChild === 'object' && newChild !== null;
+
+ if (isObject) {
+ switch (newChild.$$typeof) {
+ case REACT_ELEMENT_TYPE:
+ return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, expirationTime));
+ case REACT_PORTAL_TYPE:
+ return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, expirationTime));
+ }
+ }
+
+ if (typeof newChild === 'string' || typeof newChild === 'number') {
+ return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, expirationTime));
+ }
+
+ if (isArray(newChild)) {
+ return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, expirationTime);
+ }
+
+ if (getIteratorFn(newChild)) {
+ return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, expirationTime);
+ }
+
+ if (isObject) {
+ throwOnInvalidObjectType(returnFiber, newChild);
+ }
+
+ if (typeof newChild === 'undefined' && !isUnkeyedTopLevelFragment) {
+ // If the new child is undefined, and the return fiber is a composite
+ // component, throw an error. If Fiber return types are disabled,
+ // we already threw above.
+ switch (returnFiber.tag) {
+ case ClassComponent:
+ {
+
+ }
+ // Intentionally fall through to the next case, which handles both
+ // functions and classes
+ // eslint-disable-next-lined no-fallthrough
+ case FunctionComponent:
+ {
+ var Component = returnFiber.type;
+ reactProdInvariant('152', Component.displayName || Component.name || 'Component');
+ }
+ }
+ }
+
+ // Remaining cases are all treated as empty.
+ return deleteRemainingChildren(returnFiber, currentFirstChild);
+ }
+
+ return reconcileChildFibers;
+}
+
+var reconcileChildFibers = ChildReconciler(true);
+var mountChildFibers = ChildReconciler(false);
+
+function cloneChildFibers(current$$1, workInProgress) {
+ !(current$$1 === null || workInProgress.child === current$$1.child) ? reactProdInvariant('153') : void 0;
+
+ if (workInProgress.child === null) {
+ return;
+ }
+
+ var currentChild = workInProgress.child;
+ var newChild = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
+ workInProgress.child = newChild;
+
+ newChild.return = workInProgress;
+ while (currentChild.sibling !== null) {
+ currentChild = currentChild.sibling;
+ newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
+ newChild.return = workInProgress;
+ }
+ newChild.sibling = null;
+}
+
+var NO_CONTEXT$1 = {};
+
+var contextStackCursor$1 = createCursor(NO_CONTEXT$1);
+var contextFiberStackCursor = createCursor(NO_CONTEXT$1);
+var rootInstanceStackCursor = createCursor(NO_CONTEXT$1);
+
+function requiredContext(c) {
+ !(c !== NO_CONTEXT$1) ? reactProdInvariant('174') : void 0;
+ return c;
+}
+
+function getRootHostContainer() {
+ var rootInstance = requiredContext(rootInstanceStackCursor.current);
+ return rootInstance;
+}
+
+function pushHostContainer(fiber, nextRootInstance) {
+ // Push current root instance onto the stack;
+ // This allows us to reset root when portals are popped.
+ push(rootInstanceStackCursor, nextRootInstance, fiber);
+ // Track the context and the Fiber that provided it.
+ // This enables us to pop only Fibers that provide unique contexts.
+ push(contextFiberStackCursor, fiber, fiber);
+
+ // Finally, we need to push the host context to the stack.
+ // However, we can't just call getRootHostContext() and push it because
+ // we'd have a different number of entries on the stack depending on
+ // whether getRootHostContext() throws somewhere in renderer code or not.
+ // So we push an empty value first. This lets us safely unwind on errors.
+ push(contextStackCursor$1, NO_CONTEXT$1, fiber);
+ var nextRootContext = getRootHostContext(nextRootInstance);
+ // Now that we know this function doesn't throw, replace it.
+ pop(contextStackCursor$1, fiber);
+ push(contextStackCursor$1, nextRootContext, fiber);
+}
+
+function popHostContainer(fiber) {
+ pop(contextStackCursor$1, fiber);
+ pop(contextFiberStackCursor, fiber);
+ pop(rootInstanceStackCursor, fiber);
+}
+
+function getHostContext() {
+ var context = requiredContext(contextStackCursor$1.current);
+ return context;
+}
+
+function pushHostContext(fiber) {
+ var rootInstance = requiredContext(rootInstanceStackCursor.current);
+ var context = requiredContext(contextStackCursor$1.current);
+ var nextContext = getChildHostContext(context, fiber.type, rootInstance);
+
+ // Don't push this Fiber's context unless it's unique.
+ if (context === nextContext) {
+ return;
+ }
+
+ // Track the context and the Fiber that provided it.
+ // This enables us to pop only Fibers that provide unique contexts.
+ push(contextFiberStackCursor, fiber, fiber);
+ push(contextStackCursor$1, nextContext, fiber);
+}
+
+function popHostContext(fiber) {
+ // Do not pop unless this Fiber provided the current context.
+ // pushHostContext() only pushes Fibers that provide unique contexts.
+ if (contextFiberStackCursor.current !== fiber) {
+ return;
+ }
+
+ pop(contextStackCursor$1, fiber);
+ pop(contextFiberStackCursor, fiber);
+}
+
+var NoEffect$1 = /* */0;
+var UnmountSnapshot = /* */2;
+var UnmountMutation = /* */4;
+var MountMutation = /* */8;
+var UnmountLayout = /* */16;
+var MountLayout = /* */32;
+var MountPassive = /* */64;
+var UnmountPassive = /* */128;
+
+var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher;
+
+
+// These are set right before calling the component.
+var renderExpirationTime = NoWork;
+// The work-in-progress fiber. I've named it differently to distinguish it from
+// the work-in-progress hook.
+var currentlyRenderingFiber$1 = null;
+
+// Hooks are stored as a linked list on the fiber's memoizedState field. The
+// current hook list is the list that belongs to the current fiber. The
+// work-in-progress hook list is a new list that will be added to the
+// work-in-progress fiber.
+var currentHook = null;
+var nextCurrentHook = null;
+var firstWorkInProgressHook = null;
+var workInProgressHook = null;
+var nextWorkInProgressHook = null;
+
+var remainingExpirationTime = NoWork;
+var componentUpdateQueue = null;
+var sideEffectTag = 0;
+
+// Updates scheduled during render will trigger an immediate re-render at the
+// end of the current pass. We can't store these updates on the normal queue,
+// because if the work is aborted, they should be discarded. Because this is
+// a relatively rare case, we also don't want to add an additional field to
+// either the hook or queue object types. So we store them in a lazily create
+// map of queue -> render-phase updates, which are discarded once the component
+// completes without re-rendering.
+
+// Whether an update was scheduled during the currently executing render pass.
+var didScheduleRenderPhaseUpdate = false;
+// Lazily created map of render-phase updates
+var renderPhaseUpdates = null;
+// Counter to prevent infinite loops.
+var numberOfReRenders = 0;
+var RE_RENDER_LIMIT = 25;
+
+function throwInvalidHookError() {
+ reactProdInvariant('321');
+}
+
+function areHookInputsEqual(nextDeps, prevDeps) {
+ if (prevDeps === null) {
+ return false;
+ }
+
+ for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) {
+ if (is(nextDeps[i], prevDeps[i])) {
+ continue;
+ }
+ return false;
+ }
+ return true;
+}
+
+function renderWithHooks(current, workInProgress, Component, props, refOrContext, nextRenderExpirationTime) {
+ renderExpirationTime = nextRenderExpirationTime;
+ currentlyRenderingFiber$1 = workInProgress;
+ nextCurrentHook = current !== null ? current.memoizedState : null;
+
+ {
+ ReactCurrentDispatcher$1.current = nextCurrentHook === null ? HooksDispatcherOnMount : HooksDispatcherOnUpdate;
+ }
+
+ var children = Component(props, refOrContext);
+
+ if (didScheduleRenderPhaseUpdate) {
+ do {
+ didScheduleRenderPhaseUpdate = false;
+ numberOfReRenders += 1;
+
+ // Start over from the beginning of the list
+ nextCurrentHook = current !== null ? current.memoizedState : null;
+ nextWorkInProgressHook = firstWorkInProgressHook;
+
+ currentHook = null;
+ workInProgressHook = null;
+ componentUpdateQueue = null;
+
+ ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdate;
+
+ children = Component(props, refOrContext);
+ } while (didScheduleRenderPhaseUpdate);
+
+ renderPhaseUpdates = null;
+ numberOfReRenders = 0;
+ }
+
+ // We can assume the previous dispatcher is always this one, since we set it
+ // at the beginning of the render phase and there's no re-entrancy.
+ ReactCurrentDispatcher$1.current = ContextOnlyDispatcher;
+
+ var renderedWork = currentlyRenderingFiber$1;
+
+ renderedWork.memoizedState = firstWorkInProgressHook;
+ renderedWork.expirationTime = remainingExpirationTime;
+ renderedWork.updateQueue = componentUpdateQueue;
+ renderedWork.effectTag |= sideEffectTag;
+
+ var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null;
+
+ renderExpirationTime = NoWork;
+ currentlyRenderingFiber$1 = null;
+
+ currentHook = null;
+ nextCurrentHook = null;
+ firstWorkInProgressHook = null;
+ workInProgressHook = null;
+ nextWorkInProgressHook = null;
+
+ remainingExpirationTime = NoWork;
+ componentUpdateQueue = null;
+ sideEffectTag = 0;
+
+ // These were reset above
+ // didScheduleRenderPhaseUpdate = false;
+ // renderPhaseUpdates = null;
+ // numberOfReRenders = 0;
+
+ !!didRenderTooFewHooks ? reactProdInvariant('300') : void 0;
+
+ return children;
+}
+
+function bailoutHooks(current, workInProgress, expirationTime) {
+ workInProgress.updateQueue = current.updateQueue;
+ workInProgress.effectTag &= ~(Passive | Update);
+ if (current.expirationTime <= expirationTime) {
+ current.expirationTime = NoWork;
+ }
+}
+
+function resetHooks() {
+ // We can assume the previous dispatcher is always this one, since we set it
+ // at the beginning of the render phase and there's no re-entrancy.
+ ReactCurrentDispatcher$1.current = ContextOnlyDispatcher;
+
+ // This is used to reset the state of this module when a component throws.
+ // It's also called inside mountIndeterminateComponent if we determine the
+ // component is a module-style component.
+ renderExpirationTime = NoWork;
+ currentlyRenderingFiber$1 = null;
+
+ currentHook = null;
+ nextCurrentHook = null;
+ firstWorkInProgressHook = null;
+ workInProgressHook = null;
+ nextWorkInProgressHook = null;
+
+ remainingExpirationTime = NoWork;
+ componentUpdateQueue = null;
+ sideEffectTag = 0;
+
+ didScheduleRenderPhaseUpdate = false;
+ renderPhaseUpdates = null;
+ numberOfReRenders = 0;
+}
+
+function mountWorkInProgressHook() {
+ var hook = {
+ memoizedState: null,
+
+ baseState: null,
+ queue: null,
+ baseUpdate: null,
+
+ next: null
+ };
+
+ if (workInProgressHook === null) {
+ // This is the first hook in the list
+ firstWorkInProgressHook = workInProgressHook = hook;
+ } else {
+ // Append to the end of the list
+ workInProgressHook = workInProgressHook.next = hook;
+ }
+ return workInProgressHook;
+}
+
+function updateWorkInProgressHook() {
+ // This function is used both for updates and for re-renders triggered by a
+ // render phase update. It assumes there is either a current hook we can
+ // clone, or a work-in-progress hook from a previous render pass that we can
+ // use as a base. When we reach the end of the base list, we must switch to
+ // the dispatcher used for mounts.
+ if (nextWorkInProgressHook !== null) {
+ // There's already a work-in-progress. Reuse it.
+ workInProgressHook = nextWorkInProgressHook;
+ nextWorkInProgressHook = workInProgressHook.next;
+
+ currentHook = nextCurrentHook;
+ nextCurrentHook = currentHook !== null ? currentHook.next : null;
+ } else {
+ // Clone from the current hook.
+ !(nextCurrentHook !== null) ? reactProdInvariant('310') : void 0;
+ currentHook = nextCurrentHook;
+
+ var newHook = {
+ memoizedState: currentHook.memoizedState,
+
+ baseState: currentHook.baseState,
+ queue: currentHook.queue,
+ baseUpdate: currentHook.baseUpdate,
+
+ next: null
+ };
+
+ if (workInProgressHook === null) {
+ // This is the first hook in the list.
+ workInProgressHook = firstWorkInProgressHook = newHook;
+ } else {
+ // Append to the end of the list.
+ workInProgressHook = workInProgressHook.next = newHook;
+ }
+ nextCurrentHook = currentHook.next;
+ }
+ return workInProgressHook;
+}
+
+function createFunctionComponentUpdateQueue() {
+ return {
+ lastEffect: null
+ };
+}
+
+function basicStateReducer(state, action) {
+ return typeof action === 'function' ? action(state) : action;
+}
+
+function mountReducer(reducer, initialArg, init) {
+ var hook = mountWorkInProgressHook();
+ var initialState = void 0;
+ if (init !== undefined) {
+ initialState = init(initialArg);
+ } else {
+ initialState = initialArg;
+ }
+ hook.memoizedState = hook.baseState = initialState;
+ var queue = hook.queue = {
+ last: null,
+ dispatch: null,
+ lastRenderedReducer: reducer,
+ lastRenderedState: initialState
+ };
+ var dispatch = queue.dispatch = dispatchAction.bind(null,
+ // Flow doesn't know this is non-null, but we do.
+ currentlyRenderingFiber$1, queue);
+ return [hook.memoizedState, dispatch];
+}
+
+function updateReducer(reducer, initialArg, init) {
+ var hook = updateWorkInProgressHook();
+ var queue = hook.queue;
+ !(queue !== null) ? reactProdInvariant('311') : void 0;
+
+ queue.lastRenderedReducer = reducer;
+
+ if (numberOfReRenders > 0) {
+ // This is a re-render. Apply the new render phase updates to the previous
+ var _dispatch = queue.dispatch;
+ if (renderPhaseUpdates !== null) {
+ // Render phase updates are stored in a map of queue -> linked list
+ var firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);
+ if (firstRenderPhaseUpdate !== undefined) {
+ renderPhaseUpdates.delete(queue);
+ var newState = hook.memoizedState;
+ var update = firstRenderPhaseUpdate;
+ do {
+ // Process this render phase update. We don't have to check the
+ // priority because it will always be the same as the current
+ // render's.
+ var _action = update.action;
+ newState = reducer(newState, _action);
+ update = update.next;
+ } while (update !== null);
+
+ // Mark that the fiber performed work, but only if the new state is
+ // different from the current state.
+ if (!is(newState, hook.memoizedState)) {
+ markWorkInProgressReceivedUpdate();
+ }
+
+ hook.memoizedState = newState;
+ // Don't persist the state accumlated from the render phase updates to
+ // the base state unless the queue is empty.
+ // TODO: Not sure if this is the desired semantics, but it's what we
+ // do for gDSFP. I can't remember why.
+ if (hook.baseUpdate === queue.last) {
+ hook.baseState = newState;
+ }
+
+ queue.lastRenderedState = newState;
+
+ return [newState, _dispatch];
+ }
+ }
+ return [hook.memoizedState, _dispatch];
+ }
+
+ // The last update in the entire queue
+ var last = queue.last;
+ // The last update that is part of the base state.
+ var baseUpdate = hook.baseUpdate;
+ var baseState = hook.baseState;
+
+ // Find the first unprocessed update.
+ var first = void 0;
+ if (baseUpdate !== null) {
+ if (last !== null) {
+ // For the first update, the queue is a circular linked list where
+ // `queue.last.next = queue.first`. Once the first update commits, and
+ // the `baseUpdate` is no longer empty, we can unravel the list.
+ last.next = null;
+ }
+ first = baseUpdate.next;
+ } else {
+ first = last !== null ? last.next : null;
+ }
+ if (first !== null) {
+ var _newState = baseState;
+ var newBaseState = null;
+ var newBaseUpdate = null;
+ var prevUpdate = baseUpdate;
+ var _update = first;
+ var didSkip = false;
+ do {
+ var updateExpirationTime = _update.expirationTime;
+ if (updateExpirationTime < renderExpirationTime) {
+ // Priority is insufficient. Skip this update. If this is the first
+ // skipped update, the previous update/state is the new base
+ // update/state.
+ if (!didSkip) {
+ didSkip = true;
+ newBaseUpdate = prevUpdate;
+ newBaseState = _newState;
+ }
+ // Update the remaining priority in the queue.
+ if (updateExpirationTime > remainingExpirationTime) {
+ remainingExpirationTime = updateExpirationTime;
+ }
+ } else {
+ // Process this update.
+ if (_update.eagerReducer === reducer) {
+ // If this update was processed eagerly, and its reducer matches the
+ // current reducer, we can use the eagerly computed state.
+ _newState = _update.eagerState;
+ } else {
+ var _action2 = _update.action;
+ _newState = reducer(_newState, _action2);
+ }
+ }
+ prevUpdate = _update;
+ _update = _update.next;
+ } while (_update !== null && _update !== first);
+
+ if (!didSkip) {
+ newBaseUpdate = prevUpdate;
+ newBaseState = _newState;
+ }
+
+ // Mark that the fiber performed work, but only if the new state is
+ // different from the current state.
+ if (!is(_newState, hook.memoizedState)) {
+ markWorkInProgressReceivedUpdate();
+ }
+
+ hook.memoizedState = _newState;
+ hook.baseUpdate = newBaseUpdate;
+ hook.baseState = newBaseState;
+
+ queue.lastRenderedState = _newState;
+ }
+
+ var dispatch = queue.dispatch;
+ return [hook.memoizedState, dispatch];
+}
+
+function mountState(initialState) {
+ var hook = mountWorkInProgressHook();
+ if (typeof initialState === 'function') {
+ initialState = initialState();
+ }
+ hook.memoizedState = hook.baseState = initialState;
+ var queue = hook.queue = {
+ last: null,
+ dispatch: null,
+ lastRenderedReducer: basicStateReducer,
+ lastRenderedState: initialState
+ };
+ var dispatch = queue.dispatch = dispatchAction.bind(null,
+ // Flow doesn't know this is non-null, but we do.
+ currentlyRenderingFiber$1, queue);
+ return [hook.memoizedState, dispatch];
+}
+
+function updateState(initialState) {
+ return updateReducer(basicStateReducer, initialState);
+}
+
+function pushEffect(tag, create, destroy, deps) {
+ var effect = {
+ tag: tag,
+ create: create,
+ destroy: destroy,
+ deps: deps,
+ // Circular
+ next: null
+ };
+ if (componentUpdateQueue === null) {
+ componentUpdateQueue = createFunctionComponentUpdateQueue();
+ componentUpdateQueue.lastEffect = effect.next = effect;
+ } else {
+ var _lastEffect = componentUpdateQueue.lastEffect;
+ if (_lastEffect === null) {
+ componentUpdateQueue.lastEffect = effect.next = effect;
+ } else {
+ var firstEffect = _lastEffect.next;
+ _lastEffect.next = effect;
+ effect.next = firstEffect;
+ componentUpdateQueue.lastEffect = effect;
+ }
+ }
+ return effect;
+}
+
+function mountRef(initialValue) {
+ var hook = mountWorkInProgressHook();
+ var ref = { current: initialValue };
+ hook.memoizedState = ref;
+ return ref;
+}
+
+function updateRef(initialValue) {
+ var hook = updateWorkInProgressHook();
+ return hook.memoizedState;
+}
+
+function mountEffectImpl(fiberEffectTag, hookEffectTag, create, deps) {
+ var hook = mountWorkInProgressHook();
+ var nextDeps = deps === undefined ? null : deps;
+ sideEffectTag |= fiberEffectTag;
+ hook.memoizedState = pushEffect(hookEffectTag, create, undefined, nextDeps);
+}
+
+function updateEffectImpl(fiberEffectTag, hookEffectTag, create, deps) {
+ var hook = updateWorkInProgressHook();
+ var nextDeps = deps === undefined ? null : deps;
+ var destroy = undefined;
+
+ if (currentHook !== null) {
+ var prevEffect = currentHook.memoizedState;
+ destroy = prevEffect.destroy;
+ if (nextDeps !== null) {
+ var prevDeps = prevEffect.deps;
+ if (areHookInputsEqual(nextDeps, prevDeps)) {
+ pushEffect(NoEffect$1, create, destroy, nextDeps);
+ return;
+ }
+ }
+ }
+
+ sideEffectTag |= fiberEffectTag;
+ hook.memoizedState = pushEffect(hookEffectTag, create, destroy, nextDeps);
+}
+
+function mountEffect(create, deps) {
+ return mountEffectImpl(Update | Passive, UnmountPassive | MountPassive, create, deps);
+}
+
+function updateEffect(create, deps) {
+ return updateEffectImpl(Update | Passive, UnmountPassive | MountPassive, create, deps);
+}
+
+function mountLayoutEffect(create, deps) {
+ return mountEffectImpl(Update, UnmountMutation | MountLayout, create, deps);
+}
+
+function updateLayoutEffect(create, deps) {
+ return updateEffectImpl(Update, UnmountMutation | MountLayout, create, deps);
+}
+
+function imperativeHandleEffect(create, ref) {
+ if (typeof ref === 'function') {
+ var refCallback = ref;
+ var _inst = create();
+ refCallback(_inst);
+ return function () {
+ refCallback(null);
+ };
+ } else if (ref !== null && ref !== undefined) {
+ var refObject = ref;
+ var _inst2 = create();
+ refObject.current = _inst2;
+ return function () {
+ refObject.current = null;
+ };
+ }
+}
+
+function mountImperativeHandle(ref, create, deps) {
+ var effectDeps = deps !== null && deps !== undefined ? deps.concat([ref]) : null;
+
+ return mountEffectImpl(Update, UnmountMutation | MountLayout, imperativeHandleEffect.bind(null, create, ref), effectDeps);
+}
+
+function updateImperativeHandle(ref, create, deps) {
+ var effectDeps = deps !== null && deps !== undefined ? deps.concat([ref]) : null;
+
+ return updateEffectImpl(Update, UnmountMutation | MountLayout, imperativeHandleEffect.bind(null, create, ref), effectDeps);
+}
+
+function mountDebugValue(value, formatterFn) {
+ // This hook is normally a no-op.
+ // The react-debug-hooks package injects its own implementation
+ // so that e.g. DevTools can display custom hook values.
+}
+
+var updateDebugValue = mountDebugValue;
+
+function mountCallback(callback, deps) {
+ var hook = mountWorkInProgressHook();
+ var nextDeps = deps === undefined ? null : deps;
+ hook.memoizedState = [callback, nextDeps];
+ return callback;
+}
+
+function updateCallback(callback, deps) {
+ var hook = updateWorkInProgressHook();
+ var nextDeps = deps === undefined ? null : deps;
+ var prevState = hook.memoizedState;
+ if (prevState !== null) {
+ if (nextDeps !== null) {
+ var prevDeps = prevState[1];
+ if (areHookInputsEqual(nextDeps, prevDeps)) {
+ return prevState[0];
+ }
+ }
+ }
+ hook.memoizedState = [callback, nextDeps];
+ return callback;
+}
+
+function mountMemo(nextCreate, deps) {
+ var hook = mountWorkInProgressHook();
+ var nextDeps = deps === undefined ? null : deps;
+ var nextValue = nextCreate();
+ hook.memoizedState = [nextValue, nextDeps];
+ return nextValue;
+}
+
+function updateMemo(nextCreate, deps) {
+ var hook = updateWorkInProgressHook();
+ var nextDeps = deps === undefined ? null : deps;
+ var prevState = hook.memoizedState;
+ if (prevState !== null) {
+ // Assume these are defined. If they're not, areHookInputsEqual will warn.
+ if (nextDeps !== null) {
+ var prevDeps = prevState[1];
+ if (areHookInputsEqual(nextDeps, prevDeps)) {
+ return prevState[0];
+ }
+ }
+ }
+ var nextValue = nextCreate();
+ hook.memoizedState = [nextValue, nextDeps];
+ return nextValue;
+}
+
+function dispatchAction(fiber, queue, action) {
+ !(numberOfReRenders < RE_RENDER_LIMIT) ? reactProdInvariant('301') : void 0;
+
+ var alternate = fiber.alternate;
+ if (fiber === currentlyRenderingFiber$1 || alternate !== null && alternate === currentlyRenderingFiber$1) {
+ // This is a render phase update. Stash it in a lazily-created map of
+ // queue -> linked list of updates. After this render pass, we'll restart
+ // and apply the stashed updates on top of the work-in-progress hook.
+ didScheduleRenderPhaseUpdate = true;
+ var update = {
+ expirationTime: renderExpirationTime,
+ action: action,
+ eagerReducer: null,
+ eagerState: null,
+ next: null
+ };
+ if (renderPhaseUpdates === null) {
+ renderPhaseUpdates = new Map();
+ }
+ var firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);
+ if (firstRenderPhaseUpdate === undefined) {
+ renderPhaseUpdates.set(queue, update);
+ } else {
+ // Append the update to the end of the list.
+ var lastRenderPhaseUpdate = firstRenderPhaseUpdate;
+ while (lastRenderPhaseUpdate.next !== null) {
+ lastRenderPhaseUpdate = lastRenderPhaseUpdate.next;
+ }
+ lastRenderPhaseUpdate.next = update;
+ }
+ } else {
+ flushPassiveEffects$1();
+
+ var currentTime = requestCurrentTime();
+ var _expirationTime = computeExpirationForFiber(currentTime, fiber);
+
+ var _update2 = {
+ expirationTime: _expirationTime,
+ action: action,
+ eagerReducer: null,
+ eagerState: null,
+ next: null
+ };
+
+ // Append the update to the end of the list.
+ var _last = queue.last;
+ if (_last === null) {
+ // This is the first update. Create a circular list.
+ _update2.next = _update2;
+ } else {
+ var first = _last.next;
+ if (first !== null) {
+ // Still circular.
+ _update2.next = first;
+ }
+ _last.next = _update2;
+ }
+ queue.last = _update2;
+
+ if (fiber.expirationTime === NoWork && (alternate === null || alternate.expirationTime === NoWork)) {
+ // The queue is currently empty, which means we can eagerly compute the
+ // next state before entering the render phase. If the new state is the
+ // same as the current state, we may be able to bail out entirely.
+ var _lastRenderedReducer = queue.lastRenderedReducer;
+ if (_lastRenderedReducer !== null) {
+ try {
+ var currentState = queue.lastRenderedState;
+ var _eagerState = _lastRenderedReducer(currentState, action);
+ // Stash the eagerly computed state, and the reducer used to compute
+ // it, on the update object. If the reducer hasn't changed by the
+ // time we enter the render phase, then the eager state can be used
+ // without calling the reducer again.
+ _update2.eagerReducer = _lastRenderedReducer;
+ _update2.eagerState = _eagerState;
+ if (is(_eagerState, currentState)) {
+ // Fast path. We can bail out without scheduling React to re-render.
+ // It's still possible that we'll need to rebase this update later,
+ // if the component re-renders for a different reason and by that
+ // time the reducer has changed.
+ return;
+ }
+ } catch (error) {
+ // Suppress the error. It will throw again in the render phase.
+ } finally {
+
+ }
+ }
+ }
+ scheduleWork(fiber, _expirationTime);
+ }
+}
+
+var ContextOnlyDispatcher = {
+ readContext: readContext,
+
+ useCallback: throwInvalidHookError,
+ useContext: throwInvalidHookError,
+ useEffect: throwInvalidHookError,
+ useImperativeHandle: throwInvalidHookError,
+ useLayoutEffect: throwInvalidHookError,
+ useMemo: throwInvalidHookError,
+ useReducer: throwInvalidHookError,
+ useRef: throwInvalidHookError,
+ useState: throwInvalidHookError,
+ useDebugValue: throwInvalidHookError
+};
+
+var HooksDispatcherOnMount = {
+ readContext: readContext,
+
+ useCallback: mountCallback,
+ useContext: readContext,
+ useEffect: mountEffect,
+ useImperativeHandle: mountImperativeHandle,
+ useLayoutEffect: mountLayoutEffect,
+ useMemo: mountMemo,
+ useReducer: mountReducer,
+ useRef: mountRef,
+ useState: mountState,
+ useDebugValue: mountDebugValue
+};
+
+var HooksDispatcherOnUpdate = {
+ readContext: readContext,
+
+ useCallback: updateCallback,
+ useContext: readContext,
+ useEffect: updateEffect,
+ useImperativeHandle: updateImperativeHandle,
+ useLayoutEffect: updateLayoutEffect,
+ useMemo: updateMemo,
+ useReducer: updateReducer,
+ useRef: updateRef,
+ useState: updateState,
+ useDebugValue: updateDebugValue
+};
+
+var commitTime = 0;
+var profilerStartTime = -1;
+
+function getCommitTime() {
+ return commitTime;
+}
+
+function recordCommitTime() {
+ if (!enableProfilerTimer) {
+ return;
+ }
+ commitTime = now();
+}
+
+function startProfilerTimer(fiber) {
+ if (!enableProfilerTimer) {
+ return;
+ }
+
+ profilerStartTime = now();
+
+ if (fiber.actualStartTime < 0) {
+ fiber.actualStartTime = now();
+ }
+}
+
+function stopProfilerTimerIfRunning(fiber) {
+ if (!enableProfilerTimer) {
+ return;
+ }
+ profilerStartTime = -1;
+}
+
+function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) {
+ if (!enableProfilerTimer) {
+ return;
+ }
+
+ if (profilerStartTime >= 0) {
+ var elapsedTime = now() - profilerStartTime;
+ fiber.actualDuration += elapsedTime;
+ if (overrideBaseTime) {
+ fiber.selfBaseDuration = elapsedTime;
+ }
+ profilerStartTime = -1;
+ }
+}
+
+// The deepest Fiber on the stack involved in a hydration context.
+// This may have been an insertion or a hydration.
+var hydrationParentFiber = null;
+var nextHydratableInstance = null;
+var isHydrating = false;
+
+function enterHydrationState(fiber) {
+ if (!supportsHydration) {
+ return false;
+ }
+
+ var parentInstance = fiber.stateNode.containerInfo;
+ nextHydratableInstance = getFirstHydratableChild(parentInstance);
+ hydrationParentFiber = fiber;
+ isHydrating = true;
+ return true;
+}
+
+function reenterHydrationStateFromDehydratedSuspenseInstance(fiber) {
+ if (!supportsHydration) {
+ return false;
+ }
+
+ var suspenseInstance = fiber.stateNode;
+ nextHydratableInstance = getNextHydratableSibling(suspenseInstance);
+ popToNextHostParent(fiber);
+ isHydrating = true;
+ return true;
+}
+
+function deleteHydratableInstance(returnFiber, instance) {
+ var childToDelete = createFiberFromHostInstanceForDeletion();
+ childToDelete.stateNode = instance;
+ childToDelete.return = returnFiber;
+ childToDelete.effectTag = Deletion;
+
+ // This might seem like it belongs on progressedFirstDeletion. However,
+ // these children are not part of the reconciliation list of children.
+ // Even if we abort and rereconcile the children, that will try to hydrate
+ // again and the nodes are still in the host tree so these will be
+ // recreated.
+ if (returnFiber.lastEffect !== null) {
+ returnFiber.lastEffect.nextEffect = childToDelete;
+ returnFiber.lastEffect = childToDelete;
+ } else {
+ returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
+ }
+}
+
+function insertNonHydratedInstance(returnFiber, fiber) {
+ fiber.effectTag |= Placement;
+
+}
+
+function tryHydrate(fiber, nextInstance) {
+ switch (fiber.tag) {
+ case HostComponent:
+ {
+ var type = fiber.type;
+ var props = fiber.pendingProps;
+ var instance = canHydrateInstance(nextInstance, type, props);
+ if (instance !== null) {
+ fiber.stateNode = instance;
+ return true;
+ }
+ return false;
+ }
+ case HostText:
+ {
+ var text = fiber.pendingProps;
+ var textInstance = canHydrateTextInstance(nextInstance, text);
+ if (textInstance !== null) {
+ fiber.stateNode = textInstance;
+ return true;
+ }
+ return false;
+ }
+ case SuspenseComponent:
+ {
+ if (enableSuspenseServerRenderer) {
+ var suspenseInstance = canHydrateSuspenseInstance(nextInstance);
+ if (suspenseInstance !== null) {
+ // Downgrade the tag to a dehydrated component until we've hydrated it.
+ fiber.tag = DehydratedSuspenseComponent;
+ fiber.stateNode = suspenseInstance;
+ return true;
+ }
+ }
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
+function tryToClaimNextHydratableInstance(fiber) {
+ if (!isHydrating) {
+ return;
+ }
+ var nextInstance = nextHydratableInstance;
+ if (!nextInstance) {
+ // Nothing to hydrate. Make it an insertion.
+ insertNonHydratedInstance(hydrationParentFiber, fiber);
+ isHydrating = false;
+ hydrationParentFiber = fiber;
+ return;
+ }
+ var firstAttemptedInstance = nextInstance;
+ if (!tryHydrate(fiber, nextInstance)) {
+ // If we can't hydrate this instance let's try the next one.
+ // We use this as a heuristic. It's based on intuition and not data so it
+ // might be flawed or unnecessary.
+ nextInstance = getNextHydratableSibling(firstAttemptedInstance);
+ if (!nextInstance || !tryHydrate(fiber, nextInstance)) {
+ // Nothing to hydrate. Make it an insertion.
+ insertNonHydratedInstance(hydrationParentFiber, fiber);
+ isHydrating = false;
+ hydrationParentFiber = fiber;
+ return;
+ }
+ // We matched the next one, we'll now assume that the first one was
+ // superfluous and we'll delete it. Since we can't eagerly delete it
+ // we'll have to schedule a deletion. To do that, this node needs a dummy
+ // fiber associated with it.
+ deleteHydratableInstance(hydrationParentFiber, firstAttemptedInstance);
+ }
+ hydrationParentFiber = fiber;
+ nextHydratableInstance = getFirstHydratableChild(nextInstance);
+}
+
+function prepareToHydrateHostInstance(fiber, rootContainerInstance, hostContext) {
+ if (!supportsHydration) {
+ reactProdInvariant('175');
+ }
+
+ var instance = fiber.stateNode;
+ var updatePayload = hydrateInstance(instance, fiber.type, fiber.memoizedProps, rootContainerInstance, hostContext, fiber);
+ // TODO: Type this specific to this type of component.
+ fiber.updateQueue = updatePayload;
+ // If the update payload indicates that there is a change or if there
+ // is a new ref we mark this as an update.
+ if (updatePayload !== null) {
+ return true;
+ }
+ return false;
+}
+
+function prepareToHydrateHostTextInstance(fiber) {
+ if (!supportsHydration) {
+ reactProdInvariant('176');
+ }
+
+ var textInstance = fiber.stateNode;
+ var textContent = fiber.memoizedProps;
+ var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber);
+ return shouldUpdate;
+}
+
+function skipPastDehydratedSuspenseInstance(fiber) {
+ if (!supportsHydration) {
+ reactProdInvariant('316');
+ }
+ var suspenseInstance = fiber.stateNode;
+ !suspenseInstance ? reactProdInvariant('317') : void 0;
+ nextHydratableInstance = getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance);
+}
+
+function popToNextHostParent(fiber) {
+ var parent = fiber.return;
+ while (parent !== null && parent.tag !== HostComponent && parent.tag !== HostRoot && parent.tag !== DehydratedSuspenseComponent) {
+ parent = parent.return;
+ }
+ hydrationParentFiber = parent;
+}
+
+function popHydrationState(fiber) {
+ if (!supportsHydration) {
+ return false;
+ }
+ if (fiber !== hydrationParentFiber) {
+ // We're deeper than the current hydration context, inside an inserted
+ // tree.
+ return false;
+ }
+ if (!isHydrating) {
+ // If we're not currently hydrating but we're in a hydration context, then
+ // we were an insertion and now need to pop up reenter hydration of our
+ // siblings.
+ popToNextHostParent(fiber);
+ isHydrating = true;
+ return false;
+ }
+
+ var type = fiber.type;
+
+ // If we have any remaining hydratable nodes, we need to delete them now.
+ // We only do this deeper than head and body since they tend to have random
+ // other nodes in them. We also ignore components with pure text content in
+ // side of them.
+ // TODO: Better heuristic.
+ if (fiber.tag !== HostComponent || type !== 'head' && type !== 'body' && !shouldSetTextContent(type, fiber.memoizedProps)) {
+ var nextInstance = nextHydratableInstance;
+ while (nextInstance) {
+ deleteHydratableInstance(fiber, nextInstance);
+ nextInstance = getNextHydratableSibling(nextInstance);
+ }
+ }
+
+ popToNextHostParent(fiber);
+ nextHydratableInstance = hydrationParentFiber ? getNextHydratableSibling(fiber.stateNode) : null;
+ return true;
+}
+
+function resetHydrationState() {
+ if (!supportsHydration) {
+ return;
+ }
+
+ hydrationParentFiber = null;
+ nextHydratableInstance = null;
+ isHydrating = false;
+}
+
+var ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner;
+
+var didReceiveUpdate = false;
+
+
+
+function reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime) {
+ if (current$$1 === null) {
+ // If this is a fresh new component that hasn't been rendered yet, we
+ // won't update its child set by applying minimal side-effects. Instead,
+ // we will add them all to the child before it gets rendered. That means
+ // we can optimize this reconciliation pass by not tracking side-effects.
+ workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
+ } else {
+ // If the current child is the same as the work in progress, it means that
+ // we haven't yet started any work on these children. Therefore, we use
+ // the clone algorithm to create a copy of all the current children.
+
+ // If we had any progressed work already, that is invalid at this point so
+ // let's throw it out.
+ workInProgress.child = reconcileChildFibers(workInProgress, current$$1.child, nextChildren, renderExpirationTime);
+ }
+}
+
+function forceUnmountCurrentAndReconcile(current$$1, workInProgress, nextChildren, renderExpirationTime) {
+ // This function is fork of reconcileChildren. It's used in cases where we
+ // want to reconcile without matching against the existing set. This has the
+ // effect of all current children being unmounted; even if the type and key
+ // are the same, the old child is unmounted and a new child is created.
+ //
+ // To do this, we're going to go through the reconcile algorithm twice. In
+ // the first pass, we schedule a deletion for all the current children by
+ // passing null.
+ workInProgress.child = reconcileChildFibers(workInProgress, current$$1.child, null, renderExpirationTime);
+ // In the second pass, we mount the new children. The trick here is that we
+ // pass null in place of where we usually pass the current child set. This has
+ // the effect of remounting all children regardless of whether their their
+ // identity matches.
+ workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
+}
+
+function updateForwardRef(current$$1, workInProgress, Component, nextProps, renderExpirationTime) {
+ // TODO: current can be non-null here even if the component
+ // hasn't yet mounted. This happens after the first render suspends.
+ // We'll need to figure out if this is fine or can cause issues.
+
+ var render = Component.render;
+ var ref = workInProgress.ref;
+
+ // The rest is a fork of updateFunctionComponent
+ var nextChildren = void 0;
+ prepareToReadContext(workInProgress, renderExpirationTime);
+ {
+ nextChildren = renderWithHooks(current$$1, workInProgress, render, nextProps, ref, renderExpirationTime);
+ }
+
+ if (current$$1 !== null && !didReceiveUpdate) {
+ bailoutHooks(current$$1, workInProgress, renderExpirationTime);
+ return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ }
+
+ // React DevTools reads this flag.
+ workInProgress.effectTag |= PerformedWork;
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ return workInProgress.child;
+}
+
+function updateMemoComponent(current$$1, workInProgress, Component, nextProps, updateExpirationTime, renderExpirationTime) {
+ if (current$$1 === null) {
+ var type = Component.type;
+ if (isSimpleFunctionComponent(type) && Component.compare === null &&
+ // SimpleMemoComponent codepath doesn't resolve outer props either.
+ Component.defaultProps === undefined) {
+ // If this is a plain function component without default props,
+ // and with only the default shallow comparison, we upgrade it
+ // to a SimpleMemoComponent to allow fast path updates.
+ workInProgress.tag = SimpleMemoComponent;
+ workInProgress.type = type;
+ return updateSimpleMemoComponent(current$$1, workInProgress, type, nextProps, updateExpirationTime, renderExpirationTime);
+ }
+ var child = createFiberFromTypeAndProps(Component.type, null, nextProps, null, workInProgress.mode, renderExpirationTime);
+ child.ref = workInProgress.ref;
+ child.return = workInProgress;
+ workInProgress.child = child;
+ return child;
+ }
+ var currentChild = current$$1.child; // This is always exactly one child
+ if (updateExpirationTime < renderExpirationTime) {
+ // This will be the props with resolved defaultProps,
+ // unlike current.memoizedProps which will be the unresolved ones.
+ var prevProps = currentChild.memoizedProps;
+ // Default to shallow comparison
+ var compare = Component.compare;
+ compare = compare !== null ? compare : shallowEqual;
+ if (compare(prevProps, nextProps) && current$$1.ref === workInProgress.ref) {
+ return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ }
+ }
+ // React DevTools reads this flag.
+ workInProgress.effectTag |= PerformedWork;
+ var newChild = createWorkInProgress(currentChild, nextProps, renderExpirationTime);
+ newChild.ref = workInProgress.ref;
+ newChild.return = workInProgress;
+ workInProgress.child = newChild;
+ return newChild;
+}
+
+function updateSimpleMemoComponent(current$$1, workInProgress, Component, nextProps, updateExpirationTime, renderExpirationTime) {
+ // TODO: current can be non-null here even if the component
+ // hasn't yet mounted. This happens when the inner render suspends.
+ // We'll need to figure out if this is fine or can cause issues.
+
+ if (current$$1 !== null) {
+ var prevProps = current$$1.memoizedProps;
+ if (shallowEqual(prevProps, nextProps) && current$$1.ref === workInProgress.ref) {
+ didReceiveUpdate = false;
+ if (updateExpirationTime < renderExpirationTime) {
+ return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ }
+ }
+ }
+ return updateFunctionComponent(current$$1, workInProgress, Component, nextProps, renderExpirationTime);
+}
+
+function updateFragment(current$$1, workInProgress, renderExpirationTime) {
+ var nextChildren = workInProgress.pendingProps;
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ return workInProgress.child;
+}
+
+function updateMode(current$$1, workInProgress, renderExpirationTime) {
+ var nextChildren = workInProgress.pendingProps.children;
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ return workInProgress.child;
+}
+
+function updateProfiler(current$$1, workInProgress, renderExpirationTime) {
+ if (enableProfilerTimer) {
+ workInProgress.effectTag |= Update;
+ }
+ var nextProps = workInProgress.pendingProps;
+ var nextChildren = nextProps.children;
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ return workInProgress.child;
+}
+
+function markRef(current$$1, workInProgress) {
+ var ref = workInProgress.ref;
+ if (current$$1 === null && ref !== null || current$$1 !== null && current$$1.ref !== ref) {
+ // Schedule a Ref effect
+ workInProgress.effectTag |= Ref;
+ }
+}
+
+function updateFunctionComponent(current$$1, workInProgress, Component, nextProps, renderExpirationTime) {
+ var unmaskedContext = getUnmaskedContext(workInProgress, Component, true);
+ var context = getMaskedContext(workInProgress, unmaskedContext);
+
+ var nextChildren = void 0;
+ prepareToReadContext(workInProgress, renderExpirationTime);
+ {
+ nextChildren = renderWithHooks(current$$1, workInProgress, Component, nextProps, context, renderExpirationTime);
+ }
+
+ if (current$$1 !== null && !didReceiveUpdate) {
+ bailoutHooks(current$$1, workInProgress, renderExpirationTime);
+ return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ }
+
+ // React DevTools reads this flag.
+ workInProgress.effectTag |= PerformedWork;
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ return workInProgress.child;
+}
+
+function updateClassComponent(current$$1, workInProgress, Component, nextProps, renderExpirationTime) {
+ var hasContext = void 0;
+ if (isContextProvider(Component)) {
+ hasContext = true;
+ pushContextProvider(workInProgress);
+ } else {
+ hasContext = false;
+ }
+ prepareToReadContext(workInProgress, renderExpirationTime);
+
+ var instance = workInProgress.stateNode;
+ var shouldUpdate = void 0;
+ if (instance === null) {
+ if (current$$1 !== null) {
+ // An class component without an instance only mounts if it suspended
+ // inside a non- concurrent tree, in an inconsistent state. We want to
+ // tree it like a new mount, even though an empty version of it already
+ // committed. Disconnect the alternate pointers.
+ current$$1.alternate = null;
+ workInProgress.alternate = null;
+ // Since this is conceptually a new fiber, schedule a Placement effect
+ workInProgress.effectTag |= Placement;
+ }
+ // In the initial pass we might need to construct the instance.
+ constructClassInstance(workInProgress, Component, nextProps, renderExpirationTime);
+ mountClassInstance(workInProgress, Component, nextProps, renderExpirationTime);
+ shouldUpdate = true;
+ } else if (current$$1 === null) {
+ // In a resume, we'll already have an instance we can reuse.
+ shouldUpdate = resumeMountClassInstance(workInProgress, Component, nextProps, renderExpirationTime);
+ } else {
+ shouldUpdate = updateClassInstance(current$$1, workInProgress, Component, nextProps, renderExpirationTime);
+ }
+ var nextUnitOfWork = finishClassComponent(current$$1, workInProgress, Component, shouldUpdate, hasContext, renderExpirationTime);
+ return nextUnitOfWork;
+}
+
+function finishClassComponent(current$$1, workInProgress, Component, shouldUpdate, hasContext, renderExpirationTime) {
+ // Refs should update even if shouldComponentUpdate returns false
+ markRef(current$$1, workInProgress);
+
+ var didCaptureError = (workInProgress.effectTag & DidCapture) !== NoEffect;
+
+ if (!shouldUpdate && !didCaptureError) {
+ // Context providers should defer to sCU for rendering
+ if (hasContext) {
+ invalidateContextProvider(workInProgress, Component, false);
+ }
+
+ return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ }
+
+ var instance = workInProgress.stateNode;
+
+ // Rerender
+ ReactCurrentOwner$2.current = workInProgress;
+ var nextChildren = void 0;
+ if (didCaptureError && typeof Component.getDerivedStateFromError !== 'function') {
+ // If we captured an error, but getDerivedStateFrom catch is not defined,
+ // unmount all the children. componentDidCatch will schedule an update to
+ // re-render a fallback. This is temporary until we migrate everyone to
+ // the new API.
+ // TODO: Warn in a future release.
+ nextChildren = null;
+
+ if (enableProfilerTimer) {
+ stopProfilerTimerIfRunning(workInProgress);
+ }
+ } else {
+ {
+ nextChildren = instance.render();
+ }
+ }
+
+ // React DevTools reads this flag.
+ workInProgress.effectTag |= PerformedWork;
+ if (current$$1 !== null && didCaptureError) {
+ // If we're recovering from an error, reconcile without reusing any of
+ // the existing children. Conceptually, the normal children and the children
+ // that are shown on error are two different sets, so we shouldn't reuse
+ // normal children even if their identities match.
+ forceUnmountCurrentAndReconcile(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ } else {
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ }
+
+ // Memoize state using the values we just used to render.
+ // TODO: Restructure so we never read values from the instance.
+ workInProgress.memoizedState = instance.state;
+
+ // The context might have changed so we need to recalculate it.
+ if (hasContext) {
+ invalidateContextProvider(workInProgress, Component, true);
+ }
+
+ return workInProgress.child;
+}
+
+function pushHostRootContext(workInProgress) {
+ var root = workInProgress.stateNode;
+ if (root.pendingContext) {
+ pushTopLevelContextObject(workInProgress, root.pendingContext, root.pendingContext !== root.context);
+ } else if (root.context) {
+ // Should always be set
+ pushTopLevelContextObject(workInProgress, root.context, false);
+ }
+ pushHostContainer(workInProgress, root.containerInfo);
+}
+
+function updateHostRoot(current$$1, workInProgress, renderExpirationTime) {
+ pushHostRootContext(workInProgress);
+ var updateQueue = workInProgress.updateQueue;
+ !(updateQueue !== null) ? reactProdInvariant('282') : void 0;
+ var nextProps = workInProgress.pendingProps;
+ var prevState = workInProgress.memoizedState;
+ var prevChildren = prevState !== null ? prevState.element : null;
+ processUpdateQueue(workInProgress, updateQueue, nextProps, null, renderExpirationTime);
+ var nextState = workInProgress.memoizedState;
+ // Caution: React DevTools currently depends on this property
+ // being called "element".
+ var nextChildren = nextState.element;
+ if (nextChildren === prevChildren) {
+ // If the state is the same as before, that's a bailout because we had
+ // no work that expires at this time.
+ resetHydrationState();
+ return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ }
+ var root = workInProgress.stateNode;
+ if ((current$$1 === null || current$$1.child === null) && root.hydrate && enterHydrationState(workInProgress)) {
+ // If we don't have any current children this might be the first pass.
+ // We always try to hydrate. If this isn't a hydration pass there won't
+ // be any children to hydrate which is effectively the same thing as
+ // not hydrating.
+
+ // This is a bit of a hack. We track the host root as a placement to
+ // know that we're currently in a mounting state. That way isMounted
+ // works as expected. We must reset this before committing.
+ // TODO: Delete this when we delete isMounted and findDOMNode.
+ workInProgress.effectTag |= Placement;
+
+ // Ensure that children mount into this root without tracking
+ // side-effects. This ensures that we don't store Placement effects on
+ // nodes that will be hydrated.
+ workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
+ } else {
+ // Otherwise reset hydration state in case we aborted and resumed another
+ // root.
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ resetHydrationState();
+ }
+ return workInProgress.child;
+}
+
+function updateHostComponent(current$$1, workInProgress, renderExpirationTime) {
+ pushHostContext(workInProgress);
+
+ if (current$$1 === null) {
+ tryToClaimNextHydratableInstance(workInProgress);
+ }
+
+ var type = workInProgress.type;
+ var nextProps = workInProgress.pendingProps;
+ var prevProps = current$$1 !== null ? current$$1.memoizedProps : null;
+
+ var nextChildren = nextProps.children;
+ var isDirectTextChild = shouldSetTextContent(type, nextProps);
+
+ if (isDirectTextChild) {
+ // We special case a direct text child of a host node. This is a common
+ // case. We won't handle it as a reified child. We will instead handle
+ // this in the host environment that also have access to this prop. That
+ // avoids allocating another HostText fiber and traversing it.
+ nextChildren = null;
+ } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) {
+ // If we're switching from a direct text child to a normal child, or to
+ // empty, we need to schedule the text content to be reset.
+ workInProgress.effectTag |= ContentReset;
+ }
+
+ markRef(current$$1, workInProgress);
+
+ // Check the host config to see if the children are offscreen/hidden.
+ if (renderExpirationTime !== Never && workInProgress.mode & ConcurrentMode && shouldDeprioritizeSubtree(type, nextProps)) {
+ // Schedule this fiber to re-render at offscreen priority. Then bailout.
+ workInProgress.expirationTime = workInProgress.childExpirationTime = Never;
+ return null;
+ }
+
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ return workInProgress.child;
+}
+
+function updateHostText(current$$1, workInProgress) {
+ if (current$$1 === null) {
+ tryToClaimNextHydratableInstance(workInProgress);
+ }
+ // Nothing to do here. This is terminal. We'll do the completion step
+ // immediately after.
+ return null;
+}
+
+function mountLazyComponent(_current, workInProgress, elementType, updateExpirationTime, renderExpirationTime) {
+ if (_current !== null) {
+ // An lazy component only mounts if it suspended inside a non-
+ // concurrent tree, in an inconsistent state. We want to treat it like
+ // a new mount, even though an empty version of it already committed.
+ // Disconnect the alternate pointers.
+ _current.alternate = null;
+ workInProgress.alternate = null;
+ // Since this is conceptually a new fiber, schedule a Placement effect
+ workInProgress.effectTag |= Placement;
+ }
+
+ var props = workInProgress.pendingProps;
+ // We can't start a User Timing measurement with correct label yet.
+ // Cancel and resume right after we know the tag.
+ cancelWorkTimer(workInProgress);
+ var Component = readLazyComponentType(elementType);
+ // Store the unwrapped component in the type.
+ workInProgress.type = Component;
+ var resolvedTag = workInProgress.tag = resolveLazyComponentTag(Component);
+ startWorkTimer(workInProgress);
+ var resolvedProps = resolveDefaultProps(Component, props);
+ var child = void 0;
+ switch (resolvedTag) {
+ case FunctionComponent:
+ {
+ child = updateFunctionComponent(null, workInProgress, Component, resolvedProps, renderExpirationTime);
+ break;
+ }
+ case ClassComponent:
+ {
+ child = updateClassComponent(null, workInProgress, Component, resolvedProps, renderExpirationTime);
+ break;
+ }
+ case ForwardRef:
+ {
+ child = updateForwardRef(null, workInProgress, Component, resolvedProps, renderExpirationTime);
+ break;
+ }
+ case MemoComponent:
+ {
+ child = updateMemoComponent(null, workInProgress, Component, resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too
+ updateExpirationTime, renderExpirationTime);
+ break;
+ }
+ default:
+ {
+ var hint = '';
+ reactProdInvariant('306', Component, hint);
+ }
+ }
+ return child;
+}
+
+function mountIncompleteClassComponent(_current, workInProgress, Component, nextProps, renderExpirationTime) {
+ if (_current !== null) {
+ // An incomplete component only mounts if it suspended inside a non-
+ // concurrent tree, in an inconsistent state. We want to treat it like
+ // a new mount, even though an empty version of it already committed.
+ // Disconnect the alternate pointers.
+ _current.alternate = null;
+ workInProgress.alternate = null;
+ // Since this is conceptually a new fiber, schedule a Placement effect
+ workInProgress.effectTag |= Placement;
+ }
+
+ // Promote the fiber to a class and try rendering again.
+ workInProgress.tag = ClassComponent;
+
+ // The rest of this function is a fork of `updateClassComponent`
+
+ // Push context providers early to prevent context stack mismatches.
+ // During mounting we don't know the child context yet as the instance doesn't exist.
+ // We will invalidate the child context in finishClassComponent() right after rendering.
+ var hasContext = void 0;
+ if (isContextProvider(Component)) {
+ hasContext = true;
+ pushContextProvider(workInProgress);
+ } else {
+ hasContext = false;
+ }
+ prepareToReadContext(workInProgress, renderExpirationTime);
+
+ constructClassInstance(workInProgress, Component, nextProps, renderExpirationTime);
+ mountClassInstance(workInProgress, Component, nextProps, renderExpirationTime);
+
+ return finishClassComponent(null, workInProgress, Component, true, hasContext, renderExpirationTime);
+}
+
+function mountIndeterminateComponent(_current, workInProgress, Component, renderExpirationTime) {
+ if (_current !== null) {
+ // An indeterminate component only mounts if it suspended inside a non-
+ // concurrent tree, in an inconsistent state. We want to treat it like
+ // a new mount, even though an empty version of it already committed.
+ // Disconnect the alternate pointers.
+ _current.alternate = null;
+ workInProgress.alternate = null;
+ // Since this is conceptually a new fiber, schedule a Placement effect
+ workInProgress.effectTag |= Placement;
+ }
+
+ var props = workInProgress.pendingProps;
+ var unmaskedContext = getUnmaskedContext(workInProgress, Component, false);
+ var context = getMaskedContext(workInProgress, unmaskedContext);
+
+ prepareToReadContext(workInProgress, renderExpirationTime);
+
+ var value = void 0;
+
+ {
+ value = renderWithHooks(null, workInProgress, Component, props, context, renderExpirationTime);
+ }
+ // React DevTools reads this flag.
+ workInProgress.effectTag |= PerformedWork;
+
+ if (typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) {
+ // Proceed under the assumption that this is a class instance
+ workInProgress.tag = ClassComponent;
+
+ // Throw out any hooks that were used.
+ resetHooks();
+
+ // Push context providers early to prevent context stack mismatches.
+ // During mounting we don't know the child context yet as the instance doesn't exist.
+ // We will invalidate the child context in finishClassComponent() right after rendering.
+ var hasContext = false;
+ if (isContextProvider(Component)) {
+ hasContext = true;
+ pushContextProvider(workInProgress);
+ } else {
+ hasContext = false;
+ }
+
+ workInProgress.memoizedState = value.state !== null && value.state !== undefined ? value.state : null;
+
+ var getDerivedStateFromProps = Component.getDerivedStateFromProps;
+ if (typeof getDerivedStateFromProps === 'function') {
+ applyDerivedStateFromProps(workInProgress, Component, getDerivedStateFromProps, props);
+ }
+
+ adoptClassInstance(workInProgress, value);
+ mountClassInstance(workInProgress, Component, props, renderExpirationTime);
+ return finishClassComponent(null, workInProgress, Component, true, hasContext, renderExpirationTime);
+ } else {
+ // Proceed under the assumption that this is a function component
+ workInProgress.tag = FunctionComponent;
+ reconcileChildren(null, workInProgress, value, renderExpirationTime);
+ return workInProgress.child;
+ }
+}
+
+function updateSuspenseComponent(current$$1, workInProgress, renderExpirationTime) {
+ var mode = workInProgress.mode;
+ var nextProps = workInProgress.pendingProps;
+
+ // We should attempt to render the primary children unless this boundary
+ // already suspended during this render (`alreadyCaptured` is true).
+ var nextState = workInProgress.memoizedState;
+
+ var nextDidTimeout = void 0;
+ if ((workInProgress.effectTag & DidCapture) === NoEffect) {
+ // This is the first attempt.
+ nextState = null;
+ nextDidTimeout = false;
+ } else {
+ // Something in this boundary's subtree already suspended. Switch to
+ // rendering the fallback children.
+ nextState = {
+ timedOutAt: nextState !== null ? nextState.timedOutAt : NoWork
+ };
+ nextDidTimeout = true;
+ workInProgress.effectTag &= ~DidCapture;
+ }
+
+ // This next part is a bit confusing. If the children timeout, we switch to
+ // showing the fallback children in place of the "primary" children.
+ // However, we don't want to delete the primary children because then their
+ // state will be lost (both the React state and the host state, e.g.
+ // uncontrolled form inputs). Instead we keep them mounted and hide them.
+ // Both the fallback children AND the primary children are rendered at the
+ // same time. Once the primary children are un-suspended, we can delete
+ // the fallback children — don't need to preserve their state.
+ //
+ // The two sets of children are siblings in the host environment, but
+ // semantically, for purposes of reconciliation, they are two separate sets.
+ // So we store them using two fragment fibers.
+ //
+ // However, we want to avoid allocating extra fibers for every placeholder.
+ // They're only necessary when the children time out, because that's the
+ // only time when both sets are mounted.
+ //
+ // So, the extra fragment fibers are only used if the children time out.
+ // Otherwise, we render the primary children directly. This requires some
+ // custom reconciliation logic to preserve the state of the primary
+ // children. It's essentially a very basic form of re-parenting.
+
+ // `child` points to the child fiber. In the normal case, this is the first
+ // fiber of the primary children set. In the timed-out case, it's a
+ // a fragment fiber containing the primary children.
+ var child = void 0;
+ // `next` points to the next fiber React should render. In the normal case,
+ // it's the same as `child`: the first fiber of the primary children set.
+ // In the timed-out case, it's a fragment fiber containing the *fallback*
+ // children -- we skip over the primary children entirely.
+ var next = void 0;
+ if (current$$1 === null) {
+ if (enableSuspenseServerRenderer) {
+ // If we're currently hydrating, try to hydrate this boundary.
+ // But only if this has a fallback.
+ if (nextProps.fallback !== undefined) {
+ tryToClaimNextHydratableInstance(workInProgress);
+ // This could've changed the tag if this was a dehydrated suspense component.
+ if (workInProgress.tag === DehydratedSuspenseComponent) {
+ return updateDehydratedSuspenseComponent(null, workInProgress, renderExpirationTime);
+ }
+ }
+ }
+
+ // This is the initial mount. This branch is pretty simple because there's
+ // no previous state that needs to be preserved.
+ if (nextDidTimeout) {
+ // Mount separate fragments for primary and fallback children.
+ var nextFallbackChildren = nextProps.fallback;
+ var primaryChildFragment = createFiberFromFragment(null, mode, NoWork, null);
+
+ if ((workInProgress.mode & ConcurrentMode) === NoContext) {
+ // Outside of concurrent mode, we commit the effects from the
+ var progressedState = workInProgress.memoizedState;
+ var progressedPrimaryChild = progressedState !== null ? workInProgress.child.child : workInProgress.child;
+ primaryChildFragment.child = progressedPrimaryChild;
+ }
+
+ var fallbackChildFragment = createFiberFromFragment(nextFallbackChildren, mode, renderExpirationTime, null);
+ primaryChildFragment.sibling = fallbackChildFragment;
+ child = primaryChildFragment;
+ // Skip the primary children, and continue working on the
+ // fallback children.
+ next = fallbackChildFragment;
+ child.return = next.return = workInProgress;
+ } else {
+ // Mount the primary children without an intermediate fragment fiber.
+ var nextPrimaryChildren = nextProps.children;
+ child = next = mountChildFibers(workInProgress, null, nextPrimaryChildren, renderExpirationTime);
+ }
+ } else {
+ // This is an update. This branch is more complicated because we need to
+ // ensure the state of the primary children is preserved.
+ var prevState = current$$1.memoizedState;
+ var prevDidTimeout = prevState !== null;
+ if (prevDidTimeout) {
+ // The current tree already timed out. That means each child set is
+ var currentPrimaryChildFragment = current$$1.child;
+ var currentFallbackChildFragment = currentPrimaryChildFragment.sibling;
+ if (nextDidTimeout) {
+ // Still timed out. Reuse the current primary children by cloning
+ // its fragment. We're going to skip over these entirely.
+ var _nextFallbackChildren = nextProps.fallback;
+ var _primaryChildFragment = createWorkInProgress(currentPrimaryChildFragment, currentPrimaryChildFragment.pendingProps, NoWork);
+
+ if ((workInProgress.mode & ConcurrentMode) === NoContext) {
+ // Outside of concurrent mode, we commit the effects from the
+ var _progressedState = workInProgress.memoizedState;
+ var _progressedPrimaryChild = _progressedState !== null ? workInProgress.child.child : workInProgress.child;
+ if (_progressedPrimaryChild !== currentPrimaryChildFragment.child) {
+ _primaryChildFragment.child = _progressedPrimaryChild;
+ }
+ }
+
+ // Because primaryChildFragment is a new fiber that we're inserting as the
+ // parent of a new tree, we need to set its treeBaseDuration.
+ if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
+ // treeBaseDuration is the sum of all the child tree base durations.
+ var treeBaseDuration = 0;
+ var hiddenChild = _primaryChildFragment.child;
+ while (hiddenChild !== null) {
+ treeBaseDuration += hiddenChild.treeBaseDuration;
+ hiddenChild = hiddenChild.sibling;
+ }
+ _primaryChildFragment.treeBaseDuration = treeBaseDuration;
+ }
+
+ // Clone the fallback child fragment, too. These we'll continue
+ // working on.
+ var _fallbackChildFragment = _primaryChildFragment.sibling = createWorkInProgress(currentFallbackChildFragment, _nextFallbackChildren, currentFallbackChildFragment.expirationTime);
+ child = _primaryChildFragment;
+ _primaryChildFragment.childExpirationTime = NoWork;
+ // Skip the primary children, and continue working on the
+ // fallback children.
+ next = _fallbackChildFragment;
+ child.return = next.return = workInProgress;
+ } else {
+ // No longer suspended. Switch back to showing the primary children,
+ // and remove the intermediate fragment fiber.
+ var _nextPrimaryChildren = nextProps.children;
+ var currentPrimaryChild = currentPrimaryChildFragment.child;
+ var primaryChild = reconcileChildFibers(workInProgress, currentPrimaryChild, _nextPrimaryChildren, renderExpirationTime);
+
+ // If this render doesn't suspend, we need to delete the fallback
+ // children. Wait until the complete phase, after we've confirmed the
+ // fallback is no longer needed.
+ // TODO: Would it be better to store the fallback fragment on
+ // the stateNode?
+
+ // Continue rendering the children, like we normally do.
+ child = next = primaryChild;
+ }
+ } else {
+ // The current tree has not already timed out. That means the primary
+ // children are not wrapped in a fragment fiber.
+ var _currentPrimaryChild = current$$1.child;
+ if (nextDidTimeout) {
+ // Timed out. Wrap the children in a fragment fiber to keep them
+ // separate from the fallback children.
+ var _nextFallbackChildren2 = nextProps.fallback;
+ var _primaryChildFragment2 = createFiberFromFragment(
+ // It shouldn't matter what the pending props are because we aren't
+ // going to render this fragment.
+ null, mode, NoWork, null);
+ _primaryChildFragment2.child = _currentPrimaryChild;
+
+ // Even though we're creating a new fiber, there are no new children,
+ // because we're reusing an already mounted tree. So we don't need to
+ // schedule a placement.
+ // primaryChildFragment.effectTag |= Placement;
+
+ if ((workInProgress.mode & ConcurrentMode) === NoContext) {
+ // Outside of concurrent mode, we commit the effects from the
+ var _progressedState2 = workInProgress.memoizedState;
+ var _progressedPrimaryChild2 = _progressedState2 !== null ? workInProgress.child.child : workInProgress.child;
+ _primaryChildFragment2.child = _progressedPrimaryChild2;
+ }
+
+ // Because primaryChildFragment is a new fiber that we're inserting as the
+ // parent of a new tree, we need to set its treeBaseDuration.
+ if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
+ // treeBaseDuration is the sum of all the child tree base durations.
+ var _treeBaseDuration = 0;
+ var _hiddenChild = _primaryChildFragment2.child;
+ while (_hiddenChild !== null) {
+ _treeBaseDuration += _hiddenChild.treeBaseDuration;
+ _hiddenChild = _hiddenChild.sibling;
+ }
+ _primaryChildFragment2.treeBaseDuration = _treeBaseDuration;
+ }
+
+ // Create a fragment from the fallback children, too.
+ var _fallbackChildFragment2 = _primaryChildFragment2.sibling = createFiberFromFragment(_nextFallbackChildren2, mode, renderExpirationTime, null);
+ _fallbackChildFragment2.effectTag |= Placement;
+ child = _primaryChildFragment2;
+ _primaryChildFragment2.childExpirationTime = NoWork;
+ // Skip the primary children, and continue working on the
+ // fallback children.
+ next = _fallbackChildFragment2;
+ child.return = next.return = workInProgress;
+ } else {
+ // Still haven't timed out. Continue rendering the children, like we
+ // normally do.
+ var _nextPrimaryChildren2 = nextProps.children;
+ next = child = reconcileChildFibers(workInProgress, _currentPrimaryChild, _nextPrimaryChildren2, renderExpirationTime);
+ }
+ }
+ workInProgress.stateNode = current$$1.stateNode;
+ }
+
+ workInProgress.memoizedState = nextState;
+ workInProgress.child = child;
+ return next;
+}
+
+function updateDehydratedSuspenseComponent(current$$1, workInProgress, renderExpirationTime) {
+ if (current$$1 === null) {
+ // During the first pass, we'll bail out and not drill into the children.
+ // Instead, we'll leave the content in place and try to hydrate it later.
+ workInProgress.expirationTime = Never;
+ return null;
+ }
+ // We use childExpirationTime to indicate that a child might depend on context, so if
+ // any context has changed, we need to treat is as if the input might have changed.
+ var hasContextChanged$$1 = current$$1.childExpirationTime >= renderExpirationTime;
+ if (didReceiveUpdate || hasContextChanged$$1) {
+ // This boundary has changed since the first render. This means that we are now unable to
+ // hydrate it. We might still be able to hydrate it using an earlier expiration time but
+ // during this render we can't. Instead, we're going to delete the whole subtree and
+ // instead inject a new real Suspense boundary to take its place, which may render content
+ // or fallback. The real Suspense boundary will suspend for a while so we have some time
+ // to ensure it can produce real content, but all state and pending events will be lost.
+
+ // Detach from the current dehydrated boundary.
+ current$$1.alternate = null;
+ workInProgress.alternate = null;
+
+ // Insert a deletion in the effect list.
+ var returnFiber = workInProgress.return;
+ !(returnFiber !== null) ? reactProdInvariant('315') : void 0;
+ var last = returnFiber.lastEffect;
+ if (last !== null) {
+ last.nextEffect = current$$1;
+ returnFiber.lastEffect = current$$1;
+ } else {
+ returnFiber.firstEffect = returnFiber.lastEffect = current$$1;
+ }
+ current$$1.nextEffect = null;
+ current$$1.effectTag = Deletion;
+
+ // Upgrade this work in progress to a real Suspense component.
+ workInProgress.tag = SuspenseComponent;
+ workInProgress.stateNode = null;
+ workInProgress.memoizedState = null;
+ // This is now an insertion.
+ workInProgress.effectTag |= Placement;
+ // Retry as a real Suspense component.
+ return updateSuspenseComponent(null, workInProgress, renderExpirationTime);
+ }
+ if ((workInProgress.effectTag & DidCapture) === NoEffect) {
+ // This is the first attempt.
+ reenterHydrationStateFromDehydratedSuspenseInstance(workInProgress);
+ var nextProps = workInProgress.pendingProps;
+ var nextChildren = nextProps.children;
+ workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
+ return workInProgress.child;
+ } else {
+ // Something suspended. Leave the existing children in place.
+ // TODO: In non-concurrent mode, should we commit the nodes we have hydrated so far?
+ workInProgress.child = null;
+ return null;
+ }
+}
+
+function updatePortalComponent(current$$1, workInProgress, renderExpirationTime) {
+ pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
+ var nextChildren = workInProgress.pendingProps;
+ if (current$$1 === null) {
+ // Portals are special because we don't append the children during mount
+ // but at commit. Therefore we need to track insertions which the normal
+ // flow doesn't do during mount. This doesn't happen at the root because
+ // the root always starts with a "current" with a null child.
+ // TODO: Consider unifying this with how the root works.
+ workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
+ } else {
+ reconcileChildren(current$$1, workInProgress, nextChildren, renderExpirationTime);
+ }
+ return workInProgress.child;
+}
+
+function updateContextProvider(current$$1, workInProgress, renderExpirationTime) {
+ var providerType = workInProgress.type;
+ var context = providerType._context;
+
+ var newProps = workInProgress.pendingProps;
+ var oldProps = workInProgress.memoizedProps;
+
+ var newValue = newProps.value;
+
+ pushProvider(workInProgress, newValue);
+
+ if (oldProps !== null) {
+ var oldValue = oldProps.value;
+ var changedBits = calculateChangedBits(context, newValue, oldValue);
+ if (changedBits === 0) {
+ // No change. Bailout early if children are the same.
+ if (oldProps.children === newProps.children && !hasContextChanged()) {
+ return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ }
+ } else {
+ // The context value changed. Search for matching consumers and schedule
+ // them to update.
+ propagateContextChange(workInProgress, context, changedBits, renderExpirationTime);
+ }
+ }
+
+ var newChildren = newProps.children;
+ reconcileChildren(current$$1, workInProgress, newChildren, renderExpirationTime);
+ return workInProgress.child;
+}
+
+function updateContextConsumer(current$$1, workInProgress, renderExpirationTime) {
+ var context = workInProgress.type;
+ // The logic below for Context differs depending on PROD or DEV mode. In
+ // DEV mode, we create a separate object for Context.Consumer that acts
+ // like a proxy to Context. This proxy object adds unnecessary code in PROD
+ // so we use the old behaviour (Context.Consumer references Context) to
+ // reduce size and overhead. The separate object references context via
+ // a property called "_context", which also gives us the ability to check
+ // in DEV mode if this property exists or not and warn if it does not.
+ var newProps = workInProgress.pendingProps;
+ var render = newProps.children;
+
+ prepareToReadContext(workInProgress, renderExpirationTime);
+ var newValue = readContext(context, newProps.unstable_observedBits);
+ var newChildren = void 0;
+ {
+ newChildren = render(newValue);
+ }
+
+ // React DevTools reads this flag.
+ workInProgress.effectTag |= PerformedWork;
+ reconcileChildren(current$$1, workInProgress, newChildren, renderExpirationTime);
+ return workInProgress.child;
+}
+
+function markWorkInProgressReceivedUpdate() {
+ didReceiveUpdate = true;
+}
+
+function bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime) {
+ cancelWorkTimer(workInProgress);
+
+ if (current$$1 !== null) {
+ // Reuse previous context list
+ workInProgress.contextDependencies = current$$1.contextDependencies;
+ }
+
+ if (enableProfilerTimer) {
+ // Don't update "base" render times for bailouts.
+ stopProfilerTimerIfRunning(workInProgress);
+ }
+
+ // Check if the children have any pending work.
+ var childExpirationTime = workInProgress.childExpirationTime;
+ if (childExpirationTime < renderExpirationTime) {
+ // The children don't have any work either. We can skip them.
+ // TODO: Once we add back resuming, we should check if the children are
+ // a work-in-progress set. If so, we need to transfer their effects.
+ return null;
+ } else {
+ // This fiber doesn't have work, but its subtree does. Clone the child
+ // fibers and continue.
+ cloneChildFibers(current$$1, workInProgress);
+ return workInProgress.child;
+ }
+}
+
+function beginWork(current$$1, workInProgress, renderExpirationTime) {
+ var updateExpirationTime = workInProgress.expirationTime;
+
+ if (current$$1 !== null) {
+ var oldProps = current$$1.memoizedProps;
+ var newProps = workInProgress.pendingProps;
+
+ if (oldProps !== newProps || hasContextChanged()) {
+ // If props or context changed, mark the fiber as having performed work.
+ // This may be unset if the props are determined to be equal later (memo).
+ didReceiveUpdate = true;
+ } else if (updateExpirationTime < renderExpirationTime) {
+ didReceiveUpdate = false;
+ // This fiber does not have any pending work. Bailout without entering
+ // the begin phase. There's still some bookkeeping we that needs to be done
+ // in this optimized path, mostly pushing stuff onto the stack.
+ switch (workInProgress.tag) {
+ case HostRoot:
+ pushHostRootContext(workInProgress);
+ resetHydrationState();
+ break;
+ case HostComponent:
+ pushHostContext(workInProgress);
+ break;
+ case ClassComponent:
+ {
+ var Component = workInProgress.type;
+ if (isContextProvider(Component)) {
+ pushContextProvider(workInProgress);
+ }
+ break;
+ }
+ case HostPortal:
+ pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
+ break;
+ case ContextProvider:
+ {
+ var newValue = workInProgress.memoizedProps.value;
+ pushProvider(workInProgress, newValue);
+ break;
+ }
+ case Profiler:
+ if (enableProfilerTimer) {
+ workInProgress.effectTag |= Update;
+ }
+ break;
+ case SuspenseComponent:
+ {
+ var state = workInProgress.memoizedState;
+ var didTimeout = state !== null;
+ if (didTimeout) {
+ // If this boundary is currently timed out, we need to decide
+ // whether to retry the primary children, or to skip over it and
+ // go straight to the fallback. Check the priority of the primary
+ var primaryChildFragment = workInProgress.child;
+ var primaryChildExpirationTime = primaryChildFragment.childExpirationTime;
+ if (primaryChildExpirationTime !== NoWork && primaryChildExpirationTime >= renderExpirationTime) {
+ // The primary children have pending work. Use the normal path
+ // to attempt to render the primary children again.
+ return updateSuspenseComponent(current$$1, workInProgress, renderExpirationTime);
+ } else {
+ // The primary children do not have pending work with sufficient
+ // priority. Bailout.
+ var child = bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ if (child !== null) {
+ // The fallback children have pending work. Skip over the
+ // primary children and work on the fallback.
+ return child.sibling;
+ } else {
+ return null;
+ }
+ }
+ }
+ break;
+ }
+ case DehydratedSuspenseComponent:
+ {
+ if (enableSuspenseServerRenderer) {
+ // We know that this component will suspend again because if it has
+ // been unsuspended it has committed as a regular Suspense component.
+ // If it needs to be retried, it should have work scheduled on it.
+ workInProgress.effectTag |= DidCapture;
+ break;
+ }
+ }
+ }
+ return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
+ }
+ } else {
+ didReceiveUpdate = false;
+ }
+
+ // Before entering the begin phase, clear the expiration time.
+ workInProgress.expirationTime = NoWork;
+
+ switch (workInProgress.tag) {
+ case IndeterminateComponent:
+ {
+ var elementType = workInProgress.elementType;
+ return mountIndeterminateComponent(current$$1, workInProgress, elementType, renderExpirationTime);
+ }
+ case LazyComponent:
+ {
+ var _elementType = workInProgress.elementType;
+ return mountLazyComponent(current$$1, workInProgress, _elementType, updateExpirationTime, renderExpirationTime);
+ }
+ case FunctionComponent:
+ {
+ var _Component = workInProgress.type;
+ var unresolvedProps = workInProgress.pendingProps;
+ var resolvedProps = workInProgress.elementType === _Component ? unresolvedProps : resolveDefaultProps(_Component, unresolvedProps);
+ return updateFunctionComponent(current$$1, workInProgress, _Component, resolvedProps, renderExpirationTime);
+ }
+ case ClassComponent:
+ {
+ var _Component2 = workInProgress.type;
+ var _unresolvedProps = workInProgress.pendingProps;
+ var _resolvedProps = workInProgress.elementType === _Component2 ? _unresolvedProps : resolveDefaultProps(_Component2, _unresolvedProps);
+ return updateClassComponent(current$$1, workInProgress, _Component2, _resolvedProps, renderExpirationTime);
+ }
+ case HostRoot:
+ return updateHostRoot(current$$1, workInProgress, renderExpirationTime);
+ case HostComponent:
+ return updateHostComponent(current$$1, workInProgress, renderExpirationTime);
+ case HostText:
+ return updateHostText(current$$1, workInProgress);
+ case SuspenseComponent:
+ return updateSuspenseComponent(current$$1, workInProgress, renderExpirationTime);
+ case HostPortal:
+ return updatePortalComponent(current$$1, workInProgress, renderExpirationTime);
+ case ForwardRef:
+ {
+ var type = workInProgress.type;
+ var _unresolvedProps2 = workInProgress.pendingProps;
+ var _resolvedProps2 = workInProgress.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2);
+ return updateForwardRef(current$$1, workInProgress, type, _resolvedProps2, renderExpirationTime);
+ }
+ case Fragment:
+ return updateFragment(current$$1, workInProgress, renderExpirationTime);
+ case Mode:
+ return updateMode(current$$1, workInProgress, renderExpirationTime);
+ case Profiler:
+ return updateProfiler(current$$1, workInProgress, renderExpirationTime);
+ case ContextProvider:
+ return updateContextProvider(current$$1, workInProgress, renderExpirationTime);
+ case ContextConsumer:
+ return updateContextConsumer(current$$1, workInProgress, renderExpirationTime);
+ case MemoComponent:
+ {
+ var _type2 = workInProgress.type;
+ var _unresolvedProps3 = workInProgress.pendingProps;
+ // Resolve outer props first, then resolve inner props.
+ var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3);
+ _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3);
+ return updateMemoComponent(current$$1, workInProgress, _type2, _resolvedProps3, updateExpirationTime, renderExpirationTime);
+ }
+ case SimpleMemoComponent:
+ {
+ return updateSimpleMemoComponent(current$$1, workInProgress, workInProgress.type, workInProgress.pendingProps, updateExpirationTime, renderExpirationTime);
+ }
+ case IncompleteClassComponent:
+ {
+ var _Component3 = workInProgress.type;
+ var _unresolvedProps4 = workInProgress.pendingProps;
+ var _resolvedProps4 = workInProgress.elementType === _Component3 ? _unresolvedProps4 : resolveDefaultProps(_Component3, _unresolvedProps4);
+ return mountIncompleteClassComponent(current$$1, workInProgress, _Component3, _resolvedProps4, renderExpirationTime);
+ }
+ case DehydratedSuspenseComponent:
+ {
+ if (enableSuspenseServerRenderer) {
+ return updateDehydratedSuspenseComponent(current$$1, workInProgress, renderExpirationTime);
+ }
+ break;
+ }
+ }
+ reactProdInvariant('156');
+}
+
+var valueCursor = createCursor(null);
+
+var currentlyRenderingFiber = null;
+var lastContextDependency = null;
+var lastContextWithAllBitsObserved = null;
+
+function resetContextDependences() {
+ // This is called right before React yields execution, to ensure `readContext`
+ // cannot be called outside the render phase.
+ currentlyRenderingFiber = null;
+ lastContextDependency = null;
+ lastContextWithAllBitsObserved = null;
+
+}
+
+
+
+
+
+function pushProvider(providerFiber, nextValue) {
+ var context = providerFiber.type._context;
+
+ if (isPrimaryRenderer) {
+ push(valueCursor, context._currentValue, providerFiber);
+
+ context._currentValue = nextValue;
+
+ } else {
+ push(valueCursor, context._currentValue2, providerFiber);
+
+ context._currentValue2 = nextValue;
+
+ }
+}
+
+function popProvider(providerFiber) {
+ var currentValue = valueCursor.current;
+
+ pop(valueCursor, providerFiber);
+
+ var context = providerFiber.type._context;
+ if (isPrimaryRenderer) {
+ context._currentValue = currentValue;
+ } else {
+ context._currentValue2 = currentValue;
+ }
+}
+
+function calculateChangedBits(context, newValue, oldValue) {
+ if (is(oldValue, newValue)) {
+ // No change
+ return 0;
+ } else {
+ var changedBits = typeof context._calculateChangedBits === 'function' ? context._calculateChangedBits(oldValue, newValue) : maxSigned31BitInt;
+
+ return changedBits | 0;
+ }
+}
+
+function scheduleWorkOnParentPath(parent, renderExpirationTime) {
+ // Update the child expiration time of all the ancestors, including
+ // the alternates.
+ var node = parent;
+ while (node !== null) {
+ var alternate = node.alternate;
+ if (node.childExpirationTime < renderExpirationTime) {
+ node.childExpirationTime = renderExpirationTime;
+ if (alternate !== null && alternate.childExpirationTime < renderExpirationTime) {
+ alternate.childExpirationTime = renderExpirationTime;
+ }
+ } else if (alternate !== null && alternate.childExpirationTime < renderExpirationTime) {
+ alternate.childExpirationTime = renderExpirationTime;
+ } else {
+ // Neither alternate was updated, which means the rest of the
+ // ancestor path already has sufficient priority.
+ break;
+ }
+ node = node.return;
+ }
+}
+
+function propagateContextChange(workInProgress, context, changedBits, renderExpirationTime) {
+ var fiber = workInProgress.child;
+ if (fiber !== null) {
+ // Set the return pointer of the child to the work-in-progress fiber.
+ fiber.return = workInProgress;
+ }
+ while (fiber !== null) {
+ var nextFiber = void 0;
+
+ // Visit this fiber.
+ var list = fiber.contextDependencies;
+ if (list !== null) {
+ nextFiber = fiber.child;
+
+ var dependency = list.first;
+ while (dependency !== null) {
+ // Check if the context matches.
+ if (dependency.context === context && (dependency.observedBits & changedBits) !== 0) {
+ // Match! Schedule an update on this fiber.
+
+ if (fiber.tag === ClassComponent) {
+ // Schedule a force update on the work-in-progress.
+ var update = createUpdate(renderExpirationTime);
+ update.tag = ForceUpdate;
+ // TODO: Because we don't have a work-in-progress, this will add the
+ // update to the current fiber, too, which means it will persist even if
+ // this render is thrown away. Since it's a race condition, not sure it's
+ // worth fixing.
+ enqueueUpdate(fiber, update);
+ }
+
+ if (fiber.expirationTime < renderExpirationTime) {
+ fiber.expirationTime = renderExpirationTime;
+ }
+ var alternate = fiber.alternate;
+ if (alternate !== null && alternate.expirationTime < renderExpirationTime) {
+ alternate.expirationTime = renderExpirationTime;
+ }
+
+ scheduleWorkOnParentPath(fiber.return, renderExpirationTime);
+
+ // Mark the expiration time on the list, too.
+ if (list.expirationTime < renderExpirationTime) {
+ list.expirationTime = renderExpirationTime;
+ }
+
+ // Since we already found a match, we can stop traversing the
+ // dependency list.
+ break;
+ }
+ dependency = dependency.next;
+ }
+ } else if (fiber.tag === ContextProvider) {
+ // Don't scan deeper if this is a matching provider
+ nextFiber = fiber.type === workInProgress.type ? null : fiber.child;
+ } else if (enableSuspenseServerRenderer && fiber.tag === DehydratedSuspenseComponent) {
+ // If a dehydrated suspense component is in this subtree, we don't know
+ // if it will have any context consumers in it. The best we can do is
+ // mark it as having updates on its children.
+ if (fiber.expirationTime < renderExpirationTime) {
+ fiber.expirationTime = renderExpirationTime;
+ }
+ var _alternate = fiber.alternate;
+ if (_alternate !== null && _alternate.expirationTime < renderExpirationTime) {
+ _alternate.expirationTime = renderExpirationTime;
+ }
+ // This is intentionally passing this fiber as the parent
+ // because we want to schedule this fiber as having work
+ // on its children. We'll use the childExpirationTime on
+ // this fiber to indicate that a context has changed.
+ scheduleWorkOnParentPath(fiber, renderExpirationTime);
+ nextFiber = fiber.sibling;
+ } else {
+ // Traverse down.
+ nextFiber = fiber.child;
+ }
+
+ if (nextFiber !== null) {
+ // Set the return pointer of the child to the work-in-progress fiber.
+ nextFiber.return = fiber;
+ } else {
+ // No child. Traverse to next sibling.
+ nextFiber = fiber;
+ while (nextFiber !== null) {
+ if (nextFiber === workInProgress) {
+ // We're back to the root of this subtree. Exit.
+ nextFiber = null;
+ break;
+ }
+ var sibling = nextFiber.sibling;
+ if (sibling !== null) {
+ // Set the return pointer of the sibling to the work-in-progress fiber.
+ sibling.return = nextFiber.return;
+ nextFiber = sibling;
+ break;
+ }
+ // No more siblings. Traverse up.
+ nextFiber = nextFiber.return;
+ }
+ }
+ fiber = nextFiber;
+ }
+}
+
+function prepareToReadContext(workInProgress, renderExpirationTime) {
+ currentlyRenderingFiber = workInProgress;
+ lastContextDependency = null;
+ lastContextWithAllBitsObserved = null;
+
+ var currentDependencies = workInProgress.contextDependencies;
+ if (currentDependencies !== null && currentDependencies.expirationTime >= renderExpirationTime) {
+ // Context list has a pending update. Mark that this fiber performed work.
+ markWorkInProgressReceivedUpdate();
+ }
+
+ // Reset the work-in-progress list
+ workInProgress.contextDependencies = null;
+}
+
+function readContext(context, observedBits) {
+ if (lastContextWithAllBitsObserved === context) {
+ // Nothing to do. We already observe everything in this context.
+ } else if (observedBits === false || observedBits === 0) {
+ // Do not observe any updates.
+ } else {
+ var resolvedObservedBits = void 0; // Avoid deopting on observable arguments or heterogeneous types.
+ if (typeof observedBits !== 'number' || observedBits === maxSigned31BitInt) {
+ // Observe all updates.
+ lastContextWithAllBitsObserved = context;
+ resolvedObservedBits = maxSigned31BitInt;
+ } else {
+ resolvedObservedBits = observedBits;
+ }
+
+ var contextItem = {
+ context: context,
+ observedBits: resolvedObservedBits,
+ next: null
+ };
+
+ if (lastContextDependency === null) {
+ !(currentlyRenderingFiber !== null) ? reactProdInvariant('308') : void 0;
+
+ // This is the first dependency for this component. Create a new list.
+ lastContextDependency = contextItem;
+ currentlyRenderingFiber.contextDependencies = {
+ first: contextItem,
+ expirationTime: NoWork
+ };
+ } else {
+ // Append a new context item.
+ lastContextDependency = lastContextDependency.next = contextItem;
+ }
+ }
+ return isPrimaryRenderer ? context._currentValue : context._currentValue2;
+}
+
+// UpdateQueue is a linked list of prioritized updates.
+//
+// Like fibers, update queues come in pairs: a current queue, which represents
+// the visible state of the screen, and a work-in-progress queue, which can be
+// mutated and processed asynchronously before it is committed — a form of
+// double buffering. If a work-in-progress render is discarded before finishing,
+// we create a new work-in-progress by cloning the current queue.
+//
+// Both queues share a persistent, singly-linked list structure. To schedule an
+// update, we append it to the end of both queues. Each queue maintains a
+// pointer to first update in the persistent list that hasn't been processed.
+// The work-in-progress pointer always has a position equal to or greater than
+// the current queue, since we always work on that one. The current queue's
+// pointer is only updated during the commit phase, when we swap in the
+// work-in-progress.
+//
+// For example:
+//
+// Current pointer: A - B - C - D - E - F
+// Work-in-progress pointer: D - E - F
+// ^
+// The work-in-progress queue has
+// processed more updates than current.
+//
+// The reason we append to both queues is because otherwise we might drop
+// updates without ever processing them. For example, if we only add updates to
+// the work-in-progress queue, some updates could be lost whenever a work-in
+// -progress render restarts by cloning from current. Similarly, if we only add
+// updates to the current queue, the updates will be lost whenever an already
+// in-progress queue commits and swaps with the current queue. However, by
+// adding to both queues, we guarantee that the update will be part of the next
+// work-in-progress. (And because the work-in-progress queue becomes the
+// current queue once it commits, there's no danger of applying the same
+// update twice.)
+//
+// Prioritization
+// --------------
+//
+// Updates are not sorted by priority, but by insertion; new updates are always
+// appended to the end of the list.
+//
+// The priority is still important, though. When processing the update queue
+// during the render phase, only the updates with sufficient priority are
+// included in the result. If we skip an update because it has insufficient
+// priority, it remains in the queue to be processed later, during a lower
+// priority render. Crucially, all updates subsequent to a skipped update also
+// remain in the queue *regardless of their priority*. That means high priority
+// updates are sometimes processed twice, at two separate priorities. We also
+// keep track of a base state, that represents the state before the first
+// update in the queue is applied.
+//
+// For example:
+//
+// Given a base state of '', and the following queue of updates
+//
+// A1 - B2 - C1 - D2
+//
+// where the number indicates the priority, and the update is applied to the
+// previous state by appending a letter, React will process these updates as
+// two separate renders, one per distinct priority level:
+//
+// First render, at priority 1:
+// Base state: ''
+// Updates: [A1, C1]
+// Result state: 'AC'
+//
+// Second render, at priority 2:
+// Base state: 'A' <- The base state does not include C1,
+// because B2 was skipped.
+// Updates: [B2, C1, D2] <- C1 was rebased on top of B2
+// Result state: 'ABCD'
+//
+// Because we process updates in insertion order, and rebase high priority
+// updates when preceding updates are skipped, the final result is deterministic
+// regardless of priority. Intermediate state may vary according to system
+// resources, but the final state is always the same.
+
+var UpdateState = 0;
+var ReplaceState = 1;
+var ForceUpdate = 2;
+var CaptureUpdate = 3;
+
+// Global state that is reset at the beginning of calling `processUpdateQueue`.
+// It should only be read right after calling `processUpdateQueue`, via
+// `checkHasForceUpdateAfterProcessing`.
+var hasForceUpdate = false;
+
+
+function createUpdateQueue(baseState) {
+ var queue = {
+ baseState: baseState,
+ firstUpdate: null,
+ lastUpdate: null,
+ firstCapturedUpdate: null,
+ lastCapturedUpdate: null,
+ firstEffect: null,
+ lastEffect: null,
+ firstCapturedEffect: null,
+ lastCapturedEffect: null
+ };
+ return queue;
+}
+
+function cloneUpdateQueue(currentQueue) {
+ var queue = {
+ baseState: currentQueue.baseState,
+ firstUpdate: currentQueue.firstUpdate,
+ lastUpdate: currentQueue.lastUpdate,
+
+ // TODO: With resuming, if we bail out and resuse the child tree, we should
+ // keep these effects.
+ firstCapturedUpdate: null,
+ lastCapturedUpdate: null,
+
+ firstEffect: null,
+ lastEffect: null,
+
+ firstCapturedEffect: null,
+ lastCapturedEffect: null
+ };
+ return queue;
+}
+
+function createUpdate(expirationTime) {
+ return {
+ expirationTime: expirationTime,
+
+ tag: UpdateState,
+ payload: null,
+ callback: null,
+
+ next: null,
+ nextEffect: null
+ };
+}
+
+function appendUpdateToQueue(queue, update) {
+ // Append the update to the end of the list.
+ if (queue.lastUpdate === null) {
+ // Queue is empty
+ queue.firstUpdate = queue.lastUpdate = update;
+ } else {
+ queue.lastUpdate.next = update;
+ queue.lastUpdate = update;
+ }
+}
+
+function enqueueUpdate(fiber, update) {
+ // Update queues are created lazily.
+ var alternate = fiber.alternate;
+ var queue1 = void 0;
+ var queue2 = void 0;
+ if (alternate === null) {
+ // There's only one fiber.
+ queue1 = fiber.updateQueue;
+ queue2 = null;
+ if (queue1 === null) {
+ queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);
+ }
+ } else {
+ // There are two owners.
+ queue1 = fiber.updateQueue;
+ queue2 = alternate.updateQueue;
+ if (queue1 === null) {
+ if (queue2 === null) {
+ // Neither fiber has an update queue. Create new ones.
+ queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);
+ queue2 = alternate.updateQueue = createUpdateQueue(alternate.memoizedState);
+ } else {
+ // Only one fiber has an update queue. Clone to create a new one.
+ queue1 = fiber.updateQueue = cloneUpdateQueue(queue2);
+ }
+ } else {
+ if (queue2 === null) {
+ // Only one fiber has an update queue. Clone to create a new one.
+ queue2 = alternate.updateQueue = cloneUpdateQueue(queue1);
+ } else {
+ // Both owners have an update queue.
+ }
+ }
+ }
+ if (queue2 === null || queue1 === queue2) {
+ // There's only a single queue.
+ appendUpdateToQueue(queue1, update);
+ } else {
+ // There are two queues. We need to append the update to both queues,
+ // while accounting for the persistent structure of the list — we don't
+ // want the same update to be added multiple times.
+ if (queue1.lastUpdate === null || queue2.lastUpdate === null) {
+ // One of the queues is not empty. We must add the update to both queues.
+ appendUpdateToQueue(queue1, update);
+ appendUpdateToQueue(queue2, update);
+ } else {
+ // Both queues are non-empty. The last update is the same in both lists,
+ // because of structural sharing. So, only append to one of the lists.
+ appendUpdateToQueue(queue1, update);
+ // But we still need to update the `lastUpdate` pointer of queue2.
+ queue2.lastUpdate = update;
+ }
+ }
+
+
+}
+
+function enqueueCapturedUpdate(workInProgress, update) {
+ // Captured updates go into a separate list, and only on the work-in-
+ // progress queue.
+ var workInProgressQueue = workInProgress.updateQueue;
+ if (workInProgressQueue === null) {
+ workInProgressQueue = workInProgress.updateQueue = createUpdateQueue(workInProgress.memoizedState);
+ } else {
+ // TODO: I put this here rather than createWorkInProgress so that we don't
+ // clone the queue unnecessarily. There's probably a better way to
+ // structure this.
+ workInProgressQueue = ensureWorkInProgressQueueIsAClone(workInProgress, workInProgressQueue);
+ }
+
+ // Append the update to the end of the list.
+ if (workInProgressQueue.lastCapturedUpdate === null) {
+ // This is the first render phase update
+ workInProgressQueue.firstCapturedUpdate = workInProgressQueue.lastCapturedUpdate = update;
+ } else {
+ workInProgressQueue.lastCapturedUpdate.next = update;
+ workInProgressQueue.lastCapturedUpdate = update;
+ }
+}
+
+function ensureWorkInProgressQueueIsAClone(workInProgress, queue) {
+ var current = workInProgress.alternate;
+ if (current !== null) {
+ // If the work-in-progress queue is equal to the current queue,
+ // we need to clone it first.
+ if (queue === current.updateQueue) {
+ queue = workInProgress.updateQueue = cloneUpdateQueue(queue);
+ }
+ }
+ return queue;
+}
+
+function getStateFromUpdate(workInProgress, queue, update, prevState, nextProps, instance) {
+ switch (update.tag) {
+ case ReplaceState:
+ {
+ var _payload = update.payload;
+ if (typeof _payload === 'function') {
+ // Updater function
+ var nextState = _payload.call(instance, prevState, nextProps);
+ return nextState;
+ }
+ // State object
+ return _payload;
+ }
+ case CaptureUpdate:
+ {
+ workInProgress.effectTag = workInProgress.effectTag & ~ShouldCapture | DidCapture;
+ }
+ // Intentional fallthrough
+ case UpdateState:
+ {
+ var _payload2 = update.payload;
+ var partialState = void 0;
+ if (typeof _payload2 === 'function') {
+ // Updater function
+ partialState = _payload2.call(instance, prevState, nextProps);
+
+ } else {
+ // Partial state object
+ partialState = _payload2;
+ }
+ if (partialState === null || partialState === undefined) {
+ // Null and undefined are treated as no-ops.
+ return prevState;
+ }
+ // Merge the partial state and the previous state.
+ return _assign({}, prevState, partialState);
+ }
+ case ForceUpdate:
+ {
+ hasForceUpdate = true;
+ return prevState;
+ }
+ }
+ return prevState;
+}
+
+function processUpdateQueue(workInProgress, queue, props, instance, renderExpirationTime) {
+ hasForceUpdate = false;
+
+ queue = ensureWorkInProgressQueueIsAClone(workInProgress, queue);
+
+ var newBaseState = queue.baseState;
+ var newFirstUpdate = null;
+ var newExpirationTime = NoWork;
+
+ // Iterate through the list of updates to compute the result.
+ var update = queue.firstUpdate;
+ var resultState = newBaseState;
+ while (update !== null) {
+ var updateExpirationTime = update.expirationTime;
+ if (updateExpirationTime < renderExpirationTime) {
+ // This update does not have sufficient priority. Skip it.
+ if (newFirstUpdate === null) {
+ // This is the first skipped update. It will be the first update in
+ // the new list.
+ newFirstUpdate = update;
+ // Since this is the first update that was skipped, the current result
+ // is the new base state.
+ newBaseState = resultState;
+ }
+ // Since this update will remain in the list, update the remaining
+ // expiration time.
+ if (newExpirationTime < updateExpirationTime) {
+ newExpirationTime = updateExpirationTime;
+ }
+ } else {
+ // This update does have sufficient priority. Process it and compute
+ // a new result.
+ resultState = getStateFromUpdate(workInProgress, queue, update, resultState, props, instance);
+ var _callback = update.callback;
+ if (_callback !== null) {
+ workInProgress.effectTag |= Callback;
+ // Set this to null, in case it was mutated during an aborted render.
+ update.nextEffect = null;
+ if (queue.lastEffect === null) {
+ queue.firstEffect = queue.lastEffect = update;
+ } else {
+ queue.lastEffect.nextEffect = update;
+ queue.lastEffect = update;
+ }
+ }
+ }
+ // Continue to the next update.
+ update = update.next;
+ }
+
+ // Separately, iterate though the list of captured updates.
+ var newFirstCapturedUpdate = null;
+ update = queue.firstCapturedUpdate;
+ while (update !== null) {
+ var _updateExpirationTime = update.expirationTime;
+ if (_updateExpirationTime < renderExpirationTime) {
+ // This update does not have sufficient priority. Skip it.
+ if (newFirstCapturedUpdate === null) {
+ // This is the first skipped captured update. It will be the first
+ // update in the new list.
+ newFirstCapturedUpdate = update;
+ // If this is the first update that was skipped, the current result is
+ // the new base state.
+ if (newFirstUpdate === null) {
+ newBaseState = resultState;
+ }
+ }
+ // Since this update will remain in the list, update the remaining
+ // expiration time.
+ if (newExpirationTime < _updateExpirationTime) {
+ newExpirationTime = _updateExpirationTime;
+ }
+ } else {
+ // This update does have sufficient priority. Process it and compute
+ // a new result.
+ resultState = getStateFromUpdate(workInProgress, queue, update, resultState, props, instance);
+ var _callback2 = update.callback;
+ if (_callback2 !== null) {
+ workInProgress.effectTag |= Callback;
+ // Set this to null, in case it was mutated during an aborted render.
+ update.nextEffect = null;
+ if (queue.lastCapturedEffect === null) {
+ queue.firstCapturedEffect = queue.lastCapturedEffect = update;
+ } else {
+ queue.lastCapturedEffect.nextEffect = update;
+ queue.lastCapturedEffect = update;
+ }
+ }
+ }
+ update = update.next;
+ }
+
+ if (newFirstUpdate === null) {
+ queue.lastUpdate = null;
+ }
+ if (newFirstCapturedUpdate === null) {
+ queue.lastCapturedUpdate = null;
+ } else {
+ workInProgress.effectTag |= Callback;
+ }
+ if (newFirstUpdate === null && newFirstCapturedUpdate === null) {
+ // We processed every update, without skipping. That means the new base
+ // state is the same as the result state.
+ newBaseState = resultState;
+ }
+
+ queue.baseState = newBaseState;
+ queue.firstUpdate = newFirstUpdate;
+ queue.firstCapturedUpdate = newFirstCapturedUpdate;
+
+ // Set the remaining expiration time to be whatever is remaining in the queue.
+ // This should be fine because the only two other things that contribute to
+ // expiration time are props and context. We're already in the middle of the
+ // begin phase by the time we start processing the queue, so we've already
+ // dealt with the props. Context in components that specify
+ // shouldComponentUpdate is tricky; but we'll have to account for
+ // that regardless.
+ workInProgress.expirationTime = newExpirationTime;
+ workInProgress.memoizedState = resultState;
+
+
+}
+
+function callCallback(callback, context) {
+ !(typeof callback === 'function') ? reactProdInvariant('191', callback) : void 0;
+ callback.call(context);
+}
+
+function resetHasForceUpdateBeforeProcessing() {
+ hasForceUpdate = false;
+}
+
+function checkHasForceUpdateAfterProcessing() {
+ return hasForceUpdate;
+}
+
+function commitUpdateQueue(finishedWork, finishedQueue, instance, renderExpirationTime) {
+ // If the finished render included captured updates, and there are still
+ // lower priority updates left over, we need to keep the captured updates
+ // in the queue so that they are rebased and not dropped once we process the
+ // queue again at the lower priority.
+ if (finishedQueue.firstCapturedUpdate !== null) {
+ // Join the captured update list to the end of the normal list.
+ if (finishedQueue.lastUpdate !== null) {
+ finishedQueue.lastUpdate.next = finishedQueue.firstCapturedUpdate;
+ finishedQueue.lastUpdate = finishedQueue.lastCapturedUpdate;
+ }
+ // Clear the list of captured updates.
+ finishedQueue.firstCapturedUpdate = finishedQueue.lastCapturedUpdate = null;
+ }
+
+ // Commit the effects
+ commitUpdateEffects(finishedQueue.firstEffect, instance);
+ finishedQueue.firstEffect = finishedQueue.lastEffect = null;
+
+ commitUpdateEffects(finishedQueue.firstCapturedEffect, instance);
+ finishedQueue.firstCapturedEffect = finishedQueue.lastCapturedEffect = null;
+}
+
+function commitUpdateEffects(effect, instance) {
+ while (effect !== null) {
+ var _callback3 = effect.callback;
+ if (_callback3 !== null) {
+ effect.callback = null;
+ callCallback(_callback3, instance);
+ }
+ effect = effect.nextEffect;
+ }
+}
+
+function createCapturedValue(value, source) {
+ // If the value is an error, call this function immediately after it is thrown
+ // so the stack is accurate.
+ return {
+ value: value,
+ source: source,
+ stack: getStackByFiberInDevAndProd(source)
+ };
+}
+
+function markUpdate(workInProgress) {
+ // Tag the fiber with an update effect. This turns a Placement into
+ // a PlacementAndUpdate.
+ workInProgress.effectTag |= Update;
+}
+
+function markRef$1(workInProgress) {
+ workInProgress.effectTag |= Ref;
+}
+
+var appendAllChildren = void 0;
+var updateHostContainer = void 0;
+var updateHostComponent$1 = void 0;
+var updateHostText$1 = void 0;
+if (supportsMutation) {
+ // Mutation mode
+
+ appendAllChildren = function (parent, workInProgress, needsVisibilityToggle, isHidden) {
+ // We only have the top Fiber that was created but we need recurse down its
+ // children to find all the terminal nodes.
+ var node = workInProgress.child;
+ while (node !== null) {
+ if (node.tag === HostComponent || node.tag === HostText) {
+ appendInitialChild(parent, node.stateNode);
+ } else if (node.tag === HostPortal) {
+ // If we have a portal child, then we don't want to traverse
+ // down its children. Instead, we'll get insertions from each child in
+ // the portal directly.
+ } else if (node.child !== null) {
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ if (node === workInProgress) {
+ return;
+ }
+ while (node.sibling === null) {
+ if (node.return === null || node.return === workInProgress) {
+ return;
+ }
+ node = node.return;
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ }
+ };
+
+ updateHostContainer = function (workInProgress) {
+ // Noop
+ };
+ updateHostComponent$1 = function (current, workInProgress, type, newProps, rootContainerInstance) {
+ // If we have an alternate, that means this is an update and we need to
+ // schedule a side-effect to do the updates.
+ var oldProps = current.memoizedProps;
+ if (oldProps === newProps) {
+ // In mutation mode, this is sufficient for a bailout because
+ // we won't touch this node even if children changed.
+ return;
+ }
+
+ // If we get updated because one of our children updated, we don't
+ // have newProps so we'll have to reuse them.
+ // TODO: Split the update API as separate for the props vs. children.
+ // Even better would be if children weren't special cased at all tho.
+ var instance = workInProgress.stateNode;
+ var currentHostContext = getHostContext();
+ // TODO: Experiencing an error where oldProps is null. Suggests a host
+ // component is hitting the resume path. Figure out why. Possibly
+ // related to `hidden`.
+ var updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext);
+ // TODO: Type this specific to this type of component.
+ workInProgress.updateQueue = updatePayload;
+ // If the update payload indicates that there is a change or if there
+ // is a new ref we mark this as an update. All the work is done in commitWork.
+ if (updatePayload) {
+ markUpdate(workInProgress);
+ }
+ };
+ updateHostText$1 = function (current, workInProgress, oldText, newText) {
+ // If the text differs, mark it as an update. All the work in done in commitWork.
+ if (oldText !== newText) {
+ markUpdate(workInProgress);
+ }
+ };
+} else if (supportsPersistence) {
+ // Persistent host tree mode
+
+ appendAllChildren = function (parent, workInProgress, needsVisibilityToggle, isHidden) {
+ // We only have the top Fiber that was created but we need recurse down its
+ // children to find all the terminal nodes.
+ var node = workInProgress.child;
+ while (node !== null) {
+ // eslint-disable-next-line no-labels
+ branches: if (node.tag === HostComponent) {
+ var instance = node.stateNode;
+ if (needsVisibilityToggle) {
+ var props = node.memoizedProps;
+ var type = node.type;
+ if (isHidden) {
+ // This child is inside a timed out tree. Hide it.
+ instance = cloneHiddenInstance(instance, type, props, node);
+ } else {
+ // This child was previously inside a timed out tree. If it was not
+ // updated during this render, it may need to be unhidden. Clone
+ // again to be sure.
+ instance = cloneUnhiddenInstance(instance, type, props, node);
+ }
+ node.stateNode = instance;
+ }
+ appendInitialChild(parent, instance);
+ } else if (node.tag === HostText) {
+ var _instance = node.stateNode;
+ if (needsVisibilityToggle) {
+ var text = node.memoizedProps;
+ var rootContainerInstance = getRootHostContainer();
+ var currentHostContext = getHostContext();
+ if (isHidden) {
+ _instance = createHiddenTextInstance(text, rootContainerInstance, currentHostContext, workInProgress);
+ } else {
+ _instance = createTextInstance(text, rootContainerInstance, currentHostContext, workInProgress);
+ }
+ node.stateNode = _instance;
+ }
+ appendInitialChild(parent, _instance);
+ } else if (node.tag === HostPortal) {
+ // If we have a portal child, then we don't want to traverse
+ // down its children. Instead, we'll get insertions from each child in
+ // the portal directly.
+ } else if (node.tag === SuspenseComponent) {
+ var current = node.alternate;
+ if (current !== null) {
+ var oldState = current.memoizedState;
+ var newState = node.memoizedState;
+ var oldIsHidden = oldState !== null;
+ var newIsHidden = newState !== null;
+ if (oldIsHidden !== newIsHidden) {
+ // The placeholder either just timed out or switched back to the normal
+ // children after having previously timed out. Toggle the visibility of
+ // the direct host children.
+ var primaryChildParent = newIsHidden ? node.child : node;
+ if (primaryChildParent !== null) {
+ appendAllChildren(parent, primaryChildParent, true, newIsHidden);
+ }
+ // eslint-disable-next-line no-labels
+ break branches;
+ }
+ }
+ if (node.child !== null) {
+ // Continue traversing like normal
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ } else if (node.child !== null) {
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ // $FlowFixMe This is correct but Flow is confused by the labeled break.
+ node = node;
+ if (node === workInProgress) {
+ return;
+ }
+ while (node.sibling === null) {
+ if (node.return === null || node.return === workInProgress) {
+ return;
+ }
+ node = node.return;
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ }
+ };
+
+ // An unfortunate fork of appendAllChildren because we have two different parent types.
+ var appendAllChildrenToContainer = function (containerChildSet, workInProgress, needsVisibilityToggle, isHidden) {
+ // We only have the top Fiber that was created but we need recurse down its
+ // children to find all the terminal nodes.
+ var node = workInProgress.child;
+ while (node !== null) {
+ // eslint-disable-next-line no-labels
+ branches: if (node.tag === HostComponent) {
+ var instance = node.stateNode;
+ if (needsVisibilityToggle) {
+ var props = node.memoizedProps;
+ var type = node.type;
+ if (isHidden) {
+ // This child is inside a timed out tree. Hide it.
+ instance = cloneHiddenInstance(instance, type, props, node);
+ } else {
+ // This child was previously inside a timed out tree. If it was not
+ // updated during this render, it may need to be unhidden. Clone
+ // again to be sure.
+ instance = cloneUnhiddenInstance(instance, type, props, node);
+ }
+ node.stateNode = instance;
+ }
+ appendChildToContainerChildSet(containerChildSet, instance);
+ } else if (node.tag === HostText) {
+ var _instance2 = node.stateNode;
+ if (needsVisibilityToggle) {
+ var text = node.memoizedProps;
+ var rootContainerInstance = getRootHostContainer();
+ var currentHostContext = getHostContext();
+ if (isHidden) {
+ _instance2 = createHiddenTextInstance(text, rootContainerInstance, currentHostContext, workInProgress);
+ } else {
+ _instance2 = createTextInstance(text, rootContainerInstance, currentHostContext, workInProgress);
+ }
+ node.stateNode = _instance2;
+ }
+ appendChildToContainerChildSet(containerChildSet, _instance2);
+ } else if (node.tag === HostPortal) {
+ // If we have a portal child, then we don't want to traverse
+ // down its children. Instead, we'll get insertions from each child in
+ // the portal directly.
+ } else if (node.tag === SuspenseComponent) {
+ var current = node.alternate;
+ if (current !== null) {
+ var oldState = current.memoizedState;
+ var newState = node.memoizedState;
+ var oldIsHidden = oldState !== null;
+ var newIsHidden = newState !== null;
+ if (oldIsHidden !== newIsHidden) {
+ // The placeholder either just timed out or switched back to the normal
+ // children after having previously timed out. Toggle the visibility of
+ // the direct host children.
+ var primaryChildParent = newIsHidden ? node.child : node;
+ if (primaryChildParent !== null) {
+ appendAllChildrenToContainer(containerChildSet, primaryChildParent, true, newIsHidden);
+ }
+ // eslint-disable-next-line no-labels
+ break branches;
+ }
+ }
+ if (node.child !== null) {
+ // Continue traversing like normal
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ } else if (node.child !== null) {
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ // $FlowFixMe This is correct but Flow is confused by the labeled break.
+ node = node;
+ if (node === workInProgress) {
+ return;
+ }
+ while (node.sibling === null) {
+ if (node.return === null || node.return === workInProgress) {
+ return;
+ }
+ node = node.return;
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ }
+ };
+ updateHostContainer = function (workInProgress) {
+ var portalOrRoot = workInProgress.stateNode;
+ var childrenUnchanged = workInProgress.firstEffect === null;
+ if (childrenUnchanged) {
+ // No changes, just reuse the existing instance.
+ } else {
+ var container = portalOrRoot.containerInfo;
+ var newChildSet = createContainerChildSet(container);
+ // If children might have changed, we have to add them all to the set.
+ appendAllChildrenToContainer(newChildSet, workInProgress, false, false);
+ portalOrRoot.pendingChildren = newChildSet;
+ // Schedule an update on the container to swap out the container.
+ markUpdate(workInProgress);
+ finalizeContainerChildren(container, newChildSet);
+ }
+ };
+ updateHostComponent$1 = function (current, workInProgress, type, newProps, rootContainerInstance) {
+ var currentInstance = current.stateNode;
+ var oldProps = current.memoizedProps;
+ // If there are no effects associated with this node, then none of our children had any updates.
+ // This guarantees that we can reuse all of them.
+ var childrenUnchanged = workInProgress.firstEffect === null;
+ if (childrenUnchanged && oldProps === newProps) {
+ // No changes, just reuse the existing instance.
+ // Note that this might release a previous clone.
+ workInProgress.stateNode = currentInstance;
+ return;
+ }
+ var recyclableInstance = workInProgress.stateNode;
+ var currentHostContext = getHostContext();
+ var updatePayload = null;
+ if (oldProps !== newProps) {
+ updatePayload = prepareUpdate(recyclableInstance, type, oldProps, newProps, rootContainerInstance, currentHostContext);
+ }
+ if (childrenUnchanged && updatePayload === null) {
+ // No changes, just reuse the existing instance.
+ // Note that this might release a previous clone.
+ workInProgress.stateNode = currentInstance;
+ return;
+ }
+ var newInstance = cloneInstance(currentInstance, updatePayload, type, oldProps, newProps, workInProgress, childrenUnchanged, recyclableInstance);
+ if (finalizeInitialChildren(newInstance, type, newProps, rootContainerInstance, currentHostContext)) {
+ markUpdate(workInProgress);
+ }
+ workInProgress.stateNode = newInstance;
+ if (childrenUnchanged) {
+ // If there are no other effects in this tree, we need to flag this node as having one.
+ // Even though we're not going to use it for anything.
+ // Otherwise parents won't know that there are new children to propagate upwards.
+ markUpdate(workInProgress);
+ } else {
+ // If children might have changed, we have to add them all to the set.
+ appendAllChildren(newInstance, workInProgress, false, false);
+ }
+ };
+ updateHostText$1 = function (current, workInProgress, oldText, newText) {
+ if (oldText !== newText) {
+ // If the text content differs, we'll create a new text instance for it.
+ var rootContainerInstance = getRootHostContainer();
+ var currentHostContext = getHostContext();
+ workInProgress.stateNode = createTextInstance(newText, rootContainerInstance, currentHostContext, workInProgress);
+ // We'll have to mark it as having an effect, even though we won't use the effect for anything.
+ // This lets the parents know that at least one of their children has changed.
+ markUpdate(workInProgress);
+ }
+ };
+} else {
+ // No host operations
+ updateHostContainer = function (workInProgress) {
+ // Noop
+ };
+ updateHostComponent$1 = function (current, workInProgress, type, newProps, rootContainerInstance) {
+ // Noop
+ };
+ updateHostText$1 = function (current, workInProgress, oldText, newText) {
+ // Noop
+ };
+}
+
+function completeWork(current, workInProgress, renderExpirationTime) {
+ var newProps = workInProgress.pendingProps;
+
+ switch (workInProgress.tag) {
+ case IndeterminateComponent:
+ break;
+ case LazyComponent:
+ break;
+ case SimpleMemoComponent:
+ case FunctionComponent:
+ break;
+ case ClassComponent:
+ {
+ var Component = workInProgress.type;
+ if (isContextProvider(Component)) {
+ popContext(workInProgress);
+ }
+ break;
+ }
+ case HostRoot:
+ {
+ popHostContainer(workInProgress);
+ popTopLevelContextObject(workInProgress);
+ var fiberRoot = workInProgress.stateNode;
+ if (fiberRoot.pendingContext) {
+ fiberRoot.context = fiberRoot.pendingContext;
+ fiberRoot.pendingContext = null;
+ }
+ if (current === null || current.child === null) {
+ // If we hydrated, pop so that we can delete any remaining children
+ // that weren't hydrated.
+ popHydrationState(workInProgress);
+ // This resets the hacky state to fix isMounted before committing.
+ // TODO: Delete this when we delete isMounted and findDOMNode.
+ workInProgress.effectTag &= ~Placement;
+ }
+ updateHostContainer(workInProgress);
+ break;
+ }
+ case HostComponent:
+ {
+ popHostContext(workInProgress);
+ var rootContainerInstance = getRootHostContainer();
+ var type = workInProgress.type;
+ if (current !== null && workInProgress.stateNode != null) {
+ updateHostComponent$1(current, workInProgress, type, newProps, rootContainerInstance);
+
+ if (current.ref !== workInProgress.ref) {
+ markRef$1(workInProgress);
+ }
+ } else {
+ if (!newProps) {
+ !(workInProgress.stateNode !== null) ? reactProdInvariant('166') : void 0;
+ // This can happen when we abort work.
+ break;
+ }
+
+ var currentHostContext = getHostContext();
+ // TODO: Move createInstance to beginWork and keep it on a context
+ // "stack" as the parent. Then append children as we go in beginWork
+ // or completeWork depending on we want to add then top->down or
+ // bottom->up. Top->down is faster in IE11.
+ var wasHydrated = popHydrationState(workInProgress);
+ if (wasHydrated) {
+ // TODO: Move this and createInstance step into the beginPhase
+ // to consolidate.
+ if (prepareToHydrateHostInstance(workInProgress, rootContainerInstance, currentHostContext)) {
+ // If changes to the hydrated node needs to be applied at the
+ // commit-phase we mark this as such.
+ markUpdate(workInProgress);
+ }
+ } else {
+ var instance = createInstance(type, newProps, rootContainerInstance, currentHostContext, workInProgress);
+
+ appendAllChildren(instance, workInProgress, false, false);
+
+ // Certain renderers require commit-time effects for initial mount.
+ // (eg DOM renderer supports auto-focus for certain elements).
+ // Make sure such renderers get scheduled for later work.
+ if (finalizeInitialChildren(instance, type, newProps, rootContainerInstance, currentHostContext)) {
+ markUpdate(workInProgress);
+ }
+ workInProgress.stateNode = instance;
+ }
+
+ if (workInProgress.ref !== null) {
+ // If there is a ref on a host node we need to schedule a callback
+ markRef$1(workInProgress);
+ }
+ }
+ break;
+ }
+ case HostText:
+ {
+ var newText = newProps;
+ if (current && workInProgress.stateNode != null) {
+ var oldText = current.memoizedProps;
+ // If we have an alternate, that means this is an update and we need
+ // to schedule a side-effect to do the updates.
+ updateHostText$1(current, workInProgress, oldText, newText);
+ } else {
+ if (typeof newText !== 'string') {
+ !(workInProgress.stateNode !== null) ? reactProdInvariant('166') : void 0;
+ // This can happen when we abort work.
+ }
+ var _rootContainerInstance = getRootHostContainer();
+ var _currentHostContext = getHostContext();
+ var _wasHydrated = popHydrationState(workInProgress);
+ if (_wasHydrated) {
+ if (prepareToHydrateHostTextInstance(workInProgress)) {
+ markUpdate(workInProgress);
+ }
+ } else {
+ workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext, workInProgress);
+ }
+ }
+ break;
+ }
+ case ForwardRef:
+ break;
+ case SuspenseComponent:
+ {
+ var nextState = workInProgress.memoizedState;
+ if ((workInProgress.effectTag & DidCapture) !== NoEffect) {
+ // Something suspended. Re-render with the fallback children.
+ workInProgress.expirationTime = renderExpirationTime;
+ // Do not reset the effect list.
+ return workInProgress;
+ }
+
+ var nextDidTimeout = nextState !== null;
+ var prevDidTimeout = current !== null && current.memoizedState !== null;
+
+ if (current !== null && !nextDidTimeout && prevDidTimeout) {
+ // We just switched from the fallback to the normal children. Delete
+ // the fallback.
+ // TODO: Would it be better to store the fallback fragment on
+ var currentFallbackChild = current.child.sibling;
+ if (currentFallbackChild !== null) {
+ // Deletions go at the beginning of the return fiber's effect list
+ var first = workInProgress.firstEffect;
+ if (first !== null) {
+ workInProgress.firstEffect = currentFallbackChild;
+ currentFallbackChild.nextEffect = first;
+ } else {
+ workInProgress.firstEffect = workInProgress.lastEffect = currentFallbackChild;
+ currentFallbackChild.nextEffect = null;
+ }
+ currentFallbackChild.effectTag = Deletion;
+ }
+ }
+
+ if (nextDidTimeout || prevDidTimeout) {
+ // If the children are hidden, or if they were previous hidden, schedule
+ // an effect to toggle their visibility. This is also used to attach a
+ // retry listener to the promise.
+ workInProgress.effectTag |= Update;
+ }
+ break;
+ }
+ case Fragment:
+ break;
+ case Mode:
+ break;
+ case Profiler:
+ break;
+ case HostPortal:
+ popHostContainer(workInProgress);
+ updateHostContainer(workInProgress);
+ break;
+ case ContextProvider:
+ // Pop provider fiber
+ popProvider(workInProgress);
+ break;
+ case ContextConsumer:
+ break;
+ case MemoComponent:
+ break;
+ case IncompleteClassComponent:
+ {
+ // Same as class component case. I put it down here so that the tags are
+ // sequential to ensure this switch is compiled to a jump table.
+ var _Component = workInProgress.type;
+ if (isContextProvider(_Component)) {
+ popContext(workInProgress);
+ }
+ break;
+ }
+ case DehydratedSuspenseComponent:
+ {
+ if (enableSuspenseServerRenderer) {
+ if (current === null) {
+ var _wasHydrated2 = popHydrationState(workInProgress);
+ !_wasHydrated2 ? reactProdInvariant('318') : void 0;
+ skipPastDehydratedSuspenseInstance(workInProgress);
+ } else if ((workInProgress.effectTag & DidCapture) === NoEffect) {
+ // This boundary did not suspend so it's now hydrated.
+ // To handle any future suspense cases, we're going to now upgrade it
+ // to a Suspense component. We detach it from the existing current fiber.
+ current.alternate = null;
+ workInProgress.alternate = null;
+ workInProgress.tag = SuspenseComponent;
+ workInProgress.memoizedState = null;
+ workInProgress.stateNode = null;
+ }
+ }
+ break;
+ }
+ default:
+ reactProdInvariant('156');
+ }
+
+ return null;
+}
+
+function shouldCaptureSuspense(workInProgress) {
+ // In order to capture, the Suspense component must have a fallback prop.
+ if (workInProgress.memoizedProps.fallback === undefined) {
+ return false;
+ }
+ // If it was the primary children that just suspended, capture and render the
+ // fallback. Otherwise, don't capture and bubble to the next boundary.
+ var nextState = workInProgress.memoizedState;
+ return nextState === null;
+}
+
+// This module is forked in different environments.
+// By default, return `true` to log errors to the console.
+// Forks can return `false` if this isn't desirable.
+function showErrorDialog(capturedError) {
+ return true;
+}
+
+function logCapturedError(capturedError) {
+ var logError = showErrorDialog(capturedError);
+
+ // Allow injected showErrorDialog() to prevent default console.error logging.
+ // This enables renderers like ReactNative to better manage redbox behavior.
+ if (logError === false) {
+ return;
+ }
+
+ var error = capturedError.error;
+ {
+ // In production, we print the error directly.
+ // This will include the message, the JS stack, and anything the browser wants to show.
+ // We pass the error object instead of custom message so that the browser displays the error natively.
+ console.error(error);
+ }
+}
+
+var PossiblyWeakSet$1 = typeof WeakSet === 'function' ? WeakSet : Set;
+
+function logError(boundary, errorInfo) {
+ var source = errorInfo.source;
+ var stack = errorInfo.stack;
+ if (stack === null && source !== null) {
+ stack = getStackByFiberInDevAndProd(source);
+ }
+
+ var capturedError = {
+ componentName: source !== null ? getComponentName(source.type) : null,
+ componentStack: stack !== null ? stack : '',
+ error: errorInfo.value,
+ errorBoundary: null,
+ errorBoundaryName: null,
+ errorBoundaryFound: false,
+ willRetry: false
+ };
+
+ if (boundary !== null && boundary.tag === ClassComponent) {
+ capturedError.errorBoundary = boundary.stateNode;
+ capturedError.errorBoundaryName = getComponentName(boundary.type);
+ capturedError.errorBoundaryFound = true;
+ capturedError.willRetry = true;
+ }
+
+ try {
+ logCapturedError(capturedError);
+ } catch (e) {
+ // This method must not throw, or React internal state will get messed up.
+ // If console.error is overridden, or logCapturedError() shows a dialog that throws,
+ // we want to report this error outside of the normal stack as a last resort.
+ // https://github.com/facebook/react/issues/13188
+ setTimeout(function () {
+ throw e;
+ });
+ }
+}
+
+var callComponentWillUnmountWithTimer = function (current$$1, instance) {
+ startPhaseTimer(current$$1, 'componentWillUnmount');
+ instance.props = current$$1.memoizedProps;
+ instance.state = current$$1.memoizedState;
+ instance.componentWillUnmount();
+ stopPhaseTimer();
+};
+
+// Capture errors so they don't interrupt unmounting.
+function safelyCallComponentWillUnmount(current$$1, instance) {
+ {
+ try {
+ callComponentWillUnmountWithTimer(current$$1, instance);
+ } catch (unmountError) {
+ captureCommitPhaseError(current$$1, unmountError);
+ }
+ }
+}
+
+function safelyDetachRef(current$$1) {
+ var ref = current$$1.ref;
+ if (ref !== null) {
+ if (typeof ref === 'function') {
+ {
+ try {
+ ref(null);
+ } catch (refError) {
+ captureCommitPhaseError(current$$1, refError);
+ }
+ }
+ } else {
+ ref.current = null;
+ }
+ }
+}
+
+function safelyCallDestroy(current$$1, destroy) {
+ {
+ try {
+ destroy();
+ } catch (error) {
+ captureCommitPhaseError(current$$1, error);
+ }
+ }
+}
+
+function commitBeforeMutationLifeCycles(current$$1, finishedWork) {
+ switch (finishedWork.tag) {
+ case FunctionComponent:
+ case ForwardRef:
+ case SimpleMemoComponent:
+ {
+ commitHookEffectList(UnmountSnapshot, NoEffect$1, finishedWork);
+ return;
+ }
+ case ClassComponent:
+ {
+ if (finishedWork.effectTag & Snapshot) {
+ if (current$$1 !== null) {
+ var prevProps = current$$1.memoizedProps;
+ var prevState = current$$1.memoizedState;
+ startPhaseTimer(finishedWork, 'getSnapshotBeforeUpdate');
+ var instance = finishedWork.stateNode;
+ // We could update instance props and state here,
+ // but instead we rely on them being set during last render.
+ // TODO: revisit this when we implement resuming.
+ var snapshot = instance.getSnapshotBeforeUpdate(finishedWork.elementType === finishedWork.type ? prevProps : resolveDefaultProps(finishedWork.type, prevProps), prevState);
+ instance.__reactInternalSnapshotBeforeUpdate = snapshot;
+ stopPhaseTimer();
+ }
+ }
+ return;
+ }
+ case HostRoot:
+ case HostComponent:
+ case HostText:
+ case HostPortal:
+ case IncompleteClassComponent:
+ // Nothing to do for these component types
+ return;
+ default:
+ {
+ reactProdInvariant('163');
+ }
+ }
+}
+
+function commitHookEffectList(unmountTag, mountTag, finishedWork) {
+ var updateQueue = finishedWork.updateQueue;
+ var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;
+ if (lastEffect !== null) {
+ var firstEffect = lastEffect.next;
+ var effect = firstEffect;
+ do {
+ if ((effect.tag & unmountTag) !== NoEffect$1) {
+ // Unmount
+ var destroy = effect.destroy;
+ effect.destroy = undefined;
+ if (destroy !== undefined) {
+ destroy();
+ }
+ }
+ if ((effect.tag & mountTag) !== NoEffect$1) {
+ // Mount
+ var create = effect.create;
+ effect.destroy = create();
+
+
+ }
+ effect = effect.next;
+ } while (effect !== firstEffect);
+ }
+}
+
+function commitPassiveHookEffects(finishedWork) {
+ commitHookEffectList(UnmountPassive, NoEffect$1, finishedWork);
+ commitHookEffectList(NoEffect$1, MountPassive, finishedWork);
+}
+
+function commitLifeCycles(finishedRoot, current$$1, finishedWork, committedExpirationTime) {
+ switch (finishedWork.tag) {
+ case FunctionComponent:
+ case ForwardRef:
+ case SimpleMemoComponent:
+ {
+ commitHookEffectList(UnmountLayout, MountLayout, finishedWork);
+ break;
+ }
+ case ClassComponent:
+ {
+ var instance = finishedWork.stateNode;
+ if (finishedWork.effectTag & Update) {
+ if (current$$1 === null) {
+ startPhaseTimer(finishedWork, 'componentDidMount');
+ // We could update instance props and state here,
+ // but instead we rely on them being set during last render.
+ // TODO: revisit this when we implement resuming.
+ instance.componentDidMount();
+ stopPhaseTimer();
+ } else {
+ var prevProps = finishedWork.elementType === finishedWork.type ? current$$1.memoizedProps : resolveDefaultProps(finishedWork.type, current$$1.memoizedProps);
+ var prevState = current$$1.memoizedState;
+ startPhaseTimer(finishedWork, 'componentDidUpdate');
+ // We could update instance props and state here,
+ // but instead we rely on them being set during last render.
+ // TODO: revisit this when we implement resuming.
+ instance.componentDidUpdate(prevProps, prevState, instance.__reactInternalSnapshotBeforeUpdate);
+ stopPhaseTimer();
+ }
+ }
+ var updateQueue = finishedWork.updateQueue;
+ if (updateQueue !== null) {
+ commitUpdateQueue(finishedWork, updateQueue, instance, committedExpirationTime);
+ }
+ return;
+ }
+ case HostRoot:
+ {
+ var _updateQueue = finishedWork.updateQueue;
+ if (_updateQueue !== null) {
+ var _instance = null;
+ if (finishedWork.child !== null) {
+ switch (finishedWork.child.tag) {
+ case HostComponent:
+ _instance = getPublicInstance(finishedWork.child.stateNode);
+ break;
+ case ClassComponent:
+ _instance = finishedWork.child.stateNode;
+ break;
+ }
+ }
+ commitUpdateQueue(finishedWork, _updateQueue, _instance, committedExpirationTime);
+ }
+ return;
+ }
+ case HostComponent:
+ {
+ var _instance2 = finishedWork.stateNode;
+
+ // Renderers may schedule work to be done after host components are mounted
+ // (eg DOM renderer may schedule auto-focus for inputs and form controls).
+ // These effects should only be committed when components are first mounted,
+ // aka when there is no current/alternate.
+ if (current$$1 === null && finishedWork.effectTag & Update) {
+ var type = finishedWork.type;
+ var props = finishedWork.memoizedProps;
+
+ }
+
+ return;
+ }
+ case HostText:
+ {
+ // We have no life-cycles associated with text.
+ return;
+ }
+ case HostPortal:
+ {
+ // We have no life-cycles associated with portals.
+ return;
+ }
+ case Profiler:
+ {
+ if (enableProfilerTimer) {
+ var onRender = finishedWork.memoizedProps.onRender;
+
+ if (enableSchedulerTracing) {
+ onRender(finishedWork.memoizedProps.id, current$$1 === null ? 'mount' : 'update', finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, getCommitTime(), finishedRoot.memoizedInteractions);
+ } else {
+ onRender(finishedWork.memoizedProps.id, current$$1 === null ? 'mount' : 'update', finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, getCommitTime());
+ }
+ }
+ return;
+ }
+ case SuspenseComponent:
+ break;
+ case IncompleteClassComponent:
+ break;
+ default:
+ {
+ reactProdInvariant('163');
+ }
+ }
+}
+
+function hideOrUnhideAllChildren(finishedWork, isHidden) {
+ if (supportsMutation) {
+ // We only have the top Fiber that was inserted but we need to recurse down its
+ var node = finishedWork;
+ while (true) {
+ if (node.tag === HostComponent) {
+ var instance = node.stateNode;
+ if (isHidden) {
+ hideInstance(instance);
+ } else {
+ unhideInstance(node.stateNode, node.memoizedProps);
+ }
+ } else if (node.tag === HostText) {
+ var _instance3 = node.stateNode;
+ if (isHidden) {
+ hideTextInstance(_instance3);
+ } else {
+ unhideTextInstance(_instance3, node.memoizedProps);
+ }
+ } else if (node.tag === SuspenseComponent && node.memoizedState !== null) {
+ // Found a nested Suspense component that timed out. Skip over the
+ var fallbackChildFragment = node.child.sibling;
+ fallbackChildFragment.return = node;
+ node = fallbackChildFragment;
+ continue;
+ } else if (node.child !== null) {
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ if (node === finishedWork) {
+ return;
+ }
+ while (node.sibling === null) {
+ if (node.return === null || node.return === finishedWork) {
+ return;
+ }
+ node = node.return;
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ }
+ }
+}
+
+function commitAttachRef(finishedWork) {
+ var ref = finishedWork.ref;
+ if (ref !== null) {
+ var instance = finishedWork.stateNode;
+ var instanceToUse = void 0;
+ switch (finishedWork.tag) {
+ case HostComponent:
+ instanceToUse = getPublicInstance(instance);
+ break;
+ default:
+ instanceToUse = instance;
+ }
+ if (typeof ref === 'function') {
+ ref(instanceToUse);
+ } else {
+ ref.current = instanceToUse;
+ }
+ }
+}
+
+function commitDetachRef(current$$1) {
+ var currentRef = current$$1.ref;
+ if (currentRef !== null) {
+ if (typeof currentRef === 'function') {
+ currentRef(null);
+ } else {
+ currentRef.current = null;
+ }
+ }
+}
+
+// User-originating errors (lifecycles and refs) should not interrupt
+// deletion, so don't let them throw. Host-originating errors should
+// interrupt deletion, so it's okay
+function commitUnmount(current$$1) {
+ onCommitUnmount(current$$1);
+
+ switch (current$$1.tag) {
+ case FunctionComponent:
+ case ForwardRef:
+ case MemoComponent:
+ case SimpleMemoComponent:
+ {
+ var updateQueue = current$$1.updateQueue;
+ if (updateQueue !== null) {
+ var lastEffect = updateQueue.lastEffect;
+ if (lastEffect !== null) {
+ var firstEffect = lastEffect.next;
+ var effect = firstEffect;
+ do {
+ var destroy = effect.destroy;
+ if (destroy !== undefined) {
+ safelyCallDestroy(current$$1, destroy);
+ }
+ effect = effect.next;
+ } while (effect !== firstEffect);
+ }
+ }
+ break;
+ }
+ case ClassComponent:
+ {
+ safelyDetachRef(current$$1);
+ var instance = current$$1.stateNode;
+ if (typeof instance.componentWillUnmount === 'function') {
+ safelyCallComponentWillUnmount(current$$1, instance);
+ }
+ return;
+ }
+ case HostComponent:
+ {
+ safelyDetachRef(current$$1);
+ return;
+ }
+ case HostPortal:
+ {
+ // TODO: this is recursive.
+ // We are also not using this parent because
+ // the portal will get pushed immediately.
+ if (supportsMutation) {
+ unmountHostComponents(current$$1);
+ } else if (supportsPersistence) {
+ emptyPortalContainer(current$$1);
+ }
+ return;
+ }
+ }
+}
+
+function commitNestedUnmounts(root) {
+ // While we're inside a removed host node we don't want to call
+ // removeChild on the inner nodes because they're removed by the top
+ // call anyway. We also want to call componentWillUnmount on all
+ // composites before this host node is removed from the tree. Therefore
+ var node = root;
+ while (true) {
+ commitUnmount(node);
+ // Visit children because they may contain more composite or host nodes.
+ // Skip portals because commitUnmount() currently visits them recursively.
+ if (node.child !== null && (
+ // If we use mutation we drill down into portals using commitUnmount above.
+ // If we don't use mutation we drill down into portals here instead.
+ !supportsMutation || node.tag !== HostPortal)) {
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ if (node === root) {
+ return;
+ }
+ while (node.sibling === null) {
+ if (node.return === null || node.return === root) {
+ return;
+ }
+ node = node.return;
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ }
+}
+
+function detachFiber(current$$1) {
+ // Cut off the return pointers to disconnect it from the tree. Ideally, we
+ // should clear the child pointer of the parent alternate to let this
+ // get GC:ed but we don't know which for sure which parent is the current
+ // one so we'll settle for GC:ing the subtree of this child. This child
+ // itself will be GC:ed when the parent updates the next time.
+ current$$1.return = null;
+ current$$1.child = null;
+ current$$1.memoizedState = null;
+ current$$1.updateQueue = null;
+ var alternate = current$$1.alternate;
+ if (alternate !== null) {
+ alternate.return = null;
+ alternate.child = null;
+ alternate.memoizedState = null;
+ alternate.updateQueue = null;
+ }
+}
+
+function emptyPortalContainer(current$$1) {
+ if (!supportsPersistence) {
+ return;
+ }
+
+ var portal = current$$1.stateNode;
+ var containerInfo = portal.containerInfo;
+
+ var emptyChildSet = createContainerChildSet(containerInfo);
+ replaceContainerChildren(containerInfo, emptyChildSet);
+}
+
+function commitContainer(finishedWork) {
+ if (!supportsPersistence) {
+ return;
+ }
+
+ switch (finishedWork.tag) {
+ case ClassComponent:
+ {
+ return;
+ }
+ case HostComponent:
+ {
+ return;
+ }
+ case HostText:
+ {
+ return;
+ }
+ case HostRoot:
+ case HostPortal:
+ {
+ var portalOrRoot = finishedWork.stateNode;
+ var containerInfo = portalOrRoot.containerInfo,
+ _pendingChildren = portalOrRoot.pendingChildren;
+
+ replaceContainerChildren(containerInfo, _pendingChildren);
+ return;
+ }
+ default:
+ {
+ reactProdInvariant('163');
+ }
+ }
+}
+
+function getHostParentFiber(fiber) {
+ var parent = fiber.return;
+ while (parent !== null) {
+ if (isHostParent(parent)) {
+ return parent;
+ }
+ parent = parent.return;
+ }
+ reactProdInvariant('160');
+}
+
+function isHostParent(fiber) {
+ return fiber.tag === HostComponent || fiber.tag === HostRoot || fiber.tag === HostPortal;
+}
+
+function getHostSibling(fiber) {
+ // We're going to search forward into the tree until we find a sibling host
+ // node. Unfortunately, if multiple insertions are done in a row we have to
+ // search past them. This leads to exponential search for the next sibling.
+ var node = fiber;
+ siblings: while (true) {
+ // If we didn't find anything, let's try the next sibling.
+ while (node.sibling === null) {
+ if (node.return === null || isHostParent(node.return)) {
+ // If we pop out of the root or hit the parent the fiber we are the
+ // last sibling.
+ return null;
+ }
+ node = node.return;
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ while (node.tag !== HostComponent && node.tag !== HostText && node.tag !== DehydratedSuspenseComponent) {
+ // If it is not host node and, we might have a host node inside it.
+ // Try to search down until we find one.
+ if (node.effectTag & Placement) {
+ // If we don't have a child, try the siblings instead.
+ continue siblings;
+ }
+ // If we don't have a child, try the siblings instead.
+ // We also skip portals because they are not part of this host tree.
+ if (node.child === null || node.tag === HostPortal) {
+ continue siblings;
+ } else {
+ node.child.return = node;
+ node = node.child;
+ }
+ }
+ // Check if this host node is stable or about to be placed.
+ if (!(node.effectTag & Placement)) {
+ // Found it!
+ return node.stateNode;
+ }
+ }
+}
+
+function commitPlacement(finishedWork) {
+ if (!supportsMutation) {
+ return;
+ }
+
+ // Recursively insert all host nodes into the parent.
+ var parentFiber = getHostParentFiber(finishedWork);
+
+ // Note: these two variables *must* always be updated together.
+ var parent = void 0;
+ var isContainer = void 0;
+
+ switch (parentFiber.tag) {
+ case HostComponent:
+ parent = parentFiber.stateNode;
+ isContainer = false;
+ break;
+ case HostRoot:
+ parent = parentFiber.stateNode.containerInfo;
+ isContainer = true;
+ break;
+ case HostPortal:
+ parent = parentFiber.stateNode.containerInfo;
+ isContainer = true;
+ break;
+ default:
+ reactProdInvariant('161');
+ }
+ if (parentFiber.effectTag & ContentReset) {
+ // Reset the text content of the parent before doing any insertions
+ parentFiber.effectTag &= ~ContentReset;
+ }
+
+ var before = getHostSibling(finishedWork);
+ // We only have the top Fiber that was inserted but we need to recurse down its
+ // children to find all the terminal nodes.
+ var node = finishedWork;
+ while (true) {
+ if (node.tag === HostComponent || node.tag === HostText) {
+ if (before) {
+ if (isContainer) {
+ insertInContainerBefore(parent, node.stateNode, before);
+ } else {
+ insertBefore(parent, node.stateNode, before);
+ }
+ } else {
+ if (isContainer) {
+ appendChildToContainer(parent, node.stateNode);
+ } else {
+ appendChild(parent, node.stateNode);
+ }
+ }
+ } else if (node.tag === HostPortal) {
+ // If the insertion itself is a portal, then we don't want to traverse
+ // down its children. Instead, we'll get insertions from each child in
+ // the portal directly.
+ } else if (node.child !== null) {
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ if (node === finishedWork) {
+ return;
+ }
+ while (node.sibling === null) {
+ if (node.return === null || node.return === finishedWork) {
+ return;
+ }
+ node = node.return;
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ }
+}
+
+function unmountHostComponents(current$$1) {
+ // We only have the top Fiber that was deleted but we need to recurse down its
+ var node = current$$1;
+
+ // Each iteration, currentParent is populated with node's host parent if not
+ // currentParentIsValid.
+ var currentParentIsValid = false;
+
+ // Note: these two variables *must* always be updated together.
+ var currentParent = void 0;
+ var currentParentIsContainer = void 0;
+
+ while (true) {
+ if (!currentParentIsValid) {
+ var parent = node.return;
+ findParent: while (true) {
+ !(parent !== null) ? reactProdInvariant('160') : void 0;
+ switch (parent.tag) {
+ case HostComponent:
+ currentParent = parent.stateNode;
+ currentParentIsContainer = false;
+ break findParent;
+ case HostRoot:
+ currentParent = parent.stateNode.containerInfo;
+ currentParentIsContainer = true;
+ break findParent;
+ case HostPortal:
+ currentParent = parent.stateNode.containerInfo;
+ currentParentIsContainer = true;
+ break findParent;
+ }
+ parent = parent.return;
+ }
+ currentParentIsValid = true;
+ }
+
+ if (node.tag === HostComponent || node.tag === HostText) {
+ commitNestedUnmounts(node);
+ // After all the children have unmounted, it is now safe to remove the
+ // node from the tree.
+ if (currentParentIsContainer) {
+ removeChildFromContainer(currentParent, node.stateNode);
+ } else {
+ removeChild(currentParent, node.stateNode);
+ }
+ // Don't visit children because we already visited them.
+ } else if (enableSuspenseServerRenderer && node.tag === DehydratedSuspenseComponent) {
+ // Delete the dehydrated suspense boundary and all of its content.
+ if (currentParentIsContainer) {
+ clearSuspenseBoundaryFromContainer(currentParent, node.stateNode);
+ } else {
+ clearSuspenseBoundary(currentParent, node.stateNode);
+ }
+ } else if (node.tag === HostPortal) {
+ if (node.child !== null) {
+ // When we go into a portal, it becomes the parent to remove from.
+ // We will reassign it back when we pop the portal on the way up.
+ currentParent = node.stateNode.containerInfo;
+ currentParentIsContainer = true;
+ // Visit children because portals might contain host components.
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ } else {
+ commitUnmount(node);
+ // Visit children because we may find more host components below.
+ if (node.child !== null) {
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ }
+ if (node === current$$1) {
+ return;
+ }
+ while (node.sibling === null) {
+ if (node.return === null || node.return === current$$1) {
+ return;
+ }
+ node = node.return;
+ if (node.tag === HostPortal) {
+ // When we go out of the portal, we need to restore the parent.
+ // Since we don't keep a stack of them, we will search for it.
+ currentParentIsValid = false;
+ }
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ }
+}
+
+function commitDeletion(current$$1) {
+ if (supportsMutation) {
+ // Recursively delete all host nodes from the parent.
+ // Detach refs and call componentWillUnmount() on the whole subtree.
+ unmountHostComponents(current$$1);
+ } else {
+ // Detach refs and call componentWillUnmount() on the whole subtree.
+ commitNestedUnmounts(current$$1);
+ }
+ detachFiber(current$$1);
+}
+
+function commitWork(current$$1, finishedWork) {
+ if (!supportsMutation) {
+ switch (finishedWork.tag) {
+ case FunctionComponent:
+ case ForwardRef:
+ case MemoComponent:
+ case SimpleMemoComponent:
+ {
+ // Note: We currently never use MountMutation, but useLayout uses
+ // UnmountMutation.
+ commitHookEffectList(UnmountMutation, MountMutation, finishedWork);
+ return;
+ }
+ }
+
+ commitContainer(finishedWork);
+ return;
+ }
+
+ switch (finishedWork.tag) {
+ case FunctionComponent:
+ case ForwardRef:
+ case MemoComponent:
+ case SimpleMemoComponent:
+ {
+ // Note: We currently never use MountMutation, but useLayout uses
+ // UnmountMutation.
+ commitHookEffectList(UnmountMutation, MountMutation, finishedWork);
+ return;
+ }
+ case ClassComponent:
+ {
+ return;
+ }
+ case HostComponent:
+ {
+ var instance = finishedWork.stateNode;
+ if (instance != null) {
+ // Commit the work prepared earlier.
+ var newProps = finishedWork.memoizedProps;
+ // For hydration we reuse the update path but we treat the oldProps
+ // as the newProps. The updatePayload will contain the real change in
+ // this case.
+ var oldProps = current$$1 !== null ? current$$1.memoizedProps : newProps;
+ var type = finishedWork.type;
+ // TODO: Type the updateQueue to be specific to host components.
+ var updatePayload = finishedWork.updateQueue;
+ finishedWork.updateQueue = null;
+ if (updatePayload !== null) {
+ commitUpdate(instance, updatePayload, type, oldProps, newProps, finishedWork);
+ }
+ }
+ return;
+ }
+ case HostText:
+ {
+ !(finishedWork.stateNode !== null) ? reactProdInvariant('162') : void 0;
+ var textInstance = finishedWork.stateNode;
+ var newText = finishedWork.memoizedProps;
+ // For hydration we reuse the update path but we treat the oldProps
+ // as the newProps. The updatePayload will contain the real change in
+ // this case.
+ var oldText = current$$1 !== null ? current$$1.memoizedProps : newText;
+ commitTextUpdate(textInstance, oldText, newText);
+ return;
+ }
+ case HostRoot:
+ {
+ return;
+ }
+ case Profiler:
+ {
+ return;
+ }
+ case SuspenseComponent:
+ {
+ var newState = finishedWork.memoizedState;
+
+ var newDidTimeout = void 0;
+ var primaryChildParent = finishedWork;
+ if (newState === null) {
+ newDidTimeout = false;
+ } else {
+ newDidTimeout = true;
+ primaryChildParent = finishedWork.child;
+ if (newState.timedOutAt === NoWork) {
+ // If the children had not already timed out, record the time.
+ // This is used to compute the elapsed time during subsequent
+ // attempts to render the children.
+ newState.timedOutAt = requestCurrentTime();
+ }
+ }
+
+ if (primaryChildParent !== null) {
+ hideOrUnhideAllChildren(primaryChildParent, newDidTimeout);
+ }
+
+ // If this boundary just timed out, then it will have a set of thenables.
+ // For each thenable, attach a listener so that when it resolves, React
+ // attempts to re-render the boundary in the primary (pre-timeout) state.
+ var thenables = finishedWork.updateQueue;
+ if (thenables !== null) {
+ finishedWork.updateQueue = null;
+ var retryCache = finishedWork.stateNode;
+ if (retryCache === null) {
+ retryCache = finishedWork.stateNode = new PossiblyWeakSet$1();
+ }
+ thenables.forEach(function (thenable) {
+ // Memoize using the boundary fiber to prevent redundant listeners.
+ var retry = retryTimedOutBoundary.bind(null, finishedWork, thenable);
+ if (enableSchedulerTracing) {
+ retry = unstable_wrap(retry);
+ }
+ if (!retryCache.has(thenable)) {
+ retryCache.add(thenable);
+ thenable.then(retry, retry);
+ }
+ });
+ }
+
+ return;
+ }
+ case IncompleteClassComponent:
+ {
+ return;
+ }
+ default:
+ {
+ reactProdInvariant('163');
+ }
+ }
+}
+
+function commitResetTextContent(current$$1) {
+ if (!supportsMutation) {
+ return;
+ }
+ resetTextContent(current$$1.stateNode);
+}
+
+var PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
+var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
+
+function createRootErrorUpdate(fiber, errorInfo, expirationTime) {
+ var update = createUpdate(expirationTime);
+ // Unmount the root by rendering null.
+ update.tag = CaptureUpdate;
+ // Caution: React DevTools currently depends on this property
+ // being called "element".
+ update.payload = { element: null };
+ var error = errorInfo.value;
+ update.callback = function () {
+ onUncaughtError(error);
+ logError(fiber, errorInfo);
+ };
+ return update;
+}
+
+function createClassErrorUpdate(fiber, errorInfo, expirationTime) {
+ var update = createUpdate(expirationTime);
+ update.tag = CaptureUpdate;
+ var getDerivedStateFromError = fiber.type.getDerivedStateFromError;
+ if (typeof getDerivedStateFromError === 'function') {
+ var error = errorInfo.value;
+ update.payload = function () {
+ return getDerivedStateFromError(error);
+ };
+ }
+
+ var inst = fiber.stateNode;
+ if (inst !== null && typeof inst.componentDidCatch === 'function') {
+ update.callback = function callback() {
+ if (typeof getDerivedStateFromError !== 'function') {
+ // To preserve the preexisting retry behavior of error boundaries,
+ // we keep track of which ones already failed during this batch.
+ // This gets reset before we yield back to the browser.
+ // TODO: Warn in strict mode if getDerivedStateFromError is
+ // not defined.
+ markLegacyErrorBoundaryAsFailed(this);
+ }
+ var error = errorInfo.value;
+ var stack = errorInfo.stack;
+ logError(fiber, errorInfo);
+ this.componentDidCatch(error, {
+ componentStack: stack !== null ? stack : ''
+ });
+
+ };
+ }
+ return update;
+}
+
+function attachPingListener(root, renderExpirationTime, thenable) {
+ // Attach a listener to the promise to "ping" the root and retry. But
+ // only if one does not already exist for the current render expiration
+ // time (which acts like a "thread ID" here).
+ var pingCache = root.pingCache;
+ var threadIDs = void 0;
+ if (pingCache === null) {
+ pingCache = root.pingCache = new PossiblyWeakMap();
+ threadIDs = new Set();
+ pingCache.set(thenable, threadIDs);
+ } else {
+ threadIDs = pingCache.get(thenable);
+ if (threadIDs === undefined) {
+ threadIDs = new Set();
+ pingCache.set(thenable, threadIDs);
+ }
+ }
+ if (!threadIDs.has(renderExpirationTime)) {
+ // Memoize using the thread ID to prevent redundant listeners.
+ threadIDs.add(renderExpirationTime);
+ var ping = pingSuspendedRoot.bind(null, root, thenable, renderExpirationTime);
+ if (enableSchedulerTracing) {
+ ping = unstable_wrap(ping);
+ }
+ thenable.then(ping, ping);
+ }
+}
+
+function throwException(root, returnFiber, sourceFiber, value, renderExpirationTime) {
+ // The source fiber did not complete.
+ sourceFiber.effectTag |= Incomplete;
+ // Its effect list is no longer valid.
+ sourceFiber.firstEffect = sourceFiber.lastEffect = null;
+
+ if (value !== null && typeof value === 'object' && typeof value.then === 'function') {
+ // This is a thenable.
+ var thenable = value;
+
+ // Find the earliest timeout threshold of all the placeholders in the
+ // ancestor path. We could avoid this traversal by storing the thresholds on
+ // the stack, but we choose not to because we only hit this path if we're
+ // IO-bound (i.e. if something suspends). Whereas the stack is used even in
+ // the non-IO- bound case.
+ var _workInProgress = returnFiber;
+ var earliestTimeoutMs = -1;
+ var startTimeMs = -1;
+ do {
+ if (_workInProgress.tag === SuspenseComponent) {
+ var current$$1 = _workInProgress.alternate;
+ if (current$$1 !== null) {
+ var currentState = current$$1.memoizedState;
+ if (currentState !== null) {
+ // Reached a boundary that already timed out. Do not search
+ // any further.
+ var timedOutAt = currentState.timedOutAt;
+ startTimeMs = expirationTimeToMs(timedOutAt);
+ // Do not search any further.
+ break;
+ }
+ }
+ var timeoutPropMs = _workInProgress.pendingProps.maxDuration;
+ if (typeof timeoutPropMs === 'number') {
+ if (timeoutPropMs <= 0) {
+ earliestTimeoutMs = 0;
+ } else if (earliestTimeoutMs === -1 || timeoutPropMs < earliestTimeoutMs) {
+ earliestTimeoutMs = timeoutPropMs;
+ }
+ }
+ }
+ // If there is a DehydratedSuspenseComponent we don't have to do anything because
+ // if something suspends inside it, we will simply leave that as dehydrated. It
+ // will never timeout.
+ _workInProgress = _workInProgress.return;
+ } while (_workInProgress !== null);
+
+ // Schedule the nearest Suspense to re-render the timed out view.
+ _workInProgress = returnFiber;
+ do {
+ if (_workInProgress.tag === SuspenseComponent && shouldCaptureSuspense(_workInProgress)) {
+ // Found the nearest boundary.
+
+ // Stash the promise on the boundary fiber. If the boundary times out, we'll
+ var thenables = _workInProgress.updateQueue;
+ if (thenables === null) {
+ var updateQueue = new Set();
+ updateQueue.add(thenable);
+ _workInProgress.updateQueue = updateQueue;
+ } else {
+ thenables.add(thenable);
+ }
+
+ // If the boundary is outside of concurrent mode, we should *not*
+ // suspend the commit. Pretend as if the suspended component rendered
+ // null and keep rendering. In the commit phase, we'll schedule a
+ // subsequent synchronous update to re-render the Suspense.
+ //
+ // Note: It doesn't matter whether the component that suspended was
+ // inside a concurrent mode tree. If the Suspense is outside of it, we
+ // should *not* suspend the commit.
+ if ((_workInProgress.mode & ConcurrentMode) === NoEffect) {
+ _workInProgress.effectTag |= DidCapture;
+
+ // We're going to commit this fiber even though it didn't complete.
+ // But we shouldn't call any lifecycle methods or callbacks. Remove
+ // all lifecycle effect tags.
+ sourceFiber.effectTag &= ~(LifecycleEffectMask | Incomplete);
+
+ if (sourceFiber.tag === ClassComponent) {
+ var currentSourceFiber = sourceFiber.alternate;
+ if (currentSourceFiber === null) {
+ // This is a new mount. Change the tag so it's not mistaken for a
+ // completed class component. For example, we should not call
+ // componentWillUnmount if it is deleted.
+ sourceFiber.tag = IncompleteClassComponent;
+ } else {
+ // When we try rendering again, we should not reuse the current fiber,
+ // since it's known to be in an inconsistent state. Use a force updte to
+ // prevent a bail out.
+ var update = createUpdate(Sync);
+ update.tag = ForceUpdate;
+ enqueueUpdate(sourceFiber, update);
+ }
+ }
+
+ // The source fiber did not complete. Mark it with Sync priority to
+ // indicate that it still has pending work.
+ sourceFiber.expirationTime = Sync;
+
+ // Exit without suspending.
+ return;
+ }
+
+ // Confirmed that the boundary is in a concurrent mode tree. Continue
+ // with the normal suspend path.
+
+ attachPingListener(root, renderExpirationTime, thenable);
+
+ var absoluteTimeoutMs = void 0;
+ if (earliestTimeoutMs === -1) {
+ // If no explicit threshold is given, default to an arbitrarily large
+ // value. The actual size doesn't matter because the threshold for the
+ // whole tree will be clamped to the expiration time.
+ absoluteTimeoutMs = maxSigned31BitInt;
+ } else {
+ if (startTimeMs === -1) {
+ // This suspend happened outside of any already timed-out
+ // placeholders. We don't know exactly when the update was
+ // scheduled, but we can infer an approximate start time from the
+ // expiration time. First, find the earliest uncommitted expiration
+ // time in the tree, including work that is suspended. Then subtract
+ // the offset used to compute an async update's expiration time.
+ // This will cause high priority (interactive) work to expire
+ // earlier than necessary, but we can account for this by adjusting
+ // for the Just Noticeable Difference.
+ var earliestExpirationTime = findEarliestOutstandingPriorityLevel(root, renderExpirationTime);
+ var earliestExpirationTimeMs = expirationTimeToMs(earliestExpirationTime);
+ startTimeMs = earliestExpirationTimeMs - LOW_PRIORITY_EXPIRATION;
+ }
+ absoluteTimeoutMs = startTimeMs + earliestTimeoutMs;
+ }
+
+ // Mark the earliest timeout in the suspended fiber's ancestor path.
+ // After completing the root, we'll take the largest of all the
+ // suspended fiber's timeouts and use it to compute a timeout for the
+ // whole tree.
+ renderDidSuspend(root, absoluteTimeoutMs, renderExpirationTime);
+
+ _workInProgress.effectTag |= ShouldCapture;
+ _workInProgress.expirationTime = renderExpirationTime;
+ return;
+ } else if (enableSuspenseServerRenderer && _workInProgress.tag === DehydratedSuspenseComponent) {
+ attachPingListener(root, renderExpirationTime, thenable);
+
+ // Since we already have a current fiber, we can eagerly add a retry listener.
+ var retryCache = _workInProgress.memoizedState;
+ if (retryCache === null) {
+ retryCache = _workInProgress.memoizedState = new PossiblyWeakSet();
+ var _current = _workInProgress.alternate;
+ !_current ? reactProdInvariant('319') : void 0;
+ _current.memoizedState = retryCache;
+ }
+ // Memoize using the boundary fiber to prevent redundant listeners.
+ if (!retryCache.has(thenable)) {
+ retryCache.add(thenable);
+ var retry = retryTimedOutBoundary.bind(null, _workInProgress, thenable);
+ if (enableSchedulerTracing) {
+ retry = unstable_wrap(retry);
+ }
+ thenable.then(retry, retry);
+ }
+ _workInProgress.effectTag |= ShouldCapture;
+ _workInProgress.expirationTime = renderExpirationTime;
+ return;
+ }
+ // This boundary already captured during this render. Continue to the next
+ // boundary.
+ _workInProgress = _workInProgress.return;
+ } while (_workInProgress !== null);
+ // No boundary was found. Fallthrough to error mode.
+ // TODO: Use invariant so the message is stripped in prod?
+ value = new Error((getComponentName(sourceFiber.type) || 'A React component') + ' suspended while rendering, but no fallback UI was specified.\n' + '\n' + 'Add a <Suspense fallback=...> component higher in the tree to ' + 'provide a loading indicator or placeholder to display.' + getStackByFiberInDevAndProd(sourceFiber));
+ }
+
+ // We didn't find a boundary that could handle this type of exception. Start
+ // over and traverse parent path again, this time treating the exception
+ // as an error.
+ renderDidError();
+ value = createCapturedValue(value, sourceFiber);
+ var workInProgress = returnFiber;
+ do {
+ switch (workInProgress.tag) {
+ case HostRoot:
+ {
+ var _errorInfo = value;
+ workInProgress.effectTag |= ShouldCapture;
+ workInProgress.expirationTime = renderExpirationTime;
+ var _update = createRootErrorUpdate(workInProgress, _errorInfo, renderExpirationTime);
+ enqueueCapturedUpdate(workInProgress, _update);
+ return;
+ }
+ case ClassComponent:
+ // Capture and retry
+ var errorInfo = value;
+ var ctor = workInProgress.type;
+ var instance = workInProgress.stateNode;
+ if ((workInProgress.effectTag & DidCapture) === NoEffect && (typeof ctor.getDerivedStateFromError === 'function' || instance !== null && typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance))) {
+ workInProgress.effectTag |= ShouldCapture;
+ workInProgress.expirationTime = renderExpirationTime;
+ // Schedule the error boundary to re-render using updated state
+ var _update2 = createClassErrorUpdate(workInProgress, errorInfo, renderExpirationTime);
+ enqueueCapturedUpdate(workInProgress, _update2);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ workInProgress = workInProgress.return;
+ } while (workInProgress !== null);
+}
+
+function unwindWork(workInProgress, renderExpirationTime) {
+ switch (workInProgress.tag) {
+ case ClassComponent:
+ {
+ var Component = workInProgress.type;
+ if (isContextProvider(Component)) {
+ popContext(workInProgress);
+ }
+ var effectTag = workInProgress.effectTag;
+ if (effectTag & ShouldCapture) {
+ workInProgress.effectTag = effectTag & ~ShouldCapture | DidCapture;
+ return workInProgress;
+ }
+ return null;
+ }
+ case HostRoot:
+ {
+ popHostContainer(workInProgress);
+ popTopLevelContextObject(workInProgress);
+ var _effectTag = workInProgress.effectTag;
+ !((_effectTag & DidCapture) === NoEffect) ? reactProdInvariant('285') : void 0;
+ workInProgress.effectTag = _effectTag & ~ShouldCapture | DidCapture;
+ return workInProgress;
+ }
+ case HostComponent:
+ {
+ // TODO: popHydrationState
+ popHostContext(workInProgress);
+ return null;
+ }
+ case SuspenseComponent:
+ {
+ var _effectTag2 = workInProgress.effectTag;
+ if (_effectTag2 & ShouldCapture) {
+ workInProgress.effectTag = _effectTag2 & ~ShouldCapture | DidCapture;
+ // Captured a suspense effect. Re-render the boundary.
+ return workInProgress;
+ }
+ return null;
+ }
+ case DehydratedSuspenseComponent:
+ {
+ if (enableSuspenseServerRenderer) {
+ // TODO: popHydrationState
+ var _effectTag3 = workInProgress.effectTag;
+ if (_effectTag3 & ShouldCapture) {
+ workInProgress.effectTag = _effectTag3 & ~ShouldCapture | DidCapture;
+ // Captured a suspense effect. Re-render the boundary.
+ return workInProgress;
+ }
+ }
+ return null;
+ }
+ case HostPortal:
+ popHostContainer(workInProgress);
+ return null;
+ case ContextProvider:
+ popProvider(workInProgress);
+ return null;
+ default:
+ return null;
+ }
+}
+
+function unwindInterruptedWork(interruptedWork) {
+ switch (interruptedWork.tag) {
+ case ClassComponent:
+ {
+ var childContextTypes = interruptedWork.type.childContextTypes;
+ if (childContextTypes !== null && childContextTypes !== undefined) {
+ popContext(interruptedWork);
+ }
+ break;
+ }
+ case HostRoot:
+ {
+ popHostContainer(interruptedWork);
+ popTopLevelContextObject(interruptedWork);
+ break;
+ }
+ case HostComponent:
+ {
+ popHostContext(interruptedWork);
+ break;
+ }
+ case HostPortal:
+ popHostContainer(interruptedWork);
+ break;
+ case ContextProvider:
+ popProvider(interruptedWork);
+ break;
+ default:
+ break;
+ }
+}
+
+var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
+var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;
+
+
+if (enableSchedulerTracing) {
+ // Provide explicit error message when production+profiling bundle of e.g. react-dom
+ // is used with production (non-profiling) bundle of scheduler/tracing
+ !(__interactionsRef != null && __interactionsRef.current != null) ? reactProdInvariant('302') : void 0;
+}
+
+var isWorking = false;
+
+// The next work in progress fiber that we're currently working on.
+var nextUnitOfWork = null;
+var nextRoot = null;
+// The time at which we're currently rendering work.
+var nextRenderExpirationTime = NoWork;
+var nextLatestAbsoluteTimeoutMs = -1;
+var nextRenderDidError = false;
+
+// The next fiber with an effect that we're currently committing.
+var nextEffect = null;
+
+var isCommitting$1 = false;
+var rootWithPendingPassiveEffects = null;
+var passiveEffectCallbackHandle = null;
+var passiveEffectCallback = null;
+
+var legacyErrorBoundariesThatAlreadyFailed = null;
+
+// Used for performance tracking.
+var interruptedBy = null;
+
+function resetStack() {
+ if (nextUnitOfWork !== null) {
+ var interruptedWork = nextUnitOfWork.return;
+ while (interruptedWork !== null) {
+ unwindInterruptedWork(interruptedWork);
+ interruptedWork = interruptedWork.return;
+ }
+ }
+
+ nextRoot = null;
+ nextRenderExpirationTime = NoWork;
+ nextLatestAbsoluteTimeoutMs = -1;
+ nextRenderDidError = false;
+ nextUnitOfWork = null;
+}
+
+function commitAllHostEffects() {
+ while (nextEffect !== null) {
+ recordEffect();
+
+ var effectTag = nextEffect.effectTag;
+
+ if (effectTag & ContentReset) {
+ commitResetTextContent(nextEffect);
+ }
+
+ if (effectTag & Ref) {
+ var current$$1 = nextEffect.alternate;
+ if (current$$1 !== null) {
+ commitDetachRef(current$$1);
+ }
+ }
+
+ // The following switch statement is only concerned about placement,
+ // updates, and deletions. To avoid needing to add a case for every
+ // possible bitmap value, we remove the secondary effects from the
+ // effect tag and switch on that value.
+ var primaryEffectTag = effectTag & (Placement | Update | Deletion);
+ switch (primaryEffectTag) {
+ case Placement:
+ {
+ commitPlacement(nextEffect);
+ // Clear the "placement" from effect tag so that we know that this is inserted, before
+ // any life-cycles like componentDidMount gets called.
+ // TODO: findDOMNode doesn't rely on this any more but isMounted
+ // does and isMounted is deprecated anyway so we should be able
+ // to kill this.
+ nextEffect.effectTag &= ~Placement;
+ break;
+ }
+ case PlacementAndUpdate:
+ {
+ // Placement
+ commitPlacement(nextEffect);
+ // Clear the "placement" from effect tag so that we know that this is inserted, before
+ // any life-cycles like componentDidMount gets called.
+ nextEffect.effectTag &= ~Placement;
+
+ // Update
+ var _current = nextEffect.alternate;
+ commitWork(_current, nextEffect);
+ break;
+ }
+ case Update:
+ {
+ var _current2 = nextEffect.alternate;
+ commitWork(_current2, nextEffect);
+ break;
+ }
+ case Deletion:
+ {
+ commitDeletion(nextEffect);
+ break;
+ }
+ }
+ nextEffect = nextEffect.nextEffect;
+ }
+
+
+}
+
+function commitBeforeMutationLifecycles() {
+ while (nextEffect !== null) {
+ var effectTag = nextEffect.effectTag;
+ if (effectTag & Snapshot) {
+ recordEffect();
+ var current$$1 = nextEffect.alternate;
+ commitBeforeMutationLifeCycles(current$$1, nextEffect);
+ }
+
+ nextEffect = nextEffect.nextEffect;
+ }
+
+
+}
+
+function commitAllLifeCycles(finishedRoot, committedExpirationTime) {
+ while (nextEffect !== null) {
+ var effectTag = nextEffect.effectTag;
+
+ if (effectTag & (Update | Callback)) {
+ recordEffect();
+ var current$$1 = nextEffect.alternate;
+ commitLifeCycles(finishedRoot, current$$1, nextEffect, committedExpirationTime);
+ }
+
+ if (effectTag & Ref) {
+ recordEffect();
+ commitAttachRef(nextEffect);
+ }
+
+ if (effectTag & Passive) {
+ rootWithPendingPassiveEffects = finishedRoot;
+ }
+
+ nextEffect = nextEffect.nextEffect;
+ }
+
+}
+
+function commitPassiveEffects(root, firstEffect) {
+ rootWithPendingPassiveEffects = null;
+ passiveEffectCallbackHandle = null;
+ passiveEffectCallback = null;
+
+ // Set this to true to prevent re-entrancy
+ var previousIsRendering = isRendering;
+ isRendering = true;
+
+ var effect = firstEffect;
+ do {
+ if (effect.effectTag & Passive) {
+ var didError = false;
+ var error = void 0;
+ {
+ try {
+ commitPassiveHookEffects(effect);
+ } catch (e) {
+ didError = true;
+ error = e;
+ }
+ }
+ if (didError) {
+ captureCommitPhaseError(effect, error);
+ }
+ }
+ effect = effect.nextEffect;
+ } while (effect !== null);
+ isRendering = previousIsRendering;
+
+ // Check if work was scheduled by one of the effects
+ var rootExpirationTime = root.expirationTime;
+ if (rootExpirationTime !== NoWork) {
+ requestWork(root, rootExpirationTime);
+ }
+ // Flush any sync work that was scheduled by effects
+ if (!isBatchingUpdates && !isRendering) {
+ performSyncWork();
+ }
+}
+
+function isAlreadyFailedLegacyErrorBoundary(instance) {
+ return legacyErrorBoundariesThatAlreadyFailed !== null && legacyErrorBoundariesThatAlreadyFailed.has(instance);
+}
+
+function markLegacyErrorBoundaryAsFailed(instance) {
+ if (legacyErrorBoundariesThatAlreadyFailed === null) {
+ legacyErrorBoundariesThatAlreadyFailed = new Set([instance]);
+ } else {
+ legacyErrorBoundariesThatAlreadyFailed.add(instance);
+ }
+}
+
+function flushPassiveEffects$1() {
+ if (passiveEffectCallbackHandle !== null) {
+ cancelPassiveEffects(passiveEffectCallbackHandle);
+ }
+ if (passiveEffectCallback !== null) {
+ // We call the scheduled callback instead of commitPassiveEffects directly
+ // to ensure tracing works correctly.
+ passiveEffectCallback();
+ }
+}
+
+function commitRoot(root, finishedWork) {
+ isWorking = true;
+ isCommitting$1 = true;
+ startCommitTimer();
+
+ !(root.current !== finishedWork) ? reactProdInvariant('177') : void 0;
+ var committedExpirationTime = root.pendingCommitExpirationTime;
+ !(committedExpirationTime !== NoWork) ? reactProdInvariant('261') : void 0;
+ root.pendingCommitExpirationTime = NoWork;
+
+ // Update the pending priority levels to account for the work that we are
+ // about to commit. This needs to happen before calling the lifecycles, since
+ // they may schedule additional updates.
+ var updateExpirationTimeBeforeCommit = finishedWork.expirationTime;
+ var childExpirationTimeBeforeCommit = finishedWork.childExpirationTime;
+ var earliestRemainingTimeBeforeCommit = childExpirationTimeBeforeCommit > updateExpirationTimeBeforeCommit ? childExpirationTimeBeforeCommit : updateExpirationTimeBeforeCommit;
+ markCommittedPriorityLevels(root, earliestRemainingTimeBeforeCommit);
+
+ var prevInteractions = null;
+ if (enableSchedulerTracing) {
+ // Restore any pending interactions at this point,
+ // So that cascading work triggered during the render phase will be accounted for.
+ prevInteractions = __interactionsRef.current;
+ __interactionsRef.current = root.memoizedInteractions;
+ }
+
+ // Reset this to null before calling lifecycles
+ ReactCurrentOwner$1.current = null;
+
+ var firstEffect = void 0;
+ if (finishedWork.effectTag > PerformedWork) {
+ // A fiber's effect list consists only of its children, not itself. So if
+ // the root has an effect, we need to add it to the end of the list. The
+ // resulting list is the set that would belong to the root's parent, if
+ // it had one; that is, all the effects in the tree including the root.
+ if (finishedWork.lastEffect !== null) {
+ finishedWork.lastEffect.nextEffect = finishedWork;
+ firstEffect = finishedWork.firstEffect;
+ } else {
+ firstEffect = finishedWork;
+ }
+ } else {
+ // There is no effect on the root.
+ firstEffect = finishedWork.firstEffect;
+ }
+
+ prepareForCommit(root.containerInfo);
+
+ // Invoke instances of getSnapshotBeforeUpdate before mutation.
+ nextEffect = firstEffect;
+ startCommitSnapshotEffectsTimer();
+ while (nextEffect !== null) {
+ var didError = false;
+ var error = void 0;
+ {
+ try {
+ commitBeforeMutationLifecycles();
+ } catch (e) {
+ didError = true;
+ error = e;
+ }
+ }
+ if (didError) {
+ !(nextEffect !== null) ? reactProdInvariant('178') : void 0;
+ captureCommitPhaseError(nextEffect, error);
+ // Clean-up
+ if (nextEffect !== null) {
+ nextEffect = nextEffect.nextEffect;
+ }
+ }
+ }
+ stopCommitSnapshotEffectsTimer();
+
+ if (enableProfilerTimer) {
+ // Mark the current commit time to be shared by all Profilers in this batch.
+ // This enables them to be grouped later.
+ recordCommitTime();
+ }
+
+ // Commit all the side-effects within a tree. We'll do this in two passes.
+ // The first pass performs all the host insertions, updates, deletions and
+ // ref unmounts.
+ nextEffect = firstEffect;
+ startCommitHostEffectsTimer();
+ while (nextEffect !== null) {
+ var _didError = false;
+ var _error = void 0;
+ {
+ try {
+ commitAllHostEffects();
+ } catch (e) {
+ _didError = true;
+ _error = e;
+ }
+ }
+ if (_didError) {
+ !(nextEffect !== null) ? reactProdInvariant('178') : void 0;
+ captureCommitPhaseError(nextEffect, _error);
+ // Clean-up
+ if (nextEffect !== null) {
+ nextEffect = nextEffect.nextEffect;
+ }
+ }
+ }
+ stopCommitHostEffectsTimer();
+
+ resetAfterCommit(root.containerInfo);
+
+ // The work-in-progress tree is now the current tree. This must come after
+ // the first pass of the commit phase, so that the previous tree is still
+ // current during componentWillUnmount, but before the second pass, so that
+ // the finished work is current during componentDidMount/Update.
+ root.current = finishedWork;
+
+ // In the second pass we'll perform all life-cycles and ref callbacks.
+ // Life-cycles happen as a separate pass so that all placements, updates,
+ // and deletions in the entire tree have already been invoked.
+ // This pass also triggers any renderer-specific initial effects.
+ nextEffect = firstEffect;
+ startCommitLifeCyclesTimer();
+ while (nextEffect !== null) {
+ var _didError2 = false;
+ var _error2 = void 0;
+ {
+ try {
+ commitAllLifeCycles(root, committedExpirationTime);
+ } catch (e) {
+ _didError2 = true;
+ _error2 = e;
+ }
+ }
+ if (_didError2) {
+ !(nextEffect !== null) ? reactProdInvariant('178') : void 0;
+ captureCommitPhaseError(nextEffect, _error2);
+ if (nextEffect !== null) {
+ nextEffect = nextEffect.nextEffect;
+ }
+ }
+ }
+
+ if (firstEffect !== null && rootWithPendingPassiveEffects !== null) {
+ // This commit included a passive effect. These do not need to fire until
+ // after the next paint. Schedule an callback to fire them in an async
+ // event. To ensure serial execution, the callback will be flushed early if
+ // we enter rootWithPendingPassiveEffects commit phase before then.
+ var callback = commitPassiveEffects.bind(null, root, firstEffect);
+ if (enableSchedulerTracing) {
+ // TODO: Avoid this extra callback by mutating the tracing ref directly,
+ // like we do at the beginning of commitRoot. I've opted not to do that
+ // here because that code is still in flux.
+ callback = unstable_wrap(callback);
+ }
+ passiveEffectCallbackHandle = unstable_runWithPriority(unstable_NormalPriority, function () {
+ return schedulePassiveEffects(callback);
+ });
+ passiveEffectCallback = callback;
+ }
+
+ isCommitting$1 = false;
+ isWorking = false;
+ stopCommitLifeCyclesTimer();
+ stopCommitTimer();
+ onCommitRoot(finishedWork.stateNode);
+ var updateExpirationTimeAfterCommit = finishedWork.expirationTime;
+ var childExpirationTimeAfterCommit = finishedWork.childExpirationTime;
+ var earliestRemainingTimeAfterCommit = childExpirationTimeAfterCommit > updateExpirationTimeAfterCommit ? childExpirationTimeAfterCommit : updateExpirationTimeAfterCommit;
+ if (earliestRemainingTimeAfterCommit === NoWork) {
+ // If there's no remaining work, we can clear the set of already failed
+ // error boundaries.
+ legacyErrorBoundariesThatAlreadyFailed = null;
+ }
+ onCommit(root, earliestRemainingTimeAfterCommit);
+
+ if (enableSchedulerTracing) {
+ __interactionsRef.current = prevInteractions;
+
+ var subscriber = void 0;
+
+ try {
+ subscriber = __subscriberRef.current;
+ if (subscriber !== null && root.memoizedInteractions.size > 0) {
+ var threadID = computeThreadID(committedExpirationTime, root.interactionThreadID);
+ subscriber.onWorkStopped(root.memoizedInteractions, threadID);
+ }
+ } catch (error) {
+ // It's not safe for commitRoot() to throw.
+ // Store the error for now and we'll re-throw in finishRendering().
+ if (!hasUnhandledError) {
+ hasUnhandledError = true;
+ unhandledError = error;
+ }
+ } finally {
+ // Clear completed interactions from the pending Map.
+ // Unless the render was suspended or cascading work was scheduled,
+ // In which case– leave pending interactions until the subsequent render.
+ var pendingInteractionMap = root.pendingInteractionMap;
+ pendingInteractionMap.forEach(function (scheduledInteractions, scheduledExpirationTime) {
+ // Only decrement the pending interaction count if we're done.
+ // If there's still work at the current priority,
+ // That indicates that we are waiting for suspense data.
+ if (scheduledExpirationTime > earliestRemainingTimeAfterCommit) {
+ pendingInteractionMap.delete(scheduledExpirationTime);
+
+ scheduledInteractions.forEach(function (interaction) {
+ interaction.__count--;
+
+ if (subscriber !== null && interaction.__count === 0) {
+ try {
+ subscriber.onInteractionScheduledWorkCompleted(interaction);
+ } catch (error) {
+ // It's not safe for commitRoot() to throw.
+ // Store the error for now and we'll re-throw in finishRendering().
+ if (!hasUnhandledError) {
+ hasUnhandledError = true;
+ unhandledError = error;
+ }
+ }
+ }
+ });
+ }
+ });
+ }
+ }
+}
+
+function resetChildExpirationTime(workInProgress, renderTime) {
+ if (renderTime !== Never && workInProgress.childExpirationTime === Never) {
+ // The children of this component are hidden. Don't bubble their
+ // expiration times.
+ return;
+ }
+
+ var newChildExpirationTime = NoWork;
+
+ // Bubble up the earliest expiration time.
+ if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
+ // We're in profiling mode.
+ // Let's use this same traversal to update the render durations.
+ var actualDuration = workInProgress.actualDuration;
+ var treeBaseDuration = workInProgress.selfBaseDuration;
+
+ // When a fiber is cloned, its actualDuration is reset to 0.
+ // This value will only be updated if work is done on the fiber (i.e. it doesn't bailout).
+ // When work is done, it should bubble to the parent's actualDuration.
+ // If the fiber has not been cloned though, (meaning no work was done),
+ // Then this value will reflect the amount of time spent working on a previous render.
+ // In that case it should not bubble.
+ // We determine whether it was cloned by comparing the child pointer.
+ var shouldBubbleActualDurations = workInProgress.alternate === null || workInProgress.child !== workInProgress.alternate.child;
+
+ var child = workInProgress.child;
+ while (child !== null) {
+ var childUpdateExpirationTime = child.expirationTime;
+ var childChildExpirationTime = child.childExpirationTime;
+ if (childUpdateExpirationTime > newChildExpirationTime) {
+ newChildExpirationTime = childUpdateExpirationTime;
+ }
+ if (childChildExpirationTime > newChildExpirationTime) {
+ newChildExpirationTime = childChildExpirationTime;
+ }
+ if (shouldBubbleActualDurations) {
+ actualDuration += child.actualDuration;
+ }
+ treeBaseDuration += child.treeBaseDuration;
+ child = child.sibling;
+ }
+ workInProgress.actualDuration = actualDuration;
+ workInProgress.treeBaseDuration = treeBaseDuration;
+ } else {
+ var _child = workInProgress.child;
+ while (_child !== null) {
+ var _childUpdateExpirationTime = _child.expirationTime;
+ var _childChildExpirationTime = _child.childExpirationTime;
+ if (_childUpdateExpirationTime > newChildExpirationTime) {
+ newChildExpirationTime = _childUpdateExpirationTime;
+ }
+ if (_childChildExpirationTime > newChildExpirationTime) {
+ newChildExpirationTime = _childChildExpirationTime;
+ }
+ _child = _child.sibling;
+ }
+ }
+
+ workInProgress.childExpirationTime = newChildExpirationTime;
+}
+
+function completeUnitOfWork(workInProgress) {
+ // Attempt to complete the current unit of work, then move to the
+ // next sibling. If there are no more siblings, return to the
+ // parent fiber.
+ while (true) {
+ // The current, flushed, state of this fiber is the alternate.
+ // Ideally nothing should rely on this, but relying on it here
+ // means that we don't need an additional field on the work in
+ // progress.
+ var current$$1 = workInProgress.alternate;
+ var returnFiber = workInProgress.return;
+ var siblingFiber = workInProgress.sibling;
+
+ if ((workInProgress.effectTag & Incomplete) === NoEffect) {
+ nextUnitOfWork = workInProgress;
+ if (enableProfilerTimer) {
+ if (workInProgress.mode & ProfileMode) {
+ startProfilerTimer(workInProgress);
+ }
+ nextUnitOfWork = completeWork(current$$1, workInProgress, nextRenderExpirationTime);
+ if (workInProgress.mode & ProfileMode) {
+ // Update render duration assuming we didn't error.
+ stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);
+ }
+ } else {
+ nextUnitOfWork = completeWork(current$$1, workInProgress, nextRenderExpirationTime);
+ }
+ stopWorkTimer(workInProgress);
+ resetChildExpirationTime(workInProgress, nextRenderExpirationTime);
+ if (nextUnitOfWork !== null) {
+ // Completing this fiber spawned new work. Work on that next.
+ return nextUnitOfWork;
+ }
+
+ if (returnFiber !== null &&
+ // Do not append effects to parents if a sibling failed to complete
+ (returnFiber.effectTag & Incomplete) === NoEffect) {
+ // Append all the effects of the subtree and this fiber onto the effect
+ // list of the parent. The completion order of the children affects the
+ // side-effect order.
+ if (returnFiber.firstEffect === null) {
+ returnFiber.firstEffect = workInProgress.firstEffect;
+ }
+ if (workInProgress.lastEffect !== null) {
+ if (returnFiber.lastEffect !== null) {
+ returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;
+ }
+ returnFiber.lastEffect = workInProgress.lastEffect;
+ }
+
+ // If this fiber had side-effects, we append it AFTER the children's
+ // side-effects. We can perform certain side-effects earlier if
+ // needed, by doing multiple passes over the effect list. We don't want
+ // to schedule our own side-effect on our own list because if end up
+ // reusing children we'll schedule this effect onto itself since we're
+ // at the end.
+ var effectTag = workInProgress.effectTag;
+ // Skip both NoWork and PerformedWork tags when creating the effect list.
+ // PerformedWork effect is read by React DevTools but shouldn't be committed.
+ if (effectTag > PerformedWork) {
+ if (returnFiber.lastEffect !== null) {
+ returnFiber.lastEffect.nextEffect = workInProgress;
+ } else {
+ returnFiber.firstEffect = workInProgress;
+ }
+ returnFiber.lastEffect = workInProgress;
+ }
+ }
+
+ if (siblingFiber !== null) {
+ // If there is more work to do in this returnFiber, do that next.
+ return siblingFiber;
+ } else if (returnFiber !== null) {
+ // If there's no more work in this returnFiber. Complete the returnFiber.
+ workInProgress = returnFiber;
+ continue;
+ } else {
+ // We've reached the root.
+ return null;
+ }
+ } else {
+ if (enableProfilerTimer && workInProgress.mode & ProfileMode) {
+ // Record the render duration for the fiber that errored.
+ stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);
+
+ // Include the time spent working on failed children before continuing.
+ var actualDuration = workInProgress.actualDuration;
+ var child = workInProgress.child;
+ while (child !== null) {
+ actualDuration += child.actualDuration;
+ child = child.sibling;
+ }
+ workInProgress.actualDuration = actualDuration;
+ }
+
+ // This fiber did not complete because something threw. Pop values off
+ // the stack without entering the complete phase. If this is a boundary,
+ // capture values if possible.
+ var next = unwindWork(workInProgress, nextRenderExpirationTime);
+ // Because this fiber did not complete, don't reset its expiration time.
+ if (workInProgress.effectTag & DidCapture) {
+ // Restarting an error boundary
+ stopFailedWorkTimer(workInProgress);
+ } else {
+ stopWorkTimer(workInProgress);
+ }
+
+ if (next !== null) {
+ stopWorkTimer(workInProgress);
+ next.effectTag &= HostEffectMask;
+ return next;
+ }
+
+ if (returnFiber !== null) {
+ // Mark the parent fiber as incomplete and clear its effect list.
+ returnFiber.firstEffect = returnFiber.lastEffect = null;
+ returnFiber.effectTag |= Incomplete;
+ }
+
+ if (siblingFiber !== null) {
+ // If there is more work to do in this returnFiber, do that next.
+ return siblingFiber;
+ } else if (returnFiber !== null) {
+ // If there's no more work in this returnFiber. Complete the returnFiber.
+ workInProgress = returnFiber;
+ continue;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ // Without this explicit null return Flow complains of invalid return type
+ // TODO Remove the above while(true) loop
+ // eslint-disable-next-line no-unreachable
+ return null;
+}
+
+function performUnitOfWork(workInProgress) {
+ // The current, flushed, state of this fiber is the alternate.
+ // Ideally nothing should rely on this, but relying on it here
+ // means that we don't need an additional field on the work in
+ // progress.
+ var current$$1 = workInProgress.alternate;
+
+ // See if beginning this work spawns more work.
+ startWorkTimer(workInProgress);
+ var next = void 0;
+ if (enableProfilerTimer) {
+ if (workInProgress.mode & ProfileMode) {
+ startProfilerTimer(workInProgress);
+ }
+
+ next = beginWork(current$$1, workInProgress, nextRenderExpirationTime);
+ workInProgress.memoizedProps = workInProgress.pendingProps;
+
+ if (workInProgress.mode & ProfileMode) {
+ // Record the render duration assuming we didn't bailout (or error).
+ stopProfilerTimerIfRunningAndRecordDelta(workInProgress, true);
+ }
+ } else {
+ next = beginWork(current$$1, workInProgress, nextRenderExpirationTime);
+ workInProgress.memoizedProps = workInProgress.pendingProps;
+ }
+
+ if (next === null) {
+ // If this doesn't spawn new work, complete the current work.
+ next = completeUnitOfWork(workInProgress);
+ }
+
+ ReactCurrentOwner$1.current = null;
+
+ return next;
+}
+
+function workLoop(isYieldy) {
+ if (!isYieldy) {
+ // Flush work without yielding
+ while (nextUnitOfWork !== null) {
+ nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
+ }
+ } else {
+ // Flush asynchronous work until there's a higher priority event
+ while (nextUnitOfWork !== null && !shouldYieldToRenderer()) {
+ nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
+ }
+ }
+}
+
+function renderRoot(root, isYieldy) {
+ !!isWorking ? reactProdInvariant('243') : void 0;
+
+ flushPassiveEffects$1();
+
+ isWorking = true;
+ var previousDispatcher = ReactCurrentDispatcher.current;
+ ReactCurrentDispatcher.current = ContextOnlyDispatcher;
+
+ var expirationTime = root.nextExpirationTimeToWorkOn;
+
+ // Check if we're starting from a fresh stack, or if we're resuming from
+ // previously yielded work.
+ if (expirationTime !== nextRenderExpirationTime || root !== nextRoot || nextUnitOfWork === null) {
+ // Reset the stack and start working from the root.
+ resetStack();
+ nextRoot = root;
+ nextRenderExpirationTime = expirationTime;
+ nextUnitOfWork = createWorkInProgress(nextRoot.current, null, nextRenderExpirationTime);
+ root.pendingCommitExpirationTime = NoWork;
+
+ if (enableSchedulerTracing) {
+ // Determine which interactions this batch of work currently includes,
+ // So that we can accurately attribute time spent working on it,
+ var interactions = new Set();
+ root.pendingInteractionMap.forEach(function (scheduledInteractions, scheduledExpirationTime) {
+ if (scheduledExpirationTime >= expirationTime) {
+ scheduledInteractions.forEach(function (interaction) {
+ return interactions.add(interaction);
+ });
+ }
+ });
+
+ // Store the current set of interactions on the FiberRoot for a few reasons:
+ // We can re-use it in hot functions like renderRoot() without having to recalculate it.
+ // We will also use it in commitWork() to pass to any Profiler onRender() hooks.
+ // This also provides DevTools with a way to access it when the onCommitRoot() hook is called.
+ root.memoizedInteractions = interactions;
+
+ if (interactions.size > 0) {
+ var subscriber = __subscriberRef.current;
+ if (subscriber !== null) {
+ var threadID = computeThreadID(expirationTime, root.interactionThreadID);
+ try {
+ subscriber.onWorkStarted(interactions, threadID);
+ } catch (error) {
+ // Work thrown by an interaction tracing subscriber should be rethrown,
+ // But only once it's safe (to avoid leaving the scheduler in an invalid state).
+ // Store the error for now and we'll re-throw in finishRendering().
+ if (!hasUnhandledError) {
+ hasUnhandledError = true;
+ unhandledError = error;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ var prevInteractions = null;
+ if (enableSchedulerTracing) {
+ // We're about to start new traced work.
+ // Restore pending interactions so cascading work triggered during the render phase will be accounted for.
+ prevInteractions = __interactionsRef.current;
+ __interactionsRef.current = root.memoizedInteractions;
+ }
+
+ var didFatal = false;
+
+ startWorkLoopTimer(nextUnitOfWork);
+
+ do {
+ try {
+ workLoop(isYieldy);
+ } catch (thrownValue) {
+ resetContextDependences();
+ resetHooks();
+
+ // Reset in case completion throws.
+ // This is only used in DEV and when replaying is on.
+ if (nextUnitOfWork === null) {
+ // This is a fatal error.
+ didFatal = true;
+ onUncaughtError(thrownValue);
+ } else {
+ if (enableProfilerTimer && nextUnitOfWork.mode & ProfileMode) {
+ // Record the time spent rendering before an error was thrown.
+ // This avoids inaccurate Profiler durations in the case of a suspended render.
+ stopProfilerTimerIfRunningAndRecordDelta(nextUnitOfWork, true);
+ }
+
+ !(nextUnitOfWork !== null) ? reactProdInvariant('271') : void 0;
+
+ var sourceFiber = nextUnitOfWork;
+ var returnFiber = sourceFiber.return;
+ if (returnFiber === null) {
+ // This is the root. The root could capture its own errors. However,
+ // we don't know if it errors before or after we pushed the host
+ // context. This information is needed to avoid a stack mismatch.
+ // Because we're not sure, treat this as a fatal error. We could track
+ // which phase it fails in, but doesn't seem worth it. At least
+ // for now.
+ didFatal = true;
+ onUncaughtError(thrownValue);
+ } else {
+ throwException(root, returnFiber, sourceFiber, thrownValue, nextRenderExpirationTime);
+ nextUnitOfWork = completeUnitOfWork(sourceFiber);
+ continue;
+ }
+ }
+ }
+ break;
+ } while (true);
+
+ if (enableSchedulerTracing) {
+ // Traced work is done for now; restore the previous interactions.
+ __interactionsRef.current = prevInteractions;
+ }
+
+ // We're done performing work. Time to clean up.
+ isWorking = false;
+ ReactCurrentDispatcher.current = previousDispatcher;
+ resetContextDependences();
+ resetHooks();
+
+ // Yield back to main thread.
+ if (didFatal) {
+ var _didCompleteRoot = false;
+ stopWorkLoopTimer(interruptedBy, _didCompleteRoot);
+ interruptedBy = null;
+ // There was a fatal error.
+ nextRoot = null;
+ onFatal(root);
+ return;
+ }
+
+ if (nextUnitOfWork !== null) {
+ // There's still remaining async work in this tree, but we ran out of time
+ // in the current frame. Yield back to the renderer. Unless we're
+ // interrupted by a higher priority update, we'll continue later from where
+ // we left off.
+ var _didCompleteRoot2 = false;
+ stopWorkLoopTimer(interruptedBy, _didCompleteRoot2);
+ interruptedBy = null;
+ onYield(root);
+ return;
+ }
+
+ // We completed the whole tree.
+ var didCompleteRoot = true;
+ stopWorkLoopTimer(interruptedBy, didCompleteRoot);
+ var rootWorkInProgress = root.current.alternate;
+ !(rootWorkInProgress !== null) ? reactProdInvariant('281') : void 0;
+
+ // `nextRoot` points to the in-progress root. A non-null value indicates
+ // that we're in the middle of an async render. Set it to null to indicate
+ // there's no more work to be done in the current batch.
+ nextRoot = null;
+ interruptedBy = null;
+
+ if (nextRenderDidError) {
+ // There was an error
+ if (hasLowerPriorityWork(root, expirationTime)) {
+ // There's lower priority work. If so, it may have the effect of fixing
+ // the exception that was just thrown. Exit without committing. This is
+ // similar to a suspend, but without a timeout because we're not waiting
+ // for a promise to resolve. React will restart at the lower
+ // priority level.
+ markSuspendedPriorityLevel(root, expirationTime);
+ var suspendedExpirationTime = expirationTime;
+ var rootExpirationTime = root.expirationTime;
+ onSuspend(root, rootWorkInProgress, suspendedExpirationTime, rootExpirationTime, -1 // Indicates no timeout
+ );
+ return;
+ } else if (
+ // There's no lower priority work, but we're rendering asynchronously.
+ // Synchronously attempt to render the same level one more time. This is
+ // similar to a suspend, but without a timeout because we're not waiting
+ // for a promise to resolve.
+ !root.didError && isYieldy) {
+ root.didError = true;
+ var _suspendedExpirationTime = root.nextExpirationTimeToWorkOn = expirationTime;
+ var _rootExpirationTime = root.expirationTime = Sync;
+ onSuspend(root, rootWorkInProgress, _suspendedExpirationTime, _rootExpirationTime, -1 // Indicates no timeout
+ );
+ return;
+ }
+ }
+
+ if (isYieldy && nextLatestAbsoluteTimeoutMs !== -1) {
+ // The tree was suspended.
+ var _suspendedExpirationTime2 = expirationTime;
+ markSuspendedPriorityLevel(root, _suspendedExpirationTime2);
+
+ // Find the earliest uncommitted expiration time in the tree, including
+ // work that is suspended. The timeout threshold cannot be longer than
+ // the overall expiration.
+ var earliestExpirationTime = findEarliestOutstandingPriorityLevel(root, expirationTime);
+ var earliestExpirationTimeMs = expirationTimeToMs(earliestExpirationTime);
+ if (earliestExpirationTimeMs < nextLatestAbsoluteTimeoutMs) {
+ nextLatestAbsoluteTimeoutMs = earliestExpirationTimeMs;
+ }
+
+ // Subtract the current time from the absolute timeout to get the number
+ // of milliseconds until the timeout. In other words, convert an absolute
+ // timestamp to a relative time. This is the value that is passed
+ // to `setTimeout`.
+ var currentTimeMs = expirationTimeToMs(requestCurrentTime());
+ var msUntilTimeout = nextLatestAbsoluteTimeoutMs - currentTimeMs;
+ msUntilTimeout = msUntilTimeout < 0 ? 0 : msUntilTimeout;
+
+ // TODO: Account for the Just Noticeable Difference
+
+ var _rootExpirationTime2 = root.expirationTime;
+ onSuspend(root, rootWorkInProgress, _suspendedExpirationTime2, _rootExpirationTime2, msUntilTimeout);
+ return;
+ }
+
+ // Ready to commit.
+ onComplete(root, rootWorkInProgress, expirationTime);
+}
+
+function captureCommitPhaseError(sourceFiber, value) {
+ var expirationTime = Sync;
+ var fiber = sourceFiber.return;
+ while (fiber !== null) {
+ switch (fiber.tag) {
+ case ClassComponent:
+ var ctor = fiber.type;
+ var instance = fiber.stateNode;
+ if (typeof ctor.getDerivedStateFromError === 'function' || typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) {
+ var errorInfo = createCapturedValue(value, sourceFiber);
+ var update = createClassErrorUpdate(fiber, errorInfo, expirationTime);
+ enqueueUpdate(fiber, update);
+ scheduleWork(fiber, expirationTime);
+ return;
+ }
+ break;
+ case HostRoot:
+ {
+ var _errorInfo = createCapturedValue(value, sourceFiber);
+ var _update = createRootErrorUpdate(fiber, _errorInfo, expirationTime);
+ enqueueUpdate(fiber, _update);
+ scheduleWork(fiber, expirationTime);
+ return;
+ }
+ }
+ fiber = fiber.return;
+ }
+
+ if (sourceFiber.tag === HostRoot) {
+ // Error was thrown at the root. There is no parent, so the root
+ // itself should capture it.
+ var rootFiber = sourceFiber;
+ var _errorInfo2 = createCapturedValue(value, rootFiber);
+ var _update2 = createRootErrorUpdate(rootFiber, _errorInfo2, expirationTime);
+ enqueueUpdate(rootFiber, _update2);
+ scheduleWork(rootFiber, expirationTime);
+ }
+}
+
+function computeThreadID(expirationTime, interactionThreadID) {
+ // Interaction threads are unique per root and expiration time.
+ return expirationTime * 1000 + interactionThreadID;
+}
+
+function computeExpirationForFiber(currentTime, fiber) {
+ var priorityLevel = unstable_getCurrentPriorityLevel();
+
+ var expirationTime = void 0;
+ if ((fiber.mode & ConcurrentMode) === NoContext) {
+ // Outside of concurrent mode, updates are always synchronous.
+ expirationTime = Sync;
+ } else if (isWorking && !isCommitting$1) {
+ // During render phase, updates expire during as the current render.
+ expirationTime = nextRenderExpirationTime;
+ } else {
+ switch (priorityLevel) {
+ case unstable_ImmediatePriority:
+ expirationTime = Sync;
+ break;
+ case unstable_UserBlockingPriority:
+ expirationTime = computeInteractiveExpiration(currentTime);
+ break;
+ case unstable_NormalPriority:
+ // This is a normal, concurrent update
+ expirationTime = computeAsyncExpiration(currentTime);
+ break;
+ case unstable_LowPriority:
+ case unstable_IdlePriority:
+ expirationTime = Never;
+ break;
+ default:
+ reactProdInvariant('313');
+ }
+
+ // If we're in the middle of rendering a tree, do not update at the same
+ // expiration time that is already rendering.
+ if (nextRoot !== null && expirationTime === nextRenderExpirationTime) {
+ expirationTime -= 1;
+ }
+ }
+
+ // Keep track of the lowest pending interactive expiration time. This
+ // allows us to synchronously flush all interactive updates
+ // when needed.
+ // TODO: Move this to renderer?
+ return expirationTime;
+}
+
+function renderDidSuspend(root, absoluteTimeoutMs, suspendedTime) {
+ // Schedule the timeout.
+ if (absoluteTimeoutMs >= 0 && nextLatestAbsoluteTimeoutMs < absoluteTimeoutMs) {
+ nextLatestAbsoluteTimeoutMs = absoluteTimeoutMs;
+ }
+}
+
+function renderDidError() {
+ nextRenderDidError = true;
+}
+
+function pingSuspendedRoot(root, thenable, pingTime) {
+ // A promise that previously suspended React from committing has resolved.
+ // If React is still suspended, try again at the previous level (pingTime).
+
+ var pingCache = root.pingCache;
+ if (pingCache !== null) {
+ // The thenable resolved, so we no longer need to memoize, because it will
+ // never be thrown again.
+ pingCache.delete(thenable);
+ }
+
+ if (nextRoot !== null && nextRenderExpirationTime === pingTime) {
+ // Received a ping at the same priority level at which we're currently
+ // rendering. Restart from the root.
+ nextRoot = null;
+ } else {
+ // Confirm that the root is still suspended at this level. Otherwise exit.
+ if (isPriorityLevelSuspended(root, pingTime)) {
+ // Ping at the original level
+ markPingedPriorityLevel(root, pingTime);
+ var rootExpirationTime = root.expirationTime;
+ if (rootExpirationTime !== NoWork) {
+ requestWork(root, rootExpirationTime);
+ }
+ }
+ }
+}
+
+function retryTimedOutBoundary(boundaryFiber, thenable) {
+ // The boundary fiber (a Suspense component) previously timed out and was
+ // rendered in its fallback state. One of the promises that suspended it has
+ // resolved, which means at least part of the tree was likely unblocked. Try
+ var retryCache = void 0;
+ if (enableSuspenseServerRenderer) {
+ switch (boundaryFiber.tag) {
+ case SuspenseComponent:
+ retryCache = boundaryFiber.stateNode;
+ break;
+ case DehydratedSuspenseComponent:
+ retryCache = boundaryFiber.memoizedState;
+ break;
+ default:
+ reactProdInvariant('314');
+ }
+ } else {
+ retryCache = boundaryFiber.stateNode;
+ }
+ if (retryCache !== null) {
+ // The thenable resolved, so we no longer need to memoize, because it will
+ // never be thrown again.
+ retryCache.delete(thenable);
+ }
+
+ var currentTime = requestCurrentTime();
+ var retryTime = computeExpirationForFiber(currentTime, boundaryFiber);
+ var root = scheduleWorkToRoot(boundaryFiber, retryTime);
+ if (root !== null) {
+ markPendingPriorityLevel(root, retryTime);
+ var rootExpirationTime = root.expirationTime;
+ if (rootExpirationTime !== NoWork) {
+ requestWork(root, rootExpirationTime);
+ }
+ }
+}
+
+function scheduleWorkToRoot(fiber, expirationTime) {
+ recordScheduleUpdate();
+
+ if (fiber.expirationTime < expirationTime) {
+ fiber.expirationTime = expirationTime;
+ }
+ var alternate = fiber.alternate;
+ if (alternate !== null && alternate.expirationTime < expirationTime) {
+ alternate.expirationTime = expirationTime;
+ }
+ // Walk the parent path to the root and update the child expiration time.
+ var node = fiber.return;
+ var root = null;
+ if (node === null && fiber.tag === HostRoot) {
+ root = fiber.stateNode;
+ } else {
+ while (node !== null) {
+ alternate = node.alternate;
+ if (node.childExpirationTime < expirationTime) {
+ node.childExpirationTime = expirationTime;
+ if (alternate !== null && alternate.childExpirationTime < expirationTime) {
+ alternate.childExpirationTime = expirationTime;
+ }
+ } else if (alternate !== null && alternate.childExpirationTime < expirationTime) {
+ alternate.childExpirationTime = expirationTime;
+ }
+ if (node.return === null && node.tag === HostRoot) {
+ root = node.stateNode;
+ break;
+ }
+ node = node.return;
+ }
+ }
+
+ if (enableSchedulerTracing) {
+ if (root !== null) {
+ var interactions = __interactionsRef.current;
+ if (interactions.size > 0) {
+ var pendingInteractionMap = root.pendingInteractionMap;
+ var pendingInteractions = pendingInteractionMap.get(expirationTime);
+ if (pendingInteractions != null) {
+ interactions.forEach(function (interaction) {
+ if (!pendingInteractions.has(interaction)) {
+ // Update the pending async work count for previously unscheduled interaction.
+ interaction.__count++;
+ }
+
+ pendingInteractions.add(interaction);
+ });
+ } else {
+ pendingInteractionMap.set(expirationTime, new Set(interactions));
+
+ // Update the pending async work count for the current interactions.
+ interactions.forEach(function (interaction) {
+ interaction.__count++;
+ });
+ }
+
+ var subscriber = __subscriberRef.current;
+ if (subscriber !== null) {
+ var threadID = computeThreadID(expirationTime, root.interactionThreadID);
+ subscriber.onWorkScheduled(interactions, threadID);
+ }
+ }
+ }
+ }
+ return root;
+}
+
+
+
+function scheduleWork(fiber, expirationTime) {
+ var root = scheduleWorkToRoot(fiber, expirationTime);
+ if (root === null) {
+ return;
+ }
+
+ if (!isWorking && nextRenderExpirationTime !== NoWork && expirationTime > nextRenderExpirationTime) {
+ // This is an interruption. (Used for performance tracking.)
+ interruptedBy = fiber;
+ resetStack();
+ }
+ markPendingPriorityLevel(root, expirationTime);
+ if (
+ // If we're in the render phase, we don't need to schedule this root
+ // for an update, because we'll do it before we exit...
+ !isWorking || isCommitting$1 ||
+ // ...unless this is a different root than the one we're rendering.
+ nextRoot !== root) {
+ var rootExpirationTime = root.expirationTime;
+ requestWork(root, rootExpirationTime);
+ }
+ if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
+ // Reset this back to zero so subsequent updates don't throw.
+ nestedUpdateCount = 0;
+ reactProdInvariant('185');
+ }
+}
+
+function syncUpdates(fn, a, b, c, d) {
+ return unstable_runWithPriority(unstable_ImmediatePriority, function () {
+ return fn(a, b, c, d);
+ });
+}
+
+// TODO: Everything below this is written as if it has been lifted to the
+// renderers. I'll do this in a follow-up.
+
+// Linked-list of roots
+var firstScheduledRoot = null;
+var lastScheduledRoot = null;
+
+var callbackExpirationTime = NoWork;
+var callbackID = void 0;
+var isRendering = false;
+var nextFlushedRoot = null;
+var nextFlushedExpirationTime = NoWork;
+var hasUnhandledError = false;
+var unhandledError = null;
+
+var isBatchingUpdates = false;
+var isUnbatchingUpdates = false;
+
+var completedBatches = null;
+
+var originalStartTimeMs = now();
+var currentRendererTime = msToExpirationTime(originalStartTimeMs);
+var currentSchedulerTime = currentRendererTime;
+
+// Use these to prevent an infinite loop of nested updates
+var NESTED_UPDATE_LIMIT = 50;
+var nestedUpdateCount = 0;
+var lastCommittedRootDuringThisBatch = null;
+
+function recomputeCurrentRendererTime() {
+ var currentTimeMs = now() - originalStartTimeMs;
+ currentRendererTime = msToExpirationTime(currentTimeMs);
+}
+
+function scheduleCallbackWithExpirationTime(root, expirationTime) {
+ if (callbackExpirationTime !== NoWork) {
+ // A callback is already scheduled. Check its expiration time (timeout).
+ if (expirationTime < callbackExpirationTime) {
+ // Existing callback has sufficient timeout. Exit.
+ return;
+ } else {
+ if (callbackID !== null) {
+ // Existing callback has insufficient timeout. Cancel and schedule a
+ // new one.
+ cancelDeferredCallback$$1(callbackID);
+ }
+ }
+ // The request callback timer is already running. Don't start a new one.
+ } else {
+ startRequestCallbackTimer();
+ }
+
+ callbackExpirationTime = expirationTime;
+ var currentMs = now() - originalStartTimeMs;
+ var expirationTimeMs = expirationTimeToMs(expirationTime);
+ var timeout = expirationTimeMs - currentMs;
+ callbackID = scheduleDeferredCallback$$1(performAsyncWork, { timeout: timeout });
+}
+
+// For every call to renderRoot, one of onFatal, onComplete, onSuspend, and
+// onYield is called upon exiting. We use these in lieu of returning a tuple.
+// I've also chosen not to inline them into renderRoot because these will
+// eventually be lifted into the renderer.
+function onFatal(root) {
+ root.finishedWork = null;
+}
+
+function onComplete(root, finishedWork, expirationTime) {
+ root.pendingCommitExpirationTime = expirationTime;
+ root.finishedWork = finishedWork;
+}
+
+function onSuspend(root, finishedWork, suspendedExpirationTime, rootExpirationTime, msUntilTimeout) {
+ root.expirationTime = rootExpirationTime;
+ if (msUntilTimeout === 0 && !shouldYieldToRenderer()) {
+ // Don't wait an additional tick. Commit the tree immediately.
+ root.pendingCommitExpirationTime = suspendedExpirationTime;
+ root.finishedWork = finishedWork;
+ } else if (msUntilTimeout > 0) {
+ // Wait `msUntilTimeout` milliseconds before committing.
+ root.timeoutHandle = scheduleTimeout(onTimeout.bind(null, root, finishedWork, suspendedExpirationTime), msUntilTimeout);
+ }
+}
+
+function onYield(root) {
+ root.finishedWork = null;
+}
+
+function onTimeout(root, finishedWork, suspendedExpirationTime) {
+ // The root timed out. Commit it.
+ root.pendingCommitExpirationTime = suspendedExpirationTime;
+ root.finishedWork = finishedWork;
+ // Read the current time before entering the commit phase. We can be
+ // certain this won't cause tearing related to batching of event updates
+ // because we're at the top of a timer event.
+ recomputeCurrentRendererTime();
+ currentSchedulerTime = currentRendererTime;
+ flushRoot(root, suspendedExpirationTime);
+}
+
+function onCommit(root, expirationTime) {
+ root.expirationTime = expirationTime;
+ root.finishedWork = null;
+}
+
+function requestCurrentTime() {
+ // requestCurrentTime is called by the scheduler to compute an expiration
+ // time.
+ //
+ // Expiration times are computed by adding to the current time (the start
+ // time). However, if two updates are scheduled within the same event, we
+ // should treat their start times as simultaneous, even if the actual clock
+ // time has advanced between the first and second call.
+
+ // In other words, because expiration times determine how updates are batched,
+ // we want all updates of like priority that occur within the same event to
+ // receive the same expiration time. Otherwise we get tearing.
+ //
+ // We keep track of two separate times: the current "renderer" time and the
+ // current "scheduler" time. The renderer time can be updated whenever; it
+ // only exists to minimize the calls performance.now.
+ //
+ // But the scheduler time can only be updated if there's no pending work, or
+ // if we know for certain that we're not in the middle of an event.
+
+ if (isRendering) {
+ // We're already rendering. Return the most recently read time.
+ return currentSchedulerTime;
+ }
+ // Check if there's pending work.
+ findHighestPriorityRoot();
+ if (nextFlushedExpirationTime === NoWork || nextFlushedExpirationTime === Never) {
+ // If there's no pending work, or if the pending work is offscreen, we can
+ // read the current time without risk of tearing.
+ recomputeCurrentRendererTime();
+ currentSchedulerTime = currentRendererTime;
+ return currentSchedulerTime;
+ }
+ // There's already pending work. We might be in the middle of a browser
+ // event. If we were to read the current time, it could cause multiple updates
+ // within the same event to receive different expiration times, leading to
+ // tearing. Return the last read time. During the next idle callback, the
+ // time will be updated.
+ return currentSchedulerTime;
+}
+
+// requestWork is called by the scheduler whenever a root receives an update.
+// It's up to the renderer to call renderRoot at some point in the future.
+function requestWork(root, expirationTime) {
+ addRootToSchedule(root, expirationTime);
+ if (isRendering) {
+ // Prevent reentrancy. Remaining work will be scheduled at the end of
+ // the currently rendering batch.
+ return;
+ }
+
+ if (isBatchingUpdates) {
+ // Flush work at the end of the batch.
+ if (isUnbatchingUpdates) {
+ // ...unless we're inside unbatchedUpdates, in which case we should
+ // flush it now.
+ nextFlushedRoot = root;
+ nextFlushedExpirationTime = Sync;
+ performWorkOnRoot(root, Sync, false);
+ }
+ return;
+ }
+
+ // TODO: Get rid of Sync and use current time?
+ if (expirationTime === Sync) {
+ performSyncWork();
+ } else {
+ scheduleCallbackWithExpirationTime(root, expirationTime);
+ }
+}
+
+function addRootToSchedule(root, expirationTime) {
+ // Add the root to the schedule.
+ // Check if this root is already part of the schedule.
+ if (root.nextScheduledRoot === null) {
+ // This root is not already scheduled. Add it.
+ root.expirationTime = expirationTime;
+ if (lastScheduledRoot === null) {
+ firstScheduledRoot = lastScheduledRoot = root;
+ root.nextScheduledRoot = root;
+ } else {
+ lastScheduledRoot.nextScheduledRoot = root;
+ lastScheduledRoot = root;
+ lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
+ }
+ } else {
+ // This root is already scheduled, but its priority may have increased.
+ var remainingExpirationTime = root.expirationTime;
+ if (expirationTime > remainingExpirationTime) {
+ // Update the priority.
+ root.expirationTime = expirationTime;
+ }
+ }
+}
+
+function findHighestPriorityRoot() {
+ var highestPriorityWork = NoWork;
+ var highestPriorityRoot = null;
+ if (lastScheduledRoot !== null) {
+ var previousScheduledRoot = lastScheduledRoot;
+ var root = firstScheduledRoot;
+ while (root !== null) {
+ var remainingExpirationTime = root.expirationTime;
+ if (remainingExpirationTime === NoWork) {
+ // This root no longer has work. Remove it from the scheduler.
+
+ // TODO: This check is redudant, but Flow is confused by the branch
+ // below where we set lastScheduledRoot to null, even though we break
+ // from the loop right after.
+ !(previousScheduledRoot !== null && lastScheduledRoot !== null) ? reactProdInvariant('244') : void 0;
+ if (root === root.nextScheduledRoot) {
+ // This is the only root in the list.
+ root.nextScheduledRoot = null;
+ firstScheduledRoot = lastScheduledRoot = null;
+ break;
+ } else if (root === firstScheduledRoot) {
+ // This is the first root in the list.
+ var next = root.nextScheduledRoot;
+ firstScheduledRoot = next;
+ lastScheduledRoot.nextScheduledRoot = next;
+ root.nextScheduledRoot = null;
+ } else if (root === lastScheduledRoot) {
+ // This is the last root in the list.
+ lastScheduledRoot = previousScheduledRoot;
+ lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
+ root.nextScheduledRoot = null;
+ break;
+ } else {
+ previousScheduledRoot.nextScheduledRoot = root.nextScheduledRoot;
+ root.nextScheduledRoot = null;
+ }
+ root = previousScheduledRoot.nextScheduledRoot;
+ } else {
+ if (remainingExpirationTime > highestPriorityWork) {
+ // Update the priority, if it's higher
+ highestPriorityWork = remainingExpirationTime;
+ highestPriorityRoot = root;
+ }
+ if (root === lastScheduledRoot) {
+ break;
+ }
+ if (highestPriorityWork === Sync) {
+ // Sync is highest priority by definition so
+ // we can stop searching.
+ break;
+ }
+ previousScheduledRoot = root;
+ root = root.nextScheduledRoot;
+ }
+ }
+ }
+
+ nextFlushedRoot = highestPriorityRoot;
+ nextFlushedExpirationTime = highestPriorityWork;
+}
+
+// TODO: This wrapper exists because many of the older tests (the ones that use
+// flushDeferredPri) rely on the number of times `shouldYield` is called. We
+// should get rid of it.
+var didYield = false;
+function shouldYieldToRenderer() {
+ if (didYield) {
+ return true;
+ }
+ if (shouldYield$$1()) {
+ didYield = true;
+ return true;
+ }
+ return false;
+}
+
+function performAsyncWork() {
+ try {
+ if (!shouldYieldToRenderer()) {
+ // The callback timed out. That means at least one update has expired.
+ // Iterate through the root schedule. If they contain expired work, set
+ // the next render expiration time to the current time. This has the effect
+ // of flushing all expired work in a single batch, instead of flushing each
+ // level one at a time.
+ if (firstScheduledRoot !== null) {
+ recomputeCurrentRendererTime();
+ var root = firstScheduledRoot;
+ do {
+ didExpireAtExpirationTime(root, currentRendererTime);
+ // The root schedule is circular, so this is never null.
+ root = root.nextScheduledRoot;
+ } while (root !== firstScheduledRoot);
+ }
+ }
+ performWork(NoWork, true);
+ } finally {
+ didYield = false;
+ }
+}
+
+function performSyncWork() {
+ performWork(Sync, false);
+}
+
+function performWork(minExpirationTime, isYieldy) {
+ // Keep working on roots until there's no more work, or until there's a higher
+ // priority event.
+ findHighestPriorityRoot();
+
+ if (isYieldy) {
+ recomputeCurrentRendererTime();
+ currentSchedulerTime = currentRendererTime;
+
+ if (enableUserTimingAPI) {
+ var didExpire = nextFlushedExpirationTime > currentRendererTime;
+ var timeout = expirationTimeToMs(nextFlushedExpirationTime);
+ stopRequestCallbackTimer(didExpire, timeout);
+ }
+
+ while (nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && minExpirationTime <= nextFlushedExpirationTime && !(didYield && currentRendererTime > nextFlushedExpirationTime)) {
+ performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, currentRendererTime > nextFlushedExpirationTime);
+ findHighestPriorityRoot();
+ recomputeCurrentRendererTime();
+ currentSchedulerTime = currentRendererTime;
+ }
+ } else {
+ while (nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && minExpirationTime <= nextFlushedExpirationTime) {
+ performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, false);
+ findHighestPriorityRoot();
+ }
+ }
+
+ // We're done flushing work. Either we ran out of time in this callback,
+ // or there's no more work left with sufficient priority.
+
+ // If we're inside a callback, set this to false since we just completed it.
+ if (isYieldy) {
+ callbackExpirationTime = NoWork;
+ callbackID = null;
+ }
+ // If there's work left over, schedule a new callback.
+ if (nextFlushedExpirationTime !== NoWork) {
+ scheduleCallbackWithExpirationTime(nextFlushedRoot, nextFlushedExpirationTime);
+ }
+
+ // Clean-up.
+ finishRendering();
+}
+
+function flushRoot(root, expirationTime) {
+ !!isRendering ? reactProdInvariant('253') : void 0;
+ // Perform work on root as if the given expiration time is the current time.
+ // This has the effect of synchronously flushing all work up to and
+ // including the given time.
+ nextFlushedRoot = root;
+ nextFlushedExpirationTime = expirationTime;
+ performWorkOnRoot(root, expirationTime, false);
+ // Flush any sync work that was scheduled by lifecycles
+ performSyncWork();
+}
+
+function finishRendering() {
+ nestedUpdateCount = 0;
+ lastCommittedRootDuringThisBatch = null;
+
+ if (completedBatches !== null) {
+ var batches = completedBatches;
+ completedBatches = null;
+ for (var i = 0; i < batches.length; i++) {
+ var batch = batches[i];
+ try {
+ batch._onComplete();
+ } catch (error) {
+ if (!hasUnhandledError) {
+ hasUnhandledError = true;
+ unhandledError = error;
+ }
+ }
+ }
+ }
+
+ if (hasUnhandledError) {
+ var error = unhandledError;
+ unhandledError = null;
+ hasUnhandledError = false;
+ throw error;
+ }
+}
+
+function performWorkOnRoot(root, expirationTime, isYieldy) {
+ !!isRendering ? reactProdInvariant('245') : void 0;
+
+ isRendering = true;
+
+ // Check if this is async work or sync/expired work.
+ if (!isYieldy) {
+ // Flush work without yielding.
+ // TODO: Non-yieldy work does not necessarily imply expired work. A renderer
+ // may want to perform some work without yielding, but also without
+ // requiring the root to complete (by triggering placeholders).
+
+ var finishedWork = root.finishedWork;
+ if (finishedWork !== null) {
+ // This root is already complete. We can commit it.
+ completeRoot(root, finishedWork, expirationTime);
+ } else {
+ root.finishedWork = null;
+ // If this root previously suspended, clear its existing timeout, since
+ // we're about to try rendering again.
+ var timeoutHandle = root.timeoutHandle;
+ if (timeoutHandle !== noTimeout) {
+ root.timeoutHandle = noTimeout;
+ // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above
+ cancelTimeout(timeoutHandle);
+ }
+ renderRoot(root, isYieldy);
+ finishedWork = root.finishedWork;
+ if (finishedWork !== null) {
+ // We've completed the root. Commit it.
+ completeRoot(root, finishedWork, expirationTime);
+ }
+ }
+ } else {
+ // Flush async work.
+ var _finishedWork = root.finishedWork;
+ if (_finishedWork !== null) {
+ // This root is already complete. We can commit it.
+ completeRoot(root, _finishedWork, expirationTime);
+ } else {
+ root.finishedWork = null;
+ // If this root previously suspended, clear its existing timeout, since
+ // we're about to try rendering again.
+ var _timeoutHandle = root.timeoutHandle;
+ if (_timeoutHandle !== noTimeout) {
+ root.timeoutHandle = noTimeout;
+ // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above
+ cancelTimeout(_timeoutHandle);
+ }
+ renderRoot(root, isYieldy);
+ _finishedWork = root.finishedWork;
+ if (_finishedWork !== null) {
+ // We've completed the root. Check the if we should yield one more time
+ // before committing.
+ if (!shouldYieldToRenderer()) {
+ // Still time left. Commit the root.
+ completeRoot(root, _finishedWork, expirationTime);
+ } else {
+ // There's no time left. Mark this root as complete. We'll come
+ // back and commit it later.
+ root.finishedWork = _finishedWork;
+ }
+ }
+ }
+ }
+
+ isRendering = false;
+}
+
+function completeRoot(root, finishedWork, expirationTime) {
+ // Check if there's a batch that matches this expiration time.
+ var firstBatch = root.firstBatch;
+ if (firstBatch !== null && firstBatch._expirationTime >= expirationTime) {
+ if (completedBatches === null) {
+ completedBatches = [firstBatch];
+ } else {
+ completedBatches.push(firstBatch);
+ }
+ if (firstBatch._defer) {
+ // This root is blocked from committing by a batch. Unschedule it until
+ // we receive another update.
+ root.finishedWork = finishedWork;
+ root.expirationTime = NoWork;
+ return;
+ }
+ }
+
+ // Commit the root.
+ root.finishedWork = null;
+
+ // Check if this is a nested update (a sync update scheduled during the
+ // commit phase).
+ if (root === lastCommittedRootDuringThisBatch) {
+ // If the next root is the same as the previous root, this is a nested
+ // update. To prevent an infinite loop, increment the nested update count.
+ nestedUpdateCount++;
+ } else {
+ // Reset whenever we switch roots.
+ lastCommittedRootDuringThisBatch = root;
+ nestedUpdateCount = 0;
+ }
+ unstable_runWithPriority(unstable_ImmediatePriority, function () {
+ commitRoot(root, finishedWork);
+ });
+}
+
+function onUncaughtError(error) {
+ !(nextFlushedRoot !== null) ? reactProdInvariant('246') : void 0;
+ // Unschedule this root so we don't work on it again until there's
+ // another update.
+ nextFlushedRoot.expirationTime = NoWork;
+ if (!hasUnhandledError) {
+ hasUnhandledError = true;
+ unhandledError = error;
+ }
+}
+
+// TODO: Batching should be implemented at the renderer level, not inside
+// the reconciler.
+function batchedUpdates(fn, a) {
+ var previousIsBatchingUpdates = isBatchingUpdates;
+ isBatchingUpdates = true;
+ try {
+ return fn(a);
+ } finally {
+ isBatchingUpdates = previousIsBatchingUpdates;
+ if (!isBatchingUpdates && !isRendering) {
+ performSyncWork();
+ }
+ }
+}
+
+// TODO: Batching should be implemented at the renderer level, not within
+// the reconciler.
+function flushSync(fn, a) {
+ !!isRendering ? reactProdInvariant('187') : void 0;
+ var previousIsBatchingUpdates = isBatchingUpdates;
+ isBatchingUpdates = true;
+ try {
+ return syncUpdates(fn, a);
+ } finally {
+ isBatchingUpdates = previousIsBatchingUpdates;
+ performSyncWork();
+ }
+}
+
+function getContextForSubtree(parentComponent) {
+ if (!parentComponent) {
+ return emptyContextObject;
+ }
+
+ var fiber = get(parentComponent);
+ var parentContext = findCurrentUnmaskedContext(fiber);
+
+ if (fiber.tag === ClassComponent) {
+ var Component = fiber.type;
+ if (isContextProvider(Component)) {
+ return processChildContext(fiber, Component, parentContext);
+ }
+ }
+
+ return parentContext;
+}
+
+function scheduleRootUpdate(current$$1, element, expirationTime, callback) {
+ var update = createUpdate(expirationTime);
+ // Caution: React DevTools currently depends on this property
+ // being called "element".
+ update.payload = { element: element };
+
+ callback = callback === undefined ? null : callback;
+ if (callback !== null) {
+ update.callback = callback;
+ }
+
+ flushPassiveEffects$1();
+ enqueueUpdate(current$$1, update);
+ scheduleWork(current$$1, expirationTime);
+
+ return expirationTime;
+}
+
+function updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback) {
+ // TODO: If this is a nested container, this won't be the root.
+ var current$$1 = container.current;
+
+ var context = getContextForSubtree(parentComponent);
+ if (container.context === null) {
+ container.context = context;
+ } else {
+ container.pendingContext = context;
+ }
+
+ return scheduleRootUpdate(current$$1, element, expirationTime, callback);
+}
+
+function createContainer(containerInfo, isConcurrent, hydrate) {
+ return createFiberRoot(containerInfo, isConcurrent, hydrate);
+}
+
+function updateContainer(element, container, parentComponent, callback) {
+ var current$$1 = container.current;
+ var currentTime = requestCurrentTime();
+ var expirationTime = computeExpirationForFiber(currentTime, current$$1);
+ return updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback);
+}
+
+function getPublicRootInstance(container) {
+ var containerFiber = container.current;
+ if (!containerFiber.child) {
+ return null;
+ }
+ switch (containerFiber.child.tag) {
+ case HostComponent:
+ return getPublicInstance(containerFiber.child.stateNode);
+ default:
+ return containerFiber.child.stateNode;
+ }
+}
+
+
+
+var overrideProps = null;
+
+function injectIntoDevTools(devToolsConfig) {
+ var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance;
+ var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
+
+
+ return injectInternals(_assign({}, devToolsConfig, {
+ overrideProps: overrideProps,
+ currentDispatcherRef: ReactCurrentDispatcher,
+ findHostInstanceByFiber: function (fiber) {
+ var hostFiber = findCurrentHostFiber(fiber);
+ if (hostFiber === null) {
+ return null;
+ }
+ return hostFiber.stateNode;
+ },
+ findFiberByHostInstance: function (instance) {
+ if (!findFiberByHostInstance) {
+ // Might not be implemented by the renderer.
+ return null;
+ }
+ return findFiberByHostInstance(instance);
+ }
+ }));
+}
+
+// This file intentionally does *not* have the Flow annotation.
+// Don't add it. See `./inline-typed.js` for an explanation.
+
+// TODO: this is special because it gets imported during build.
+
+var ReactVersion = '16.8.6';
+
+var _createClass = function () { 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
+
+// for .act's return value
+
+
+var defaultTestOptions = {
+ createNodeMock: function () {
+ return null;
+ }
+};
+
+function toJSON(inst) {
+ if (inst.isHidden) {
+ // Omit timed out children from output entirely. This seems like the least
+ // surprising behavior. We could perhaps add a separate API that includes
+ // them, if it turns out people need it.
+ return null;
+ }
+ switch (inst.tag) {
+ case 'TEXT':
+ return inst.text;
+ case 'INSTANCE':
+ {
+ /* eslint-disable no-unused-vars */
+ // We don't include the `children` prop in JSON.
+ // Instead, we will include the actual rendered children.
+ var _inst$props = inst.props,
+ _children = _inst$props.children,
+ _props = _objectWithoutProperties(_inst$props, ['children']);
+ /* eslint-enable */
+
+
+ var renderedChildren = null;
+ if (inst.children && inst.children.length) {
+ for (var i = 0; i < inst.children.length; i++) {
+ var renderedChild = toJSON(inst.children[i]);
+ if (renderedChild !== null) {
+ if (renderedChildren === null) {
+ renderedChildren = [renderedChild];
+ } else {
+ renderedChildren.push(renderedChild);
+ }
+ }
+ }
+ }
+ var json = {
+ type: inst.type,
+ props: _props,
+ children: renderedChildren
+ };
+ Object.defineProperty(json, '$$typeof', {
+ value: Symbol.for('react.test.json')
+ });
+ return json;
+ }
+ default:
+ throw new Error('Unexpected node type in toJSON: ' + inst.tag);
+ }
+}
+
+function childrenToTree(node) {
+ if (!node) {
+ return null;
+ }
+ var children = nodeAndSiblingsArray(node);
+ if (children.length === 0) {
+ return null;
+ } else if (children.length === 1) {
+ return toTree(children[0]);
+ }
+ return flatten(children.map(toTree));
+}
+
+function nodeAndSiblingsArray(nodeWithSibling) {
+ var array = [];
+ var node = nodeWithSibling;
+ while (node != null) {
+ array.push(node);
+ node = node.sibling;
+ }
+ return array;
+}
+
+function flatten(arr) {
+ var result = [];
+ var stack = [{ i: 0, array: arr }];
+ while (stack.length) {
+ var n = stack.pop();
+ while (n.i < n.array.length) {
+ var el = n.array[n.i];
+ n.i += 1;
+ if (Array.isArray(el)) {
+ stack.push(n);
+ stack.push({ i: 0, array: el });
+ break;
+ }
+ result.push(el);
+ }
+ }
+ return result;
+}
+
+function toTree(node) {
+ if (node == null) {
+ return null;
+ }
+ switch (node.tag) {
+ case HostRoot:
+ return childrenToTree(node.child);
+ case HostPortal:
+ return childrenToTree(node.child);
+ case ClassComponent:
+ return {
+ nodeType: 'component',
+ type: node.type,
+ props: _assign({}, node.memoizedProps),
+ instance: node.stateNode,
+ rendered: childrenToTree(node.child)
+ };
+ case FunctionComponent:
+ case SimpleMemoComponent:
+ return {
+ nodeType: 'component',
+ type: node.type,
+ props: _assign({}, node.memoizedProps),
+ instance: null,
+ rendered: childrenToTree(node.child)
+ };
+ case HostComponent:
+ {
+ return {
+ nodeType: 'host',
+ type: node.type,
+ props: _assign({}, node.memoizedProps),
+ instance: null, // TODO: use createNodeMock here somehow?
+ rendered: flatten(nodeAndSiblingsArray(node.child).map(toTree))
+ };
+ }
+ case HostText:
+ return node.stateNode.text;
+ case Fragment:
+ case ContextProvider:
+ case ContextConsumer:
+ case Mode:
+ case Profiler:
+ case ForwardRef:
+ case MemoComponent:
+ case IncompleteClassComponent:
+ return childrenToTree(node.child);
+ default:
+ reactProdInvariant('214', node.tag);
+ }
+}
+
+var validWrapperTypes = new Set([FunctionComponent, ClassComponent, HostComponent, ForwardRef, MemoComponent, SimpleMemoComponent,
+// Normally skipped, but used when there's more than one root child.
+HostRoot]);
+
+function getChildren(parent) {
+ var children = [];
+ var startingNode = parent;
+ var node = startingNode;
+ if (node.child === null) {
+ return children;
+ }
+ node.child.return = node;
+ node = node.child;
+ outer: while (true) {
+ var descend = false;
+ if (validWrapperTypes.has(node.tag)) {
+ children.push(wrapFiber(node));
+ } else if (node.tag === HostText) {
+ children.push('' + node.memoizedProps);
+ } else {
+ descend = true;
+ }
+ if (descend && node.child !== null) {
+ node.child.return = node;
+ node = node.child;
+ continue;
+ }
+ while (node.sibling === null) {
+ if (node.return === startingNode) {
+ break outer;
+ }
+ node = node.return;
+ }
+ node.sibling.return = node.return;
+ node = node.sibling;
+ }
+ return children;
+}
+
+var ReactTestInstance = function () {
+ ReactTestInstance.prototype._currentFiber = function _currentFiber() {
+ // Throws if this component has been unmounted.
+ var fiber = findCurrentFiberUsingSlowPath(this._fiber);
+ !(fiber !== null) ? reactProdInvariant('224') : void 0;
+ return fiber;
+ };
+
+ function ReactTestInstance(fiber) {
+ _classCallCheck(this, ReactTestInstance);
+
+ !validWrapperTypes.has(fiber.tag) ? reactProdInvariant('225', fiber.tag) : void 0;
+ this._fiber = fiber;
+ }
+
+ // Custom search functions
+ ReactTestInstance.prototype.find = function find(predicate) {
+ return expectOne(this.findAll(predicate, { deep: false }), 'matching custom predicate: ' + predicate.toString());
+ };
+
+ ReactTestInstance.prototype.findByType = function findByType(type) {
+ return expectOne(this.findAllByType(type, { deep: false }), 'with node type: "' + (type.displayName || type.name) + '"');
+ };
+
+ ReactTestInstance.prototype.findByProps = function findByProps(props) {
+ return expectOne(this.findAllByProps(props, { deep: false }), 'with props: ' + JSON.stringify(props));
+ };
+
+ ReactTestInstance.prototype.findAll = function findAll(predicate) {
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
+
+ return _findAll(this, predicate, options);
+ };
+
+ ReactTestInstance.prototype.findAllByType = function findAllByType(type) {
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
+
+ return _findAll(this, function (node) {
+ return node.type === type;
+ }, options);
+ };
+
+ ReactTestInstance.prototype.findAllByProps = function findAllByProps(props) {
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
+
+ return _findAll(this, function (node) {
+ return node.props && propsMatch(node.props, props);
+ }, options);
+ };
+
+ _createClass(ReactTestInstance, [{
+ key: 'instance',
+ get: function () {
+ if (this._fiber.tag === HostComponent) {
+ return getPublicInstance(this._fiber.stateNode);
+ } else {
+ return this._fiber.stateNode;
+ }
+ }
+ }, {
+ key: 'type',
+ get: function () {
+ return this._fiber.type;
+ }
+ }, {
+ key: 'props',
+ get: function () {
+ return this._currentFiber().memoizedProps;
+ }
+ }, {
+ key: 'parent',
+ get: function () {
+ var parent = this._fiber.return;
+ while (parent !== null) {
+ if (validWrapperTypes.has(parent.tag)) {
+ if (parent.tag === HostRoot) {
+ // Special case: we only "materialize" instances for roots
+ // if they have more than a single child. So we'll check that now.
+ if (getChildren(parent).length < 2) {
+ return null;
+ }
+ }
+ return wrapFiber(parent);
+ }
+ parent = parent.return;
+ }
+ return null;
+ }
+ }, {
+ key: 'children',
+ get: function () {
+ return getChildren(this._currentFiber());
+ }
+ }]);
+
+ return ReactTestInstance;
+}();
+
+function _findAll(root, predicate, options) {
+ var deep = options ? options.deep : true;
+ var results = [];
+
+ if (predicate(root)) {
+ results.push(root);
+ if (!deep) {
+ return results;
+ }
+ }
+
+ root.children.forEach(function (child) {
+ if (typeof child === 'string') {
+ return;
+ }
+ results.push.apply(results, _findAll(child, predicate, options));
+ });
+
+ return results;
+}
+
+function expectOne(all, message) {
+ if (all.length === 1) {
+ return all[0];
+ }
+
+ var prefix = all.length === 0 ? 'No instances found ' : 'Expected 1 but found ' + all.length + ' instances ';
+
+ throw new Error(prefix + message);
+}
+
+function propsMatch(props, filter) {
+ for (var key in filter) {
+ if (props[key] !== filter[key]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+var ReactTestRendererFiber = {
+ create: function (element, options) {
+ var createNodeMock = defaultTestOptions.createNodeMock;
+ var isConcurrent = false;
+ if (typeof options === 'object' && options !== null) {
+ if (typeof options.createNodeMock === 'function') {
+ createNodeMock = options.createNodeMock;
+ }
+ if (options.unstable_isConcurrent === true) {
+ isConcurrent = true;
+ }
+ }
+ var container = {
+ children: [],
+ createNodeMock: createNodeMock,
+ tag: 'CONTAINER'
+ };
+ var root = createContainer(container, isConcurrent, false);
+ !(root != null) ? reactProdInvariant('215') : void 0;
+ updateContainer(element, root, null, null);
+
+ var entry = {
+ root: undefined, // makes flow happy
+ // we define a 'getter' for 'root' below using 'Object.defineProperty'
+ toJSON: function () {
+ if (root == null || root.current == null || container == null) {
+ return null;
+ }
+ if (container.children.length === 0) {
+ return null;
+ }
+ if (container.children.length === 1) {
+ return toJSON(container.children[0]);
+ }
+ if (container.children.length === 2 && container.children[0].isHidden === true && container.children[1].isHidden === false) {
+ // Omit timed out children from output entirely, including the fact that we
+ // temporarily wrap fallback and timed out children in an array.
+ return toJSON(container.children[1]);
+ }
+ var renderedChildren = null;
+ if (container.children && container.children.length) {
+ for (var i = 0; i < container.children.length; i++) {
+ var renderedChild = toJSON(container.children[i]);
+ if (renderedChild !== null) {
+ if (renderedChildren === null) {
+ renderedChildren = [renderedChild];
+ } else {
+ renderedChildren.push(renderedChild);
+ }
+ }
+ }
+ }
+ return renderedChildren;
+ },
+ toTree: function () {
+ if (root == null || root.current == null) {
+ return null;
+ }
+ return toTree(root.current);
+ },
+ update: function (newElement) {
+ if (root == null || root.current == null) {
+ return;
+ }
+ updateContainer(newElement, root, null, null);
+ },
+ unmount: function () {
+ if (root == null || root.current == null) {
+ return;
+ }
+ updateContainer(null, root, null, null);
+ container = null;
+ root = null;
+ },
+ getInstance: function () {
+ if (root == null || root.current == null) {
+ return null;
+ }
+ return getPublicRootInstance(root);
+ },
+
+
+ unstable_flushAll: flushAll,
+ unstable_flushSync: function (fn) {
+ clearYields();
+ return flushSync(fn);
+ },
+
+ unstable_flushNumberOfYields: flushNumberOfYields,
+ unstable_clearYields: clearYields
+ };
+
+ Object.defineProperty(entry, 'root', {
+ configurable: true,
+ enumerable: true,
+ get: function () {
+ if (root === null) {
+ throw new Error("Can't access .root on unmounted test renderer");
+ }
+ var children = getChildren(root.current);
+ if (children.length === 0) {
+ throw new Error("Can't access .root on unmounted test renderer");
+ } else if (children.length === 1) {
+ // Normally, we skip the root and just give you the child.
+ return children[0];
+ } else {
+ // However, we give you the root if there's more than one root child.
+ // We could make this the behavior for all cases but it would be a breaking change.
+ return wrapFiber(root.current);
+ }
+ }
+ });
+
+ return entry;
+ },
+
+
+ unstable_yield: yieldValue,
+ unstable_clearYields: clearYields,
+
+ /* eslint-disable camelcase */
+ unstable_batchedUpdates: batchedUpdates,
+ /* eslint-enable camelcase */
+
+ unstable_setNowImplementation: setNowImplementation,
+
+ act: function (callback) {
+ // note: keep these warning messages in sync with
+ // createNoop.js and ReactTestUtils.js
+ var result = batchedUpdates(callback);
+ flushPassiveEffects();
+ // we want the user to not expect a return,
+ // but we want to warn if they use it like they can await on it.
+ return {
+ then: function () {
+
+ }
+ };
+ }
+};
+
+// root used to flush effects during .act() calls
+var actRoot = createContainer({
+ children: [],
+ createNodeMock: defaultTestOptions.createNodeMock,
+ tag: 'CONTAINER'
+}, true, false);
+
+function flushPassiveEffects() {
+ // Trick to flush passive effects without exposing an internal API:
+ // Create a throwaway root and schedule a dummy update on it.
+ updateContainer(null, actRoot, null, null);
+}
+
+var fiberToWrapper = new WeakMap();
+function wrapFiber(fiber) {
+ var wrapper = fiberToWrapper.get(fiber);
+ if (wrapper === undefined && fiber.alternate !== null) {
+ wrapper = fiberToWrapper.get(fiber.alternate);
+ }
+ if (wrapper === undefined) {
+ wrapper = new ReactTestInstance(fiber);
+ fiberToWrapper.set(fiber, wrapper);
+ }
+ return wrapper;
+}
+
+// Enable ReactTestRenderer to be used to test DevTools integration.
+injectIntoDevTools({
+ findFiberByHostInstance: function () {
+ throw new Error('TestRenderer does not support findFiberByHostInstance()');
+ },
+ bundleType: 0,
+ version: ReactVersion,
+ rendererPackageName: 'react-test-renderer'
+});
+
+
+
+var ReactTestRenderer = ({
+ default: ReactTestRendererFiber
+});
+
+var ReactTestRenderer$1 = ( ReactTestRenderer && ReactTestRendererFiber ) || ReactTestRenderer;
+
+// TODO: decide on the top-level export form.
+// This is hacky but makes it work with both Rollup and Jest.
+var reactTestRenderer = ReactTestRenderer$1.default || ReactTestRenderer$1;
+
+return reactTestRenderer;
+
+})));