summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/vendor/react-dom.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/vendor/react-dom.js')
-rw-r--r--devtools/client/shared/vendor/react-dom.js16370
1 files changed, 16370 insertions, 0 deletions
diff --git a/devtools/client/shared/vendor/react-dom.js b/devtools/client/shared/vendor/react-dom.js
new file mode 100644
index 0000000000..ca46bb9d75
--- /dev/null
+++ b/devtools/client/shared/vendor/react-dom.js
@@ -0,0 +1,16370 @@
+/** @license React v16.6.1
+ * react-dom.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('devtools/client/shared/vendor/react')) :
+ typeof define === 'function' && define.amd ? define(['devtools/client/shared/vendor/react'], factory) :
+ (global.ReactDOM = 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);
+}
+
+!React ? reactProdInvariant('227') : void 0;
+
+var invokeGuardedCallbackImpl = function (name, func, context, a, b, c, d, e, f) {
+ var funcArgs = Array.prototype.slice.call(arguments, 3);
+ try {
+ func.apply(context, funcArgs);
+ } catch (error) {
+ this.onError(error);
+ }
+};
+
+// Used by Fiber to simulate a try-catch.
+var hasError = false;
+var caughtError = null;
+
+// Used by event system to capture/rethrow the first error.
+var hasRethrowError = false;
+var rethrowError = null;
+
+var reporter = {
+ onError: function (error) {
+ hasError = true;
+ caughtError = error;
+ }
+};
+
+/**
+ * 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
+ */
+function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
+ hasError = false;
+ caughtError = null;
+ invokeGuardedCallbackImpl.apply(reporter, arguments);
+}
+
+/**
+ * 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
+ */
+function invokeGuardedCallbackAndCatchFirstError(name, func, context, a, b, c, d, e, f) {
+ invokeGuardedCallback.apply(this, arguments);
+ if (hasError) {
+ var error = clearCaughtError();
+ if (!hasRethrowError) {
+ hasRethrowError = true;
+ rethrowError = error;
+ }
+ }
+}
+
+/**
+ * During execution of guarded functions we will capture the first error which
+ * we will rethrow to be handled by the top level error handler.
+ */
+function rethrowCaughtError() {
+ if (hasRethrowError) {
+ var error = rethrowError;
+ hasRethrowError = false;
+ rethrowError = null;
+ throw error;
+ }
+}
+
+
+
+function clearCaughtError() {
+ if (hasError) {
+ var error = caughtError;
+ hasError = false;
+ caughtError = null;
+ return error;
+ } else {
+ reactProdInvariant('198');
+ }
+}
+
+/**
+ * Injectable ordering of event plugins.
+ */
+var eventPluginOrder = null;
+
+/**
+ * Injectable mapping from names to event plugin modules.
+ */
+var namesToPlugins = {};
+
+/**
+ * Recomputes the plugin list using the injected plugins and plugin ordering.
+ *
+ * @private
+ */
+function recomputePluginOrdering() {
+ if (!eventPluginOrder) {
+ // Wait until an `eventPluginOrder` is injected.
+ return;
+ }
+ for (var pluginName in namesToPlugins) {
+ var pluginModule = namesToPlugins[pluginName];
+ var pluginIndex = eventPluginOrder.indexOf(pluginName);
+ !(pluginIndex > -1) ? reactProdInvariant('96', pluginName) : void 0;
+ if (plugins[pluginIndex]) {
+ continue;
+ }
+ !pluginModule.extractEvents ? reactProdInvariant('97', pluginName) : void 0;
+ plugins[pluginIndex] = pluginModule;
+ var publishedEvents = pluginModule.eventTypes;
+ for (var eventName in publishedEvents) {
+ !publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) ? reactProdInvariant('98', eventName, pluginName) : void 0;
+ }
+ }
+}
+
+/**
+ * Publishes an event so that it can be dispatched by the supplied plugin.
+ *
+ * @param {object} dispatchConfig Dispatch configuration for the event.
+ * @param {object} PluginModule Plugin publishing the event.
+ * @return {boolean} True if the event was successfully published.
+ * @private
+ */
+function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
+ !!eventNameDispatchConfigs.hasOwnProperty(eventName) ? reactProdInvariant('99', eventName) : void 0;
+ eventNameDispatchConfigs[eventName] = dispatchConfig;
+
+ var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
+ if (phasedRegistrationNames) {
+ for (var phaseName in phasedRegistrationNames) {
+ if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
+ var phasedRegistrationName = phasedRegistrationNames[phaseName];
+ publishRegistrationName(phasedRegistrationName, pluginModule, eventName);
+ }
+ }
+ return true;
+ } else if (dispatchConfig.registrationName) {
+ publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Publishes a registration name that is used to identify dispatched events.
+ *
+ * @param {string} registrationName Registration name to add.
+ * @param {object} PluginModule Plugin publishing the event.
+ * @private
+ */
+function publishRegistrationName(registrationName, pluginModule, eventName) {
+ !!registrationNameModules[registrationName] ? reactProdInvariant('100', registrationName) : void 0;
+ registrationNameModules[registrationName] = pluginModule;
+ registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies;
+
+
+}
+
+/**
+ * Registers plugins so that they can extract and dispatch events.
+ *
+ * @see {EventPluginHub}
+ */
+
+/**
+ * Ordered list of injected plugins.
+ */
+var plugins = [];
+
+/**
+ * Mapping from event name to dispatch config
+ */
+var eventNameDispatchConfigs = {};
+
+/**
+ * Mapping from registration name to plugin module
+ */
+var registrationNameModules = {};
+
+/**
+ * Mapping from registration name to event name
+ */
+var registrationNameDependencies = {};
+
+/**
+ * Mapping from lowercase registration names to the properly cased version,
+ * used to warn in the case of missing event handlers. Available
+ * only in false.
+ * @type {Object}
+ */
+
+// Trust the developer to only use possibleRegistrationNames in false
+
+/**
+ * Injects an ordering of plugins (by plugin name). This allows the ordering
+ * to be decoupled from injection of the actual plugins so that ordering is
+ * always deterministic regardless of packaging, on-the-fly injection, etc.
+ *
+ * @param {array} InjectedEventPluginOrder
+ * @internal
+ * @see {EventPluginHub.injection.injectEventPluginOrder}
+ */
+function injectEventPluginOrder(injectedEventPluginOrder) {
+ !!eventPluginOrder ? reactProdInvariant('101') : void 0;
+ // Clone the ordering so it cannot be dynamically mutated.
+ eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder);
+ recomputePluginOrdering();
+}
+
+/**
+ * Injects plugins to be used by `EventPluginHub`. The plugin names must be
+ * in the ordering injected by `injectEventPluginOrder`.
+ *
+ * Plugins can be injected as part of page initialization or on-the-fly.
+ *
+ * @param {object} injectedNamesToPlugins Map from names to plugin modules.
+ * @internal
+ * @see {EventPluginHub.injection.injectEventPluginsByName}
+ */
+function injectEventPluginsByName(injectedNamesToPlugins) {
+ var isOrderingDirty = false;
+ for (var pluginName in injectedNamesToPlugins) {
+ if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
+ continue;
+ }
+ var pluginModule = injectedNamesToPlugins[pluginName];
+ if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) {
+ !!namesToPlugins[pluginName] ? reactProdInvariant('102', pluginName) : void 0;
+ namesToPlugins[pluginName] = pluginModule;
+ isOrderingDirty = true;
+ }
+ }
+ if (isOrderingDirty) {
+ recomputePluginOrdering();
+ }
+}
+
+/**
+ * Similar to invariant but only logs a warning if the condition is not met.
+ * This can be used to log issues in development environments in critical
+ * paths. Removing the logging code for production environments will keep the
+ * same logic and follow the same code paths.
+ */
+
+var getFiberCurrentPropsFromNode = null;
+var getInstanceFromNode = null;
+var getNodeFromInstance = null;
+
+function setComponentTree(getFiberCurrentPropsFromNodeImpl, getInstanceFromNodeImpl, getNodeFromInstanceImpl) {
+ getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl;
+ getInstanceFromNode = getInstanceFromNodeImpl;
+ getNodeFromInstance = getNodeFromInstanceImpl;
+
+}
+
+/**
+ * Dispatch the event to the listener.
+ * @param {SyntheticEvent} event SyntheticEvent to handle
+ * @param {function} listener Application-level callback
+ * @param {*} inst Internal component instance
+ */
+function executeDispatch(event, listener, inst) {
+ var type = event.type || 'unknown-event';
+ event.currentTarget = getNodeFromInstance(inst);
+ invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event);
+ event.currentTarget = null;
+}
+
+/**
+ * Standard/simple iteration through an event's collected dispatches.
+ */
+function executeDispatchesInOrder(event) {
+ var dispatchListeners = event._dispatchListeners;
+ var dispatchInstances = event._dispatchInstances;
+ if (Array.isArray(dispatchListeners)) {
+ for (var i = 0; i < dispatchListeners.length; i++) {
+ if (event.isPropagationStopped()) {
+ break;
+ }
+ // Listeners and Instances are two parallel arrays that are always in sync.
+ executeDispatch(event, dispatchListeners[i], dispatchInstances[i]);
+ }
+ } else if (dispatchListeners) {
+ executeDispatch(event, dispatchListeners, dispatchInstances);
+ }
+ event._dispatchListeners = null;
+ event._dispatchInstances = null;
+}
+
+/**
+ * @see executeDispatchesInOrderStopAtTrueImpl
+ */
+
+
+/**
+ * Execution of a "direct" dispatch - there must be at most one dispatch
+ * accumulated on the event or it is considered an error. It doesn't really make
+ * sense for an event with multiple dispatches (bubbled) to keep track of the
+ * return values at each dispatch execution, but it does tend to make sense when
+ * dealing with "direct" dispatches.
+ *
+ * @return {*} The return value of executing the single dispatch.
+ */
+
+
+/**
+ * @param {SyntheticEvent} event
+ * @return {boolean} True iff number of dispatches accumulated is greater than 0.
+ */
+
+/**
+ * Accumulates items that must not be null or undefined into the first one. This
+ * is used to conserve memory by avoiding array allocations, and thus sacrifices
+ * API cleanness. Since `current` can be null before being passed in and not
+ * null after this function, make sure to assign it back to `current`:
+ *
+ * `a = accumulateInto(a, b);`
+ *
+ * This API should be sparingly used. Try `accumulate` for something cleaner.
+ *
+ * @return {*|array<*>} An accumulation of items.
+ */
+
+function accumulateInto(current, next) {
+ !(next != null) ? reactProdInvariant('30') : void 0;
+
+ if (current == null) {
+ return next;
+ }
+
+ // Both are not empty. Warning: Never call x.concat(y) when you are not
+ // certain that x is an Array (x could be a string with concat method).
+ if (Array.isArray(current)) {
+ if (Array.isArray(next)) {
+ current.push.apply(current, next);
+ return current;
+ }
+ current.push(next);
+ return current;
+ }
+
+ if (Array.isArray(next)) {
+ // A bit too dangerous to mutate `next`.
+ return [current].concat(next);
+ }
+
+ return [current, next];
+}
+
+/**
+ * @param {array} arr an "accumulation" of items which is either an Array or
+ * a single item. Useful when paired with the `accumulate` module. This is a
+ * simple utility that allows us to reason about a collection of items, but
+ * handling the case when there is exactly one item (and we do not need to
+ * allocate an array).
+ * @param {function} cb Callback invoked with each element or a collection.
+ * @param {?} [scope] Scope used as `this` in a callback.
+ */
+function forEachAccumulated(arr, cb, scope) {
+ if (Array.isArray(arr)) {
+ arr.forEach(cb, scope);
+ } else if (arr) {
+ cb.call(scope, arr);
+ }
+}
+
+/**
+ * Internal queue of events that have accumulated their dispatches and are
+ * waiting to have their dispatches executed.
+ */
+var eventQueue = null;
+
+/**
+ * Dispatches an event and releases it back into the pool, unless persistent.
+ *
+ * @param {?object} event Synthetic event to be dispatched.
+ * @private
+ */
+var executeDispatchesAndRelease = function (event) {
+ if (event) {
+ executeDispatchesInOrder(event);
+
+ if (!event.isPersistent()) {
+ event.constructor.release(event);
+ }
+ }
+};
+var executeDispatchesAndReleaseTopLevel = function (e) {
+ return executeDispatchesAndRelease(e);
+};
+
+function isInteractive(tag) {
+ return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
+}
+
+function shouldPreventMouseEvent(name, type, props) {
+ switch (name) {
+ case 'onClick':
+ case 'onClickCapture':
+ case 'onDoubleClick':
+ case 'onDoubleClickCapture':
+ case 'onMouseDown':
+ case 'onMouseDownCapture':
+ case 'onMouseMove':
+ case 'onMouseMoveCapture':
+ case 'onMouseUp':
+ case 'onMouseUpCapture':
+ return !!(props.disabled && isInteractive(type));
+ default:
+ return false;
+ }
+}
+
+/**
+ * This is a unified interface for event plugins to be installed and configured.
+ *
+ * Event plugins can implement the following properties:
+ *
+ * `extractEvents` {function(string, DOMEventTarget, string, object): *}
+ * Required. When a top-level event is fired, this method is expected to
+ * extract synthetic events that will in turn be queued and dispatched.
+ *
+ * `eventTypes` {object}
+ * Optional, plugins that fire events must publish a mapping of registration
+ * names that are used to register listeners. Values of this mapping must
+ * be objects that contain `registrationName` or `phasedRegistrationNames`.
+ *
+ * `executeDispatch` {function(object, function, string)}
+ * Optional, allows plugins to override how an event gets dispatched. By
+ * default, the listener is simply invoked.
+ *
+ * Each plugin that is injected into `EventsPluginHub` is immediately operable.
+ *
+ * @public
+ */
+
+/**
+ * Methods for injecting dependencies.
+ */
+var injection = {
+ /**
+ * @param {array} InjectedEventPluginOrder
+ * @public
+ */
+ injectEventPluginOrder: injectEventPluginOrder,
+
+ /**
+ * @param {object} injectedNamesToPlugins Map from names to plugin modules.
+ */
+ injectEventPluginsByName: injectEventPluginsByName
+};
+
+/**
+ * @param {object} inst The instance, which is the source of events.
+ * @param {string} registrationName Name of listener (e.g. `onClick`).
+ * @return {?function} The stored callback.
+ */
+function getListener(inst, registrationName) {
+ var listener = void 0;
+
+ // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
+ // live here; needs to be moved to a better place soon
+ var stateNode = inst.stateNode;
+ if (!stateNode) {
+ // Work in progress (ex: onload events in incremental mode).
+ return null;
+ }
+ var props = getFiberCurrentPropsFromNode(stateNode);
+ if (!props) {
+ // Work in progress.
+ return null;
+ }
+ listener = props[registrationName];
+ if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
+ return null;
+ }
+ !(!listener || typeof listener === 'function') ? reactProdInvariant('231', registrationName, typeof listener) : void 0;
+ return listener;
+}
+
+/**
+ * Allows registered plugins an opportunity to extract events from top-level
+ * native browser events.
+ *
+ * @return {*} An accumulation of synthetic events.
+ * @internal
+ */
+function extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var events = null;
+ for (var i = 0; i < plugins.length; i++) {
+ // Not every plugin in the ordering may be loaded at runtime.
+ var possiblePlugin = plugins[i];
+ if (possiblePlugin) {
+ var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
+ if (extractedEvents) {
+ events = accumulateInto(events, extractedEvents);
+ }
+ }
+ }
+ return events;
+}
+
+function runEventsInBatch(events) {
+ if (events !== null) {
+ eventQueue = accumulateInto(eventQueue, events);
+ }
+
+ // Set `eventQueue` to null before processing it so that we can tell if more
+ // events get enqueued while processing.
+ var processingEventQueue = eventQueue;
+ eventQueue = null;
+
+ if (!processingEventQueue) {
+ return;
+ }
+
+ forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);
+ !!eventQueue ? reactProdInvariant('95') : void 0;
+ // This would be a good time to rethrow if any of the event handlers threw.
+ rethrowCaughtError();
+}
+
+function runExtractedEventsInBatch(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var events = extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
+ runEventsInBatch(events);
+}
+
+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;
+
+var randomKey = Math.random().toString(36).slice(2);
+var internalInstanceKey = '__reactInternalInstance$' + randomKey;
+var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
+
+function precacheFiberNode(hostInst, node) {
+ node[internalInstanceKey] = hostInst;
+}
+
+/**
+ * Given a DOM node, return the closest ReactDOMComponent or
+ * ReactDOMTextComponent instance ancestor.
+ */
+function getClosestInstanceFromNode(node) {
+ if (node[internalInstanceKey]) {
+ return node[internalInstanceKey];
+ }
+
+ while (!node[internalInstanceKey]) {
+ if (node.parentNode) {
+ node = node.parentNode;
+ } else {
+ // Top of the tree. This node must not be part of a React tree (or is
+ // unmounted, potentially).
+ return null;
+ }
+ }
+
+ var inst = node[internalInstanceKey];
+ if (inst.tag === HostComponent || inst.tag === HostText) {
+ // In Fiber, this will always be the deepest root.
+ return inst;
+ }
+
+ return null;
+}
+
+/**
+ * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
+ * instance, or null if the node was not rendered by this React.
+ */
+function getInstanceFromNode$1(node) {
+ var inst = node[internalInstanceKey];
+ if (inst) {
+ if (inst.tag === HostComponent || inst.tag === HostText) {
+ return inst;
+ } else {
+ return null;
+ }
+ }
+ return null;
+}
+
+/**
+ * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
+ * DOM node.
+ */
+function getNodeFromInstance$1(inst) {
+ if (inst.tag === HostComponent || inst.tag === HostText) {
+ // In Fiber this, is just the state node right now. We assume it will be
+ // a host component or host text.
+ return inst.stateNode;
+ }
+
+ // Without this first invariant, passing a non-DOM-component triggers the next
+ // invariant for a missing parent, which is super confusing.
+ reactProdInvariant('33');
+}
+
+function getFiberCurrentPropsFromNode$1(node) {
+ return node[internalEventHandlersKey] || null;
+}
+
+function updateFiberProps(node, props) {
+ node[internalEventHandlersKey] = props;
+}
+
+function getParent(inst) {
+ do {
+ inst = inst.return;
+ // TODO: If this is a HostRoot we might want to bail out.
+ // That is depending on if we want nested subtrees (layers) to bubble
+ // events to their parent. We could also go through parentNode on the
+ // host node but that wouldn't work for React Native and doesn't let us
+ // do the portal feature.
+ } while (inst && inst.tag !== HostComponent);
+ if (inst) {
+ return inst;
+ }
+ return null;
+}
+
+/**
+ * Return the lowest common ancestor of A and B, or null if they are in
+ * different trees.
+ */
+function getLowestCommonAncestor(instA, instB) {
+ var depthA = 0;
+ for (var tempA = instA; tempA; tempA = getParent(tempA)) {
+ depthA++;
+ }
+ var depthB = 0;
+ for (var tempB = instB; tempB; tempB = getParent(tempB)) {
+ depthB++;
+ }
+
+ // If A is deeper, crawl up.
+ while (depthA - depthB > 0) {
+ instA = getParent(instA);
+ depthA--;
+ }
+
+ // If B is deeper, crawl up.
+ while (depthB - depthA > 0) {
+ instB = getParent(instB);
+ depthB--;
+ }
+
+ // Walk in lockstep until we find a match.
+ var depth = depthA;
+ while (depth--) {
+ if (instA === instB || instA === instB.alternate) {
+ return instA;
+ }
+ instA = getParent(instA);
+ instB = getParent(instB);
+ }
+ return null;
+}
+
+/**
+ * Return if A is an ancestor of B.
+ */
+
+
+/**
+ * Return the parent instance of the passed-in instance.
+ */
+
+
+/**
+ * Simulates the traversal of a two-phase, capture/bubble event dispatch.
+ */
+function traverseTwoPhase(inst, fn, arg) {
+ var path = [];
+ while (inst) {
+ path.push(inst);
+ inst = getParent(inst);
+ }
+ var i = void 0;
+ for (i = path.length; i-- > 0;) {
+ fn(path[i], 'captured', arg);
+ }
+ for (i = 0; i < path.length; i++) {
+ fn(path[i], 'bubbled', arg);
+ }
+}
+
+/**
+ * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
+ * should would receive a `mouseEnter` or `mouseLeave` event.
+ *
+ * Does not invoke the callback on the nearest common ancestor because nothing
+ * "entered" or "left" that element.
+ */
+function traverseEnterLeave(from, to, fn, argFrom, argTo) {
+ var common = from && to ? getLowestCommonAncestor(from, to) : null;
+ var pathFrom = [];
+ while (true) {
+ if (!from) {
+ break;
+ }
+ if (from === common) {
+ break;
+ }
+ var alternate = from.alternate;
+ if (alternate !== null && alternate === common) {
+ break;
+ }
+ pathFrom.push(from);
+ from = getParent(from);
+ }
+ var pathTo = [];
+ while (true) {
+ if (!to) {
+ break;
+ }
+ if (to === common) {
+ break;
+ }
+ var _alternate = to.alternate;
+ if (_alternate !== null && _alternate === common) {
+ break;
+ }
+ pathTo.push(to);
+ to = getParent(to);
+ }
+ for (var i = 0; i < pathFrom.length; i++) {
+ fn(pathFrom[i], 'bubbled', argFrom);
+ }
+ for (var _i = pathTo.length; _i-- > 0;) {
+ fn(pathTo[_i], 'captured', argTo);
+ }
+}
+
+/**
+ * Some event types have a notion of different registration names for different
+ * "phases" of propagation. This finds listeners by a given phase.
+ */
+function listenerAtPhase(inst, event, propagationPhase) {
+ var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
+ return getListener(inst, registrationName);
+}
+
+/**
+ * A small set of propagation patterns, each of which will accept a small amount
+ * of information, and generate a set of "dispatch ready event objects" - which
+ * are sets of events that have already been annotated with a set of dispatched
+ * listener functions/ids. The API is designed this way to discourage these
+ * propagation strategies from actually executing the dispatches, since we
+ * always want to collect the entire set of dispatches before executing even a
+ * single one.
+ */
+
+/**
+ * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
+ * here, allows us to not have to bind or create functions for each event.
+ * Mutating the event's members allows us to not have to create a wrapping
+ * "dispatch" object that pairs the event with the listener.
+ */
+function accumulateDirectionalDispatches(inst, phase, event) {
+ var listener = listenerAtPhase(inst, event, phase);
+ if (listener) {
+ event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
+ event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
+ }
+}
+
+/**
+ * Collect dispatches (must be entirely collected before dispatching - see unit
+ * tests). Lazily allocate the array to conserve memory. We must loop through
+ * each event and perform the traversal for each one. We cannot perform a
+ * single traversal for the entire collection of events because each event may
+ * have a different target.
+ */
+function accumulateTwoPhaseDispatchesSingle(event) {
+ if (event && event.dispatchConfig.phasedRegistrationNames) {
+ traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
+ }
+}
+
+/**
+ * Accumulates without regard to direction, does not look for phased
+ * registration names. Same as `accumulateDirectDispatchesSingle` but without
+ * requiring that the `dispatchMarker` be the same as the dispatched ID.
+ */
+function accumulateDispatches(inst, ignoredDirection, event) {
+ if (inst && event && event.dispatchConfig.registrationName) {
+ var registrationName = event.dispatchConfig.registrationName;
+ var listener = getListener(inst, registrationName);
+ if (listener) {
+ event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
+ event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
+ }
+ }
+}
+
+/**
+ * Accumulates dispatches on an `SyntheticEvent`, but only for the
+ * `dispatchMarker`.
+ * @param {SyntheticEvent} event
+ */
+function accumulateDirectDispatchesSingle(event) {
+ if (event && event.dispatchConfig.registrationName) {
+ accumulateDispatches(event._targetInst, null, event);
+ }
+}
+
+function accumulateTwoPhaseDispatches(events) {
+ forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
+}
+
+
+
+function accumulateEnterLeaveDispatches(leave, enter, from, to) {
+ traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
+}
+
+function accumulateDirectDispatches(events) {
+ forEachAccumulated(events, accumulateDirectDispatchesSingle);
+}
+
+var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
+
+// Do not uses the below two methods directly!
+// Instead use constants exported from DOMTopLevelEventTypes in ReactDOM.
+// (It is the only module that is allowed to access these methods.)
+
+function unsafeCastStringToDOMTopLevelType(topLevelType) {
+ return topLevelType;
+}
+
+function unsafeCastDOMTopLevelTypeToString(topLevelType) {
+ return topLevelType;
+}
+
+/**
+ * Generate a mapping of standard vendor prefixes using the defined style property and event name.
+ *
+ * @param {string} styleProp
+ * @param {string} eventName
+ * @returns {object}
+ */
+function makePrefixMap(styleProp, eventName) {
+ var prefixes = {};
+
+ prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
+ prefixes['Webkit' + styleProp] = 'webkit' + eventName;
+ prefixes['Moz' + styleProp] = 'moz' + eventName;
+
+ return prefixes;
+}
+
+/**
+ * A list of event names to a configurable list of vendor prefixes.
+ */
+var vendorPrefixes = {
+ animationend: makePrefixMap('Animation', 'AnimationEnd'),
+ animationiteration: makePrefixMap('Animation', 'AnimationIteration'),
+ animationstart: makePrefixMap('Animation', 'AnimationStart'),
+ transitionend: makePrefixMap('Transition', 'TransitionEnd')
+};
+
+/**
+ * Event names that have already been detected and prefixed (if applicable).
+ */
+var prefixedEventNames = {};
+
+/**
+ * Element to check for prefixes on.
+ */
+var style = {};
+
+/**
+ * Bootstrap if a DOM exists.
+ */
+if (canUseDOM) {
+ style = document.createElementNS('http://www.w3.org/1999/xhtml', 'div').style;
+
+ // On some platforms, in particular some releases of Android 4.x,
+ // the un-prefixed "animation" and "transition" properties are defined on the
+ // style object but the events that fire will still be prefixed, so we need
+ // to check if the un-prefixed events are usable, and if not remove them from the map.
+ if (!('AnimationEvent' in window)) {
+ delete vendorPrefixes.animationend.animation;
+ delete vendorPrefixes.animationiteration.animation;
+ delete vendorPrefixes.animationstart.animation;
+ }
+
+ // Same as above
+ if (!('TransitionEvent' in window)) {
+ delete vendorPrefixes.transitionend.transition;
+ }
+}
+
+/**
+ * Attempts to determine the correct vendor prefixed event name.
+ *
+ * @param {string} eventName
+ * @returns {string}
+ */
+function getVendorPrefixedEventName(eventName) {
+ if (prefixedEventNames[eventName]) {
+ return prefixedEventNames[eventName];
+ } else if (!vendorPrefixes[eventName]) {
+ return eventName;
+ }
+
+ var prefixMap = vendorPrefixes[eventName];
+
+ for (var styleProp in prefixMap) {
+ if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {
+ return prefixedEventNames[eventName] = prefixMap[styleProp];
+ }
+ }
+
+ return eventName;
+}
+
+/**
+ * To identify top level events in ReactDOM, we use constants defined by this
+ * module. This is the only module that uses the unsafe* methods to express
+ * that the constants actually correspond to the browser event names. This lets
+ * us save some bundle size by avoiding a top level type -> event name map.
+ * The rest of ReactDOM code should import top level types from this file.
+ */
+var TOP_ABORT = unsafeCastStringToDOMTopLevelType('abort');
+var TOP_ANIMATION_END = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationend'));
+var TOP_ANIMATION_ITERATION = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationiteration'));
+var TOP_ANIMATION_START = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationstart'));
+var TOP_BLUR = unsafeCastStringToDOMTopLevelType('blur');
+var TOP_CAN_PLAY = unsafeCastStringToDOMTopLevelType('canplay');
+var TOP_CAN_PLAY_THROUGH = unsafeCastStringToDOMTopLevelType('canplaythrough');
+var TOP_CANCEL = unsafeCastStringToDOMTopLevelType('cancel');
+var TOP_CHANGE = unsafeCastStringToDOMTopLevelType('change');
+var TOP_CLICK = unsafeCastStringToDOMTopLevelType('click');
+var TOP_CLOSE = unsafeCastStringToDOMTopLevelType('close');
+var TOP_COMPOSITION_END = unsafeCastStringToDOMTopLevelType('compositionend');
+var TOP_COMPOSITION_START = unsafeCastStringToDOMTopLevelType('compositionstart');
+var TOP_COMPOSITION_UPDATE = unsafeCastStringToDOMTopLevelType('compositionupdate');
+var TOP_CONTEXT_MENU = unsafeCastStringToDOMTopLevelType('contextmenu');
+var TOP_COPY = unsafeCastStringToDOMTopLevelType('copy');
+var TOP_CUT = unsafeCastStringToDOMTopLevelType('cut');
+var TOP_DOUBLE_CLICK = unsafeCastStringToDOMTopLevelType('dblclick');
+var TOP_AUX_CLICK = unsafeCastStringToDOMTopLevelType('auxclick');
+var TOP_DRAG = unsafeCastStringToDOMTopLevelType('drag');
+var TOP_DRAG_END = unsafeCastStringToDOMTopLevelType('dragend');
+var TOP_DRAG_ENTER = unsafeCastStringToDOMTopLevelType('dragenter');
+var TOP_DRAG_EXIT = unsafeCastStringToDOMTopLevelType('dragexit');
+var TOP_DRAG_LEAVE = unsafeCastStringToDOMTopLevelType('dragleave');
+var TOP_DRAG_OVER = unsafeCastStringToDOMTopLevelType('dragover');
+var TOP_DRAG_START = unsafeCastStringToDOMTopLevelType('dragstart');
+var TOP_DROP = unsafeCastStringToDOMTopLevelType('drop');
+var TOP_DURATION_CHANGE = unsafeCastStringToDOMTopLevelType('durationchange');
+var TOP_EMPTIED = unsafeCastStringToDOMTopLevelType('emptied');
+var TOP_ENCRYPTED = unsafeCastStringToDOMTopLevelType('encrypted');
+var TOP_ENDED = unsafeCastStringToDOMTopLevelType('ended');
+var TOP_ERROR = unsafeCastStringToDOMTopLevelType('error');
+var TOP_FOCUS = unsafeCastStringToDOMTopLevelType('focus');
+var TOP_GOT_POINTER_CAPTURE = unsafeCastStringToDOMTopLevelType('gotpointercapture');
+var TOP_INPUT = unsafeCastStringToDOMTopLevelType('input');
+var TOP_INVALID = unsafeCastStringToDOMTopLevelType('invalid');
+var TOP_KEY_DOWN = unsafeCastStringToDOMTopLevelType('keydown');
+var TOP_KEY_PRESS = unsafeCastStringToDOMTopLevelType('keypress');
+var TOP_KEY_UP = unsafeCastStringToDOMTopLevelType('keyup');
+var TOP_LOAD = unsafeCastStringToDOMTopLevelType('load');
+var TOP_LOAD_START = unsafeCastStringToDOMTopLevelType('loadstart');
+var TOP_LOADED_DATA = unsafeCastStringToDOMTopLevelType('loadeddata');
+var TOP_LOADED_METADATA = unsafeCastStringToDOMTopLevelType('loadedmetadata');
+var TOP_LOST_POINTER_CAPTURE = unsafeCastStringToDOMTopLevelType('lostpointercapture');
+var TOP_MOUSE_DOWN = unsafeCastStringToDOMTopLevelType('mousedown');
+var TOP_MOUSE_MOVE = unsafeCastStringToDOMTopLevelType('mousemove');
+var TOP_MOUSE_OUT = unsafeCastStringToDOMTopLevelType('mouseout');
+var TOP_MOUSE_OVER = unsafeCastStringToDOMTopLevelType('mouseover');
+var TOP_MOUSE_UP = unsafeCastStringToDOMTopLevelType('mouseup');
+var TOP_PASTE = unsafeCastStringToDOMTopLevelType('paste');
+var TOP_PAUSE = unsafeCastStringToDOMTopLevelType('pause');
+var TOP_PLAY = unsafeCastStringToDOMTopLevelType('play');
+var TOP_PLAYING = unsafeCastStringToDOMTopLevelType('playing');
+var TOP_POINTER_CANCEL = unsafeCastStringToDOMTopLevelType('pointercancel');
+var TOP_POINTER_DOWN = unsafeCastStringToDOMTopLevelType('pointerdown');
+
+
+var TOP_POINTER_MOVE = unsafeCastStringToDOMTopLevelType('pointermove');
+var TOP_POINTER_OUT = unsafeCastStringToDOMTopLevelType('pointerout');
+var TOP_POINTER_OVER = unsafeCastStringToDOMTopLevelType('pointerover');
+var TOP_POINTER_UP = unsafeCastStringToDOMTopLevelType('pointerup');
+var TOP_PROGRESS = unsafeCastStringToDOMTopLevelType('progress');
+var TOP_RATE_CHANGE = unsafeCastStringToDOMTopLevelType('ratechange');
+var TOP_RESET = unsafeCastStringToDOMTopLevelType('reset');
+var TOP_SCROLL = unsafeCastStringToDOMTopLevelType('scroll');
+var TOP_SEEKED = unsafeCastStringToDOMTopLevelType('seeked');
+var TOP_SEEKING = unsafeCastStringToDOMTopLevelType('seeking');
+var TOP_SELECTION_CHANGE = unsafeCastStringToDOMTopLevelType('selectionchange');
+var TOP_STALLED = unsafeCastStringToDOMTopLevelType('stalled');
+var TOP_SUBMIT = unsafeCastStringToDOMTopLevelType('submit');
+var TOP_SUSPEND = unsafeCastStringToDOMTopLevelType('suspend');
+var TOP_TEXT_INPUT = unsafeCastStringToDOMTopLevelType('textInput');
+var TOP_TIME_UPDATE = unsafeCastStringToDOMTopLevelType('timeupdate');
+var TOP_TOGGLE = unsafeCastStringToDOMTopLevelType('toggle');
+var TOP_TOUCH_CANCEL = unsafeCastStringToDOMTopLevelType('touchcancel');
+var TOP_TOUCH_END = unsafeCastStringToDOMTopLevelType('touchend');
+var TOP_TOUCH_MOVE = unsafeCastStringToDOMTopLevelType('touchmove');
+var TOP_TOUCH_START = unsafeCastStringToDOMTopLevelType('touchstart');
+var TOP_TRANSITION_END = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('transitionend'));
+var TOP_VOLUME_CHANGE = unsafeCastStringToDOMTopLevelType('volumechange');
+var TOP_WAITING = unsafeCastStringToDOMTopLevelType('waiting');
+var TOP_WHEEL = unsafeCastStringToDOMTopLevelType('wheel');
+
+// List of events that need to be individually attached to media elements.
+// Note that events in this list will *not* be listened to at the top level
+// unless they're explicitly whitelisted in `ReactBrowserEventEmitter.listenTo`.
+var mediaEventTypes = [TOP_ABORT, TOP_CAN_PLAY, TOP_CAN_PLAY_THROUGH, TOP_DURATION_CHANGE, TOP_EMPTIED, TOP_ENCRYPTED, TOP_ENDED, TOP_ERROR, TOP_LOADED_DATA, TOP_LOADED_METADATA, TOP_LOAD_START, TOP_PAUSE, TOP_PLAY, TOP_PLAYING, TOP_PROGRESS, TOP_RATE_CHANGE, TOP_SEEKED, TOP_SEEKING, TOP_STALLED, TOP_SUSPEND, TOP_TIME_UPDATE, TOP_VOLUME_CHANGE, TOP_WAITING];
+
+function getRawEventName(topLevelType) {
+ return unsafeCastDOMTopLevelTypeToString(topLevelType);
+}
+
+/**
+ * These variables store information about text content of a target node,
+ * allowing comparison of content before and after a given event.
+ *
+ * Identify the node where selection currently begins, then observe
+ * both its text content and its current position in the DOM. Since the
+ * browser may natively replace the target node during composition, we can
+ * use its position to find its replacement.
+ *
+ *
+ */
+
+var root = null;
+var startText = null;
+var fallbackText = null;
+
+function initialize(nativeEventTarget) {
+ root = nativeEventTarget;
+ startText = getText();
+ return true;
+}
+
+function reset() {
+ root = null;
+ startText = null;
+ fallbackText = null;
+}
+
+function getData() {
+ if (fallbackText) {
+ return fallbackText;
+ }
+
+ var start = void 0;
+ var startValue = startText;
+ var startLength = startValue.length;
+ var end = void 0;
+ var endValue = getText();
+ var endLength = endValue.length;
+
+ for (start = 0; start < startLength; start++) {
+ if (startValue[start] !== endValue[start]) {
+ break;
+ }
+ }
+
+ var minEnd = startLength - start;
+ for (end = 1; end <= minEnd; end++) {
+ if (startValue[startLength - end] !== endValue[endLength - end]) {
+ break;
+ }
+ }
+
+ var sliceTail = end > 1 ? 1 - end : undefined;
+ fallbackText = endValue.slice(start, sliceTail);
+ return fallbackText;
+}
+
+function getText() {
+ if ('value' in root) {
+ return root.value;
+ }
+ return root.textContent;
+}
+
+var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+var _assign = ReactInternals.assign;
+
+/* eslint valid-typeof: 0 */
+
+var EVENT_POOL_SIZE = 10;
+
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var EventInterface = {
+ type: null,
+ target: null,
+ // currentTarget is set when dispatching; no use in copying it here
+ currentTarget: function () {
+ return null;
+ },
+ eventPhase: null,
+ bubbles: null,
+ cancelable: null,
+ timeStamp: function (event) {
+ return event.timeStamp || Date.now();
+ },
+ defaultPrevented: null,
+ isTrusted: null
+};
+
+function functionThatReturnsTrue() {
+ return true;
+}
+
+function functionThatReturnsFalse() {
+ return false;
+}
+
+/**
+ * Synthetic events are dispatched by event plugins, typically in response to a
+ * top-level event delegation handler.
+ *
+ * These systems should generally use pooling to reduce the frequency of garbage
+ * collection. The system should check `isPersistent` to determine whether the
+ * event should be released into the pool after being dispatched. Users that
+ * need a persisted event should invoke `persist`.
+ *
+ * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
+ * normalizing browser quirks. Subclasses do not necessarily have to implement a
+ * DOM interface; custom application-specific events can also subclass this.
+ *
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {*} targetInst Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @param {DOMEventTarget} nativeEventTarget Target node.
+ */
+function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
+ this.dispatchConfig = dispatchConfig;
+ this._targetInst = targetInst;
+ this.nativeEvent = nativeEvent;
+
+ var Interface = this.constructor.Interface;
+ for (var propName in Interface) {
+ if (!Interface.hasOwnProperty(propName)) {
+ continue;
+ }
+ var normalize = Interface[propName];
+ if (normalize) {
+ this[propName] = normalize(nativeEvent);
+ } else {
+ if (propName === 'target') {
+ this.target = nativeEventTarget;
+ } else {
+ this[propName] = nativeEvent[propName];
+ }
+ }
+ }
+
+ var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
+ if (defaultPrevented) {
+ this.isDefaultPrevented = functionThatReturnsTrue;
+ } else {
+ this.isDefaultPrevented = functionThatReturnsFalse;
+ }
+ this.isPropagationStopped = functionThatReturnsFalse;
+ return this;
+}
+
+_assign(SyntheticEvent.prototype, {
+ preventDefault: function () {
+ this.defaultPrevented = true;
+ var event = this.nativeEvent;
+ if (!event) {
+ return;
+ }
+
+ if (event.preventDefault) {
+ event.preventDefault();
+ } else if (typeof event.returnValue !== 'unknown') {
+ event.returnValue = false;
+ }
+ this.isDefaultPrevented = functionThatReturnsTrue;
+ },
+
+ stopPropagation: function () {
+ var event = this.nativeEvent;
+ if (!event) {
+ return;
+ }
+
+ if (event.stopPropagation) {
+ event.stopPropagation();
+ } else if (typeof event.cancelBubble !== 'unknown') {
+ // The ChangeEventPlugin registers a "propertychange" event for
+ // IE. This event does not support bubbling or cancelling, and
+ // any references to cancelBubble throw "Member not found". A
+ // typeof check of "unknown" circumvents this issue (and is also
+ // IE specific).
+ event.cancelBubble = true;
+ }
+
+ this.isPropagationStopped = functionThatReturnsTrue;
+ },
+
+ /**
+ * We release all dispatched `SyntheticEvent`s after each event loop, adding
+ * them back into the pool. This allows a way to hold onto a reference that
+ * won't be added back into the pool.
+ */
+ persist: function () {
+ this.isPersistent = functionThatReturnsTrue;
+ },
+
+ /**
+ * Checks if this event should be released back into the pool.
+ *
+ * @return {boolean} True if this should not be released, false otherwise.
+ */
+ isPersistent: functionThatReturnsFalse,
+
+ /**
+ * `PooledClass` looks for `destructor` on each instance it releases.
+ */
+ destructor: function () {
+ var Interface = this.constructor.Interface;
+ for (var propName in Interface) {
+ {
+ this[propName] = null;
+ }
+ }
+ this.dispatchConfig = null;
+ this._targetInst = null;
+ this.nativeEvent = null;
+ this.isDefaultPrevented = functionThatReturnsFalse;
+ this.isPropagationStopped = functionThatReturnsFalse;
+ this._dispatchListeners = null;
+ this._dispatchInstances = null;
+
+ }
+});
+
+SyntheticEvent.Interface = EventInterface;
+
+/**
+ * Helper to reduce boilerplate when creating subclasses.
+ */
+SyntheticEvent.extend = function (Interface) {
+ var Super = this;
+
+ var E = function () {};
+ E.prototype = Super.prototype;
+ var prototype = new E();
+
+ function Class() {
+ return Super.apply(this, arguments);
+ }
+ _assign(prototype, Class.prototype);
+ Class.prototype = prototype;
+ Class.prototype.constructor = Class;
+
+ Class.Interface = _assign({}, Super.Interface, Interface);
+ Class.extend = Super.extend;
+ addEventPoolingTo(Class);
+
+ return Class;
+};
+
+addEventPoolingTo(SyntheticEvent);
+
+function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {
+ var EventConstructor = this;
+ if (EventConstructor.eventPool.length) {
+ var instance = EventConstructor.eventPool.pop();
+ EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst);
+ return instance;
+ }
+ return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst);
+}
+
+function releasePooledEvent(event) {
+ var EventConstructor = this;
+ !(event instanceof EventConstructor) ? reactProdInvariant('279') : void 0;
+ event.destructor();
+ if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
+ EventConstructor.eventPool.push(event);
+ }
+}
+
+function addEventPoolingTo(EventConstructor) {
+ EventConstructor.eventPool = [];
+ EventConstructor.getPooled = getPooledEvent;
+ EventConstructor.release = releasePooledEvent;
+}
+
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents
+ */
+var SyntheticCompositionEvent = SyntheticEvent.extend({
+ data: null
+});
+
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
+ * /#events-inputevents
+ */
+var SyntheticInputEvent = SyntheticEvent.extend({
+ data: null
+});
+
+var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
+var START_KEYCODE = 229;
+
+var canUseCompositionEvent = canUseDOM && 'CompositionEvent' in window;
+
+var documentMode = null;
+if (canUseDOM && 'documentMode' in document) {
+ documentMode = document.documentMode;
+}
+
+// Webkit offers a very useful `textInput` event that can be used to
+// directly represent `beforeInput`. The IE `textinput` event is not as
+// useful, so we don't use it.
+var canUseTextInputEvent = canUseDOM && 'TextEvent' in window && !documentMode;
+
+// In IE9+, we have access to composition events, but the data supplied
+// by the native compositionend event may be incorrect. Japanese ideographic
+// spaces, for instance (\u3000) are not recorded correctly.
+var useFallbackCompositionData = canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);
+
+var SPACEBAR_CODE = 32;
+var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
+
+// Events and their corresponding property names.
+var eventTypes = {
+ beforeInput: {
+ phasedRegistrationNames: {
+ bubbled: 'onBeforeInput',
+ captured: 'onBeforeInputCapture'
+ },
+ dependencies: [TOP_COMPOSITION_END, TOP_KEY_PRESS, TOP_TEXT_INPUT, TOP_PASTE]
+ },
+ compositionEnd: {
+ phasedRegistrationNames: {
+ bubbled: 'onCompositionEnd',
+ captured: 'onCompositionEndCapture'
+ },
+ dependencies: [TOP_BLUR, TOP_COMPOSITION_END, TOP_KEY_DOWN, TOP_KEY_PRESS, TOP_KEY_UP, TOP_MOUSE_DOWN]
+ },
+ compositionStart: {
+ phasedRegistrationNames: {
+ bubbled: 'onCompositionStart',
+ captured: 'onCompositionStartCapture'
+ },
+ dependencies: [TOP_BLUR, TOP_COMPOSITION_START, TOP_KEY_DOWN, TOP_KEY_PRESS, TOP_KEY_UP, TOP_MOUSE_DOWN]
+ },
+ compositionUpdate: {
+ phasedRegistrationNames: {
+ bubbled: 'onCompositionUpdate',
+ captured: 'onCompositionUpdateCapture'
+ },
+ dependencies: [TOP_BLUR, TOP_COMPOSITION_UPDATE, TOP_KEY_DOWN, TOP_KEY_PRESS, TOP_KEY_UP, TOP_MOUSE_DOWN]
+ }
+};
+
+// Track whether we've ever handled a keypress on the space key.
+var hasSpaceKeypress = false;
+
+/**
+ * Return whether a native keypress event is assumed to be a command.
+ * This is required because Firefox fires `keypress` events for key commands
+ * (cut, copy, select-all, etc.) even though no character is inserted.
+ */
+function isKeypressCommand(nativeEvent) {
+ return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
+ // ctrlKey && altKey is equivalent to AltGr, and is not a command.
+ !(nativeEvent.ctrlKey && nativeEvent.altKey);
+}
+
+/**
+ * Translate native top level events into event types.
+ *
+ * @param {string} topLevelType
+ * @return {object}
+ */
+function getCompositionEventType(topLevelType) {
+ switch (topLevelType) {
+ case TOP_COMPOSITION_START:
+ return eventTypes.compositionStart;
+ case TOP_COMPOSITION_END:
+ return eventTypes.compositionEnd;
+ case TOP_COMPOSITION_UPDATE:
+ return eventTypes.compositionUpdate;
+ }
+}
+
+/**
+ * Does our fallback best-guess model think this event signifies that
+ * composition has begun?
+ *
+ * @param {string} topLevelType
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isFallbackCompositionStart(topLevelType, nativeEvent) {
+ return topLevelType === TOP_KEY_DOWN && nativeEvent.keyCode === START_KEYCODE;
+}
+
+/**
+ * Does our fallback mode think that this event is the end of composition?
+ *
+ * @param {string} topLevelType
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isFallbackCompositionEnd(topLevelType, nativeEvent) {
+ switch (topLevelType) {
+ case TOP_KEY_UP:
+ // Command keys insert or clear IME input.
+ return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
+ case TOP_KEY_DOWN:
+ // Expect IME keyCode on each keydown. If we get any other
+ // code we must have exited earlier.
+ return nativeEvent.keyCode !== START_KEYCODE;
+ case TOP_KEY_PRESS:
+ case TOP_MOUSE_DOWN:
+ case TOP_BLUR:
+ // Events are not possible without cancelling IME.
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * Google Input Tools provides composition data via a CustomEvent,
+ * with the `data` property populated in the `detail` object. If this
+ * is available on the event object, use it. If not, this is a plain
+ * composition event and we have nothing special to extract.
+ *
+ * @param {object} nativeEvent
+ * @return {?string}
+ */
+function getDataFromCustomEvent(nativeEvent) {
+ var detail = nativeEvent.detail;
+ if (typeof detail === 'object' && 'data' in detail) {
+ return detail.data;
+ }
+ return null;
+}
+
+/**
+ * Check if a composition event was triggered by Korean IME.
+ * Our fallback mode does not work well with IE's Korean IME,
+ * so just use native composition events when Korean IME is used.
+ * Although CompositionEvent.locale property is deprecated,
+ * it is available in IE, where our fallback mode is enabled.
+ *
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isUsingKoreanIME(nativeEvent) {
+ return nativeEvent.locale === 'ko';
+}
+
+// Track the current IME composition status, if any.
+var isComposing = false;
+
+/**
+ * @return {?object} A SyntheticCompositionEvent.
+ */
+function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var eventType = void 0;
+ var fallbackData = void 0;
+
+ if (canUseCompositionEvent) {
+ eventType = getCompositionEventType(topLevelType);
+ } else if (!isComposing) {
+ if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
+ eventType = eventTypes.compositionStart;
+ }
+ } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
+ eventType = eventTypes.compositionEnd;
+ }
+
+ if (!eventType) {
+ return null;
+ }
+
+ if (useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)) {
+ // The current composition is stored statically and must not be
+ // overwritten while composition continues.
+ if (!isComposing && eventType === eventTypes.compositionStart) {
+ isComposing = initialize(nativeEventTarget);
+ } else if (eventType === eventTypes.compositionEnd) {
+ if (isComposing) {
+ fallbackData = getData();
+ }
+ }
+ }
+
+ var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);
+
+ if (fallbackData) {
+ // Inject data generated from fallback path into the synthetic event.
+ // This matches the property of native CompositionEventInterface.
+ event.data = fallbackData;
+ } else {
+ var customData = getDataFromCustomEvent(nativeEvent);
+ if (customData !== null) {
+ event.data = customData;
+ }
+ }
+
+ accumulateTwoPhaseDispatches(event);
+ return event;
+}
+
+/**
+ * @param {TopLevelType} topLevelType Number from `TopLevelType`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?string} The string corresponding to this `beforeInput` event.
+ */
+function getNativeBeforeInputChars(topLevelType, nativeEvent) {
+ switch (topLevelType) {
+ case TOP_COMPOSITION_END:
+ return getDataFromCustomEvent(nativeEvent);
+ case TOP_KEY_PRESS:
+ /**
+ * If native `textInput` events are available, our goal is to make
+ * use of them. However, there is a special case: the spacebar key.
+ * In Webkit, preventing default on a spacebar `textInput` event
+ * cancels character insertion, but it *also* causes the browser
+ * to fall back to its default spacebar behavior of scrolling the
+ * page.
+ *
+ * Tracking at:
+ * https://code.google.com/p/chromium/issues/detail?id=355103
+ *
+ * To avoid this issue, use the keypress event as if no `textInput`
+ * event is available.
+ */
+ var which = nativeEvent.which;
+ if (which !== SPACEBAR_CODE) {
+ return null;
+ }
+
+ hasSpaceKeypress = true;
+ return SPACEBAR_CHAR;
+
+ case TOP_TEXT_INPUT:
+ // Record the characters to be added to the DOM.
+ var chars = nativeEvent.data;
+
+ // If it's a spacebar character, assume that we have already handled
+ // it at the keypress level and bail immediately. Android Chrome
+ // doesn't give us keycodes, so we need to ignore it.
+ if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
+ return null;
+ }
+
+ return chars;
+
+ default:
+ // For other native event types, do nothing.
+ return null;
+ }
+}
+
+/**
+ * For browsers that do not provide the `textInput` event, extract the
+ * appropriate string to use for SyntheticInputEvent.
+ *
+ * @param {number} topLevelType Number from `TopLevelEventTypes`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?string} The fallback string for this `beforeInput` event.
+ */
+function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
+ // If we are currently composing (IME) and using a fallback to do so,
+ // try to extract the composed characters from the fallback object.
+ // If composition event is available, we extract a string only at
+ // compositionevent, otherwise extract it at fallback events.
+ if (isComposing) {
+ if (topLevelType === TOP_COMPOSITION_END || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) {
+ var chars = getData();
+ reset();
+ isComposing = false;
+ return chars;
+ }
+ return null;
+ }
+
+ switch (topLevelType) {
+ case TOP_PASTE:
+ // If a paste event occurs after a keypress, throw out the input
+ // chars. Paste events should not lead to BeforeInput events.
+ return null;
+ case TOP_KEY_PRESS:
+ /**
+ * As of v27, Firefox may fire keypress events even when no character
+ * will be inserted. A few possibilities:
+ *
+ * - `which` is `0`. Arrow keys, Esc key, etc.
+ *
+ * - `which` is the pressed key code, but no char is available.
+ * Ex: 'AltGr + d` in Polish. There is no modified character for
+ * this key combination and no character is inserted into the
+ * document, but FF fires the keypress for char code `100` anyway.
+ * No `input` event will occur.
+ *
+ * - `which` is the pressed key code, but a command combination is
+ * being used. Ex: `Cmd+C`. No character is inserted, and no
+ * `input` event will occur.
+ */
+ if (!isKeypressCommand(nativeEvent)) {
+ // IE fires the `keypress` event when a user types an emoji via
+ // Touch keyboard of Windows. In such a case, the `char` property
+ // holds an emoji character like `\uD83D\uDE0A`. Because its length
+ // is 2, the property `which` does not represent an emoji correctly.
+ // In such a case, we directly return the `char` property instead of
+ // using `which`.
+ if (nativeEvent.char && nativeEvent.char.length > 1) {
+ return nativeEvent.char;
+ } else if (nativeEvent.which) {
+ return String.fromCharCode(nativeEvent.which);
+ }
+ }
+ return null;
+ case TOP_COMPOSITION_END:
+ return useFallbackCompositionData && !isUsingKoreanIME(nativeEvent) ? null : nativeEvent.data;
+ default:
+ return null;
+ }
+}
+
+/**
+ * Extract a SyntheticInputEvent for `beforeInput`, based on either native
+ * `textInput` or fallback behavior.
+ *
+ * @return {?object} A SyntheticInputEvent.
+ */
+function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var chars = void 0;
+
+ if (canUseTextInputEvent) {
+ chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
+ } else {
+ chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
+ }
+
+ // If no characters are being inserted, no BeforeInput event should
+ // be fired.
+ if (!chars) {
+ return null;
+ }
+
+ var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);
+
+ event.data = chars;
+ accumulateTwoPhaseDispatches(event);
+ return event;
+}
+
+/**
+ * Create an `onBeforeInput` event to match
+ * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
+ *
+ * This event plugin is based on the native `textInput` event
+ * available in Chrome, Safari, Opera, and IE. This event fires after
+ * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
+ *
+ * `beforeInput` is spec'd but not implemented in any browsers, and
+ * the `input` event does not provide any useful information about what has
+ * actually been added, contrary to the spec. Thus, `textInput` is the best
+ * available event to identify the characters that have actually been inserted
+ * into the target node.
+ *
+ * This plugin is also responsible for emitting `composition` events, thus
+ * allowing us to share composition fallback code for both `beforeInput` and
+ * `composition` event types.
+ */
+var BeforeInputEventPlugin = {
+ eventTypes: eventTypes,
+
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var composition = extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget);
+
+ var beforeInput = extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget);
+
+ if (composition === null) {
+ return beforeInput;
+ }
+
+ if (beforeInput === null) {
+ return composition;
+ }
+
+ return [composition, beforeInput];
+ }
+};
+
+// Use to restore controlled state after a change event has fired.
+
+var restoreImpl = null;
+var restoreTarget = null;
+var restoreQueue = null;
+
+function restoreStateOfTarget(target) {
+ // We perform this translation at the end of the event loop so that we
+ // always receive the correct fiber here
+ var internalInstance = getInstanceFromNode(target);
+ if (!internalInstance) {
+ // Unmounted
+ return;
+ }
+ !(typeof restoreImpl === 'function') ? reactProdInvariant('280') : void 0;
+ var props = getFiberCurrentPropsFromNode(internalInstance.stateNode);
+ restoreImpl(internalInstance.stateNode, internalInstance.type, props);
+}
+
+function setRestoreImplementation(impl) {
+ restoreImpl = impl;
+}
+
+function enqueueStateRestore(target) {
+ if (restoreTarget) {
+ if (restoreQueue) {
+ restoreQueue.push(target);
+ } else {
+ restoreQueue = [target];
+ }
+ } else {
+ restoreTarget = target;
+ }
+}
+
+function needsStateRestore() {
+ return restoreTarget !== null || restoreQueue !== null;
+}
+
+function restoreStateIfNeeded() {
+ if (!restoreTarget) {
+ return;
+ }
+ var target = restoreTarget;
+ var queuedTargets = restoreQueue;
+ restoreTarget = null;
+ restoreQueue = null;
+
+ restoreStateOfTarget(target);
+ if (queuedTargets) {
+ for (var i = 0; i < queuedTargets.length; i++) {
+ restoreStateOfTarget(queuedTargets[i]);
+ }
+ }
+}
+
+// Used as a way to call batchedUpdates when we don't have a reference to
+// the renderer. Such as when we're dispatching events or if third party
+// libraries need to call batchedUpdates. Eventually, this API will go away when
+// everything is batched by default. We'll then have a similar API to opt-out of
+// scheduled work and instead do synchronous work.
+
+// Defaults
+var _batchedUpdatesImpl = function (fn, bookkeeping) {
+ return fn(bookkeeping);
+};
+var _interactiveUpdatesImpl = function (fn, a, b) {
+ return fn(a, b);
+};
+var _flushInteractiveUpdatesImpl = function () {};
+
+var isBatching = false;
+function batchedUpdates(fn, bookkeeping) {
+ if (isBatching) {
+ // If we are currently inside another batch, we need to wait until it
+ // fully completes before restoring state.
+ return fn(bookkeeping);
+ }
+ isBatching = true;
+ try {
+ return _batchedUpdatesImpl(fn, bookkeeping);
+ } finally {
+ // Here we wait until all updates have propagated, which is important
+ // when using controlled components within layers:
+ // https://github.com/facebook/react/issues/1698
+ // Then we restore state of any controlled component.
+ isBatching = false;
+ var controlledComponentsHavePendingUpdates = needsStateRestore();
+ if (controlledComponentsHavePendingUpdates) {
+ // If a controlled event was fired, we may need to restore the state of
+ // the DOM node back to the controlled value. This is necessary when React
+ // bails out of the update without touching the DOM.
+ _flushInteractiveUpdatesImpl();
+ restoreStateIfNeeded();
+ }
+ }
+}
+
+function interactiveUpdates(fn, a, b) {
+ return _interactiveUpdatesImpl(fn, a, b);
+}
+
+
+
+function setBatchingImplementation(batchedUpdatesImpl, interactiveUpdatesImpl, flushInteractiveUpdatesImpl) {
+ _batchedUpdatesImpl = batchedUpdatesImpl;
+ _interactiveUpdatesImpl = interactiveUpdatesImpl;
+ _flushInteractiveUpdatesImpl = flushInteractiveUpdatesImpl;
+}
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
+ */
+var supportedInputTypes = {
+ color: true,
+ date: true,
+ datetime: true,
+ 'datetime-local': true,
+ email: true,
+ month: true,
+ number: true,
+ password: true,
+ range: true,
+ search: true,
+ tel: true,
+ text: true,
+ time: true,
+ url: true,
+ week: true
+};
+
+function isTextInputElement(elem) {
+ var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
+
+ if (nodeName === 'input') {
+ return !!supportedInputTypes[elem.type];
+ }
+
+ if (nodeName === 'textarea') {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * HTML nodeType values that represent the type of the node
+ */
+
+var ELEMENT_NODE = 1;
+var TEXT_NODE = 3;
+var COMMENT_NODE = 8;
+var DOCUMENT_NODE = 9;
+var DOCUMENT_FRAGMENT_NODE = 11;
+
+/**
+ * Gets the target node from a native browser event by accounting for
+ * inconsistencies in browser DOM APIs.
+ *
+ * @param {object} nativeEvent Native browser event.
+ * @return {DOMEventTarget} Target node.
+ */
+function getEventTarget(nativeEvent) {
+ // Fallback to nativeEvent.srcElement for IE9
+ // https://github.com/facebook/react/issues/12506
+ var target = nativeEvent.target || nativeEvent.srcElement || window;
+
+ // Normalize SVG <use> element events #4963
+ if (target.correspondingUseElement) {
+ target = target.correspondingUseElement;
+ }
+
+ // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
+ // @see http://www.quirksmode.org/js/events_properties.html
+ return target.nodeType === TEXT_NODE ? target.parentNode : target;
+}
+
+/**
+ * Checks if an event is supported in the current execution environment.
+ *
+ * NOTE: This will not work correctly for non-generic events such as `change`,
+ * `reset`, `load`, `error`, and `select`.
+ *
+ * Borrows from Modernizr.
+ *
+ * @param {string} eventNameSuffix Event name, e.g. "click".
+ * @return {boolean} True if the event is supported.
+ * @internal
+ * @license Modernizr 3.0.0pre (Custom Build) | MIT
+ */
+function isEventSupported(eventNameSuffix) {
+ if (!canUseDOM) {
+ return false;
+ }
+
+ var eventName = 'on' + eventNameSuffix;
+ var isSupported = eventName in document;
+
+ if (!isSupported) {
+ var element = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ element.setAttribute(eventName, 'return;');
+ isSupported = typeof element[eventName] === 'function';
+ }
+
+ return isSupported;
+}
+
+function isCheckable(elem) {
+ var type = elem.type;
+ var nodeName = elem.nodeName;
+ return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
+}
+
+function getTracker(node) {
+ return node._valueTracker;
+}
+
+function detachTracker(node) {
+ node._valueTracker = null;
+}
+
+function getValueFromNode(node) {
+ var value = '';
+ if (!node) {
+ return value;
+ }
+
+ if (isCheckable(node)) {
+ value = node.checked ? 'true' : 'false';
+ } else {
+ value = node.value;
+ }
+
+ return value;
+}
+
+function trackValueOnNode(node) {
+ var valueField = isCheckable(node) ? 'checked' : 'value';
+ var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);
+
+ var currentValue = '' + node[valueField];
+
+ // if someone has already defined a value or Safari, then bail
+ // and don't track value will cause over reporting of changes,
+ // but it's better then a hard failure
+ // (needed for certain tests that spyOn input values and Safari)
+ if (node.hasOwnProperty(valueField) || typeof descriptor === 'undefined' || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
+ return;
+ }
+ var get = descriptor.get,
+ set = descriptor.set;
+
+ Object.defineProperty(node, valueField, {
+ configurable: true,
+ get: function () {
+ return get.call(this);
+ },
+ set: function (value) {
+ currentValue = '' + value;
+ set.call(this, value);
+ }
+ });
+ // We could've passed this the first time
+ // but it triggers a bug in IE11 and Edge 14/15.
+ // Calling defineProperty() again should be equivalent.
+ // https://github.com/facebook/react/issues/11768
+ Object.defineProperty(node, valueField, {
+ enumerable: descriptor.enumerable
+ });
+
+ var tracker = {
+ getValue: function () {
+ return currentValue;
+ },
+ setValue: function (value) {
+ currentValue = '' + value;
+ },
+ stopTracking: function () {
+ detachTracker(node);
+ delete node[valueField];
+ }
+ };
+ return tracker;
+}
+
+function track(node) {
+ if (getTracker(node)) {
+ return;
+ }
+
+ // TODO: Once it's just Fiber we can move this to node._wrapperState
+ node._valueTracker = trackValueOnNode(node);
+}
+
+function updateValueIfChanged(node) {
+ if (!node) {
+ return false;
+ }
+
+ var tracker = getTracker(node);
+ // if there is no tracker at this point it's unlikely
+ // that trying again will succeed
+ if (!tracker) {
+ return true;
+ }
+
+ var lastValue = tracker.getValue();
+ var nextValue = getValueFromNode(node);
+ if (nextValue !== lastValue) {
+ tracker.setValue(nextValue);
+ return true;
+ }
+ return false;
+}
+
+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
+ };
+}
+
+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;
+};
+
+// 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 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;
+}
+
+// A reserved attribute.
+// It is handled by React separately and shouldn't be written to the DOM.
+var RESERVED = 0;
+
+// A simple string attribute.
+// Attributes that aren't in the whitelist are presumed to have this type.
+var STRING = 1;
+
+// A string attribute that accepts booleans in React. In HTML, these are called
+// "enumerated" attributes with "true" and "false" as possible values.
+// When true, it should be set to a "true" string.
+// When false, it should be set to a "false" string.
+var BOOLEANISH_STRING = 2;
+
+// A real boolean attribute.
+// When true, it should be present (set either to an empty string or its name).
+// When false, it should be omitted.
+var BOOLEAN = 3;
+
+// An attribute that can be used as a flag as well as with a value.
+// When true, it should be present (set either to an empty string or its name).
+// When false, it should be omitted.
+// For any other value, should be present with that value.
+var OVERLOADED_BOOLEAN = 4;
+
+// An attribute that must be numeric or parse as a numeric.
+// When falsy, it should be removed.
+var NUMERIC = 5;
+
+// An attribute that must be positive numeric or parse as a positive numeric.
+// When falsy, it should be removed.
+var POSITIVE_NUMERIC = 6;
+
+/* eslint-disable max-len */
+var ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD';
+/* eslint-enable max-len */
+var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
+
+
+var ROOT_ATTRIBUTE_NAME = 'data-reactroot';
+var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$');
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var illegalAttributeNameCache = {};
+var validatedAttributeNameCache = {};
+
+function isAttributeNameSafe(attributeName) {
+ if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) {
+ return true;
+ }
+ if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) {
+ return false;
+ }
+ if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
+ validatedAttributeNameCache[attributeName] = true;
+ return true;
+ }
+ illegalAttributeNameCache[attributeName] = true;
+ return false;
+}
+
+function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) {
+ if (propertyInfo !== null) {
+ return propertyInfo.type === RESERVED;
+ }
+ if (isCustomComponentTag) {
+ return false;
+ }
+ if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) {
+ return true;
+ }
+ return false;
+}
+
+function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) {
+ if (propertyInfo !== null && propertyInfo.type === RESERVED) {
+ return false;
+ }
+ switch (typeof value) {
+ case 'function':
+ // $FlowIssue symbol is perfectly valid here
+ case 'symbol':
+ // eslint-disable-line
+ return true;
+ case 'boolean':
+ {
+ if (isCustomComponentTag) {
+ return false;
+ }
+ if (propertyInfo !== null) {
+ return !propertyInfo.acceptsBooleans;
+ } else {
+ var prefix = name.toLowerCase().slice(0, 5);
+ return prefix !== 'data-' && prefix !== 'aria-';
+ }
+ }
+ default:
+ return false;
+ }
+}
+
+function shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag) {
+ if (value === null || typeof value === 'undefined') {
+ return true;
+ }
+ if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag)) {
+ return true;
+ }
+ if (isCustomComponentTag) {
+ return false;
+ }
+ if (propertyInfo !== null) {
+ switch (propertyInfo.type) {
+ case BOOLEAN:
+ return !value;
+ case OVERLOADED_BOOLEAN:
+ return value === false;
+ case NUMERIC:
+ return isNaN(value);
+ case POSITIVE_NUMERIC:
+ return isNaN(value) || value < 1;
+ }
+ }
+ return false;
+}
+
+function getPropertyInfo(name) {
+ return properties.hasOwnProperty(name) ? properties[name] : null;
+}
+
+function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace) {
+ this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN;
+ this.attributeName = attributeName;
+ this.attributeNamespace = attributeNamespace;
+ this.mustUseProperty = mustUseProperty;
+ this.propertyName = name;
+ this.type = type;
+}
+
+// When adding attributes to this list, be sure to also add them to
+// the `possibleStandardNames` module to ensure casing and incorrect
+// name warnings.
+var properties = {};
+
+// These props are reserved by React. They shouldn't be written to the DOM.
+['children', 'dangerouslySetInnerHTML',
+// TODO: This prevents the assignment of defaultValue to regular
+// elements (not just inputs). Now that ReactDOMInput assigns to the
+// defaultValue property -- do we need this?
+'defaultValue', 'defaultChecked', 'innerHTML', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'style'].forEach(function (name) {
+ properties[name] = new PropertyInfoRecord(name, RESERVED, false, // mustUseProperty
+ name, // attributeName
+ null);
+} // attributeNamespace
+);
+
+// A few React string attributes have a different name.
+// This is a mapping from React prop names to the attribute names.
+[['acceptCharset', 'accept-charset'], ['className', 'class'], ['htmlFor', 'for'], ['httpEquiv', 'http-equiv']].forEach(function (_ref) {
+ var name = _ref[0],
+ attributeName = _ref[1];
+
+ properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
+ attributeName, // attributeName
+ null);
+} // attributeNamespace
+);
+
+// These are "enumerated" HTML attributes that accept "true" and "false".
+// In React, we let users pass `true` and `false` even though technically
+// these aren't boolean attributes (they are coerced to strings).
+['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (name) {
+ properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty
+ name.toLowerCase(), // attributeName
+ null);
+} // attributeNamespace
+);
+
+// These are "enumerated" SVG attributes that accept "true" and "false".
+// In React, we let users pass `true` and `false` even though technically
+// these aren't boolean attributes (they are coerced to strings).
+// Since these are SVG attributes, their attribute names are case-sensitive.
+['autoReverse', 'externalResourcesRequired', 'focusable', 'preserveAlpha'].forEach(function (name) {
+ properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty
+ name, // attributeName
+ null);
+} // attributeNamespace
+);
+
+// These are HTML boolean attributes.
+['allowFullScreen', 'async',
+// Note: there is a special case that prevents it from being written to the DOM
+// on the client side because the browsers are inconsistent. Instead we call focus().
+'autoFocus', 'autoPlay', 'controls', 'default', 'defer', 'disabled', 'formNoValidate', 'hidden', 'loop', 'noModule', 'noValidate', 'open', 'playsInline', 'readOnly', 'required', 'reversed', 'scoped', 'seamless',
+// Microdata
+'itemScope'].forEach(function (name) {
+ properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, // mustUseProperty
+ name.toLowerCase(), // attributeName
+ null);
+} // attributeNamespace
+);
+
+// These are the few React props that we set as DOM properties
+// rather than attributes. These are all booleans.
+['checked',
+// Note: `option.selected` is not updated if `select.multiple` is
+// disabled with `removeAttribute`. We have special logic for handling this.
+'multiple', 'muted', 'selected'].forEach(function (name) {
+ properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, // mustUseProperty
+ name, // attributeName
+ null);
+} // attributeNamespace
+);
+
+// These are HTML attributes that are "overloaded booleans": they behave like
+// booleans, but can also accept a string value.
+['capture', 'download'].forEach(function (name) {
+ properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, // mustUseProperty
+ name, // attributeName
+ null);
+} // attributeNamespace
+);
+
+// These are HTML attributes that must be positive numbers.
+['cols', 'rows', 'size', 'span'].forEach(function (name) {
+ properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, // mustUseProperty
+ name, // attributeName
+ null);
+} // attributeNamespace
+);
+
+// These are HTML attributes that must be numbers.
+['rowSpan', 'start'].forEach(function (name) {
+ properties[name] = new PropertyInfoRecord(name, NUMERIC, false, // mustUseProperty
+ name.toLowerCase(), // attributeName
+ null);
+} // attributeNamespace
+);
+
+var CAMELIZE = /[\-\:]([a-z])/g;
+var capitalize = function (token) {
+ return token[1].toUpperCase();
+};
+
+// This is a list of all SVG attributes that need special casing, namespacing,
+// or boolean value assignment. Regular attributes that just accept strings
+// and have the same names are omitted, just like in the HTML whitelist.
+// Some of these attributes can be hard to find. This list was created by
+// scrapping the MDN documentation.
+['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'xmlns:xlink', 'x-height'].forEach(function (attributeName) {
+ var name = attributeName.replace(CAMELIZE, capitalize);
+ properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
+ attributeName, null);
+} // attributeNamespace
+);
+
+// String SVG attributes with the xlink namespace.
+['xlink:actuate', 'xlink:arcrole', 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type'].forEach(function (attributeName) {
+ var name = attributeName.replace(CAMELIZE, capitalize);
+ properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
+ attributeName, 'http://www.w3.org/1999/xlink');
+});
+
+// String SVG attributes with the xml namespace.
+['xml:base', 'xml:lang', 'xml:space'].forEach(function (attributeName) {
+ var name = attributeName.replace(CAMELIZE, capitalize);
+ properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
+ attributeName, 'http://www.w3.org/XML/1998/namespace');
+});
+
+// These attribute exists both in HTML and SVG.
+// The attribute name is case-sensitive in SVG so we can't just use
+// the React name like we do for attributes that exist only in HTML.
+['tabIndex', 'crossOrigin'].forEach(function (attributeName) {
+ properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty
+ attributeName.toLowerCase(), // attributeName
+ null);
+} // attributeNamespace
+);
+
+/**
+ * Get the value for a property on a node. Only used in DEV for SSR validation.
+ * The "expected" argument is used as a hint of what the expected value is.
+ * Some properties have multiple equivalent values.
+ */
+
+
+/**
+ * Get the value for a attribute on a node. Only used in DEV for SSR validation.
+ * The third argument is used as a hint of what the expected value is. Some
+ * attributes have multiple equivalent values.
+ */
+
+
+/**
+ * Sets the value for a property on a node.
+ *
+ * @param {DOMElement} node
+ * @param {string} name
+ * @param {*} value
+ */
+function setValueForProperty(node, name, value, isCustomComponentTag) {
+ var propertyInfo = getPropertyInfo(name);
+ if (shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag)) {
+ return;
+ }
+ if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
+ value = null;
+ }
+ // If the prop isn't in the special list, treat it as a simple attribute.
+ if (isCustomComponentTag || propertyInfo === null) {
+ if (isAttributeNameSafe(name)) {
+ var _attributeName = name;
+ if (value === null) {
+ node.removeAttribute(_attributeName);
+ } else {
+ node.setAttribute(_attributeName, '' + value);
+ }
+ }
+ return;
+ }
+ var mustUseProperty = propertyInfo.mustUseProperty;
+
+ if (mustUseProperty) {
+ var propertyName = propertyInfo.propertyName;
+
+ if (value === null) {
+ var type = propertyInfo.type;
+
+ node[propertyName] = type === BOOLEAN ? false : '';
+ } else {
+ // Contrary to `setAttribute`, object properties are properly
+ // `toString`ed by IE8/9.
+ node[propertyName] = value;
+ }
+ return;
+ }
+ // The rest are treated as attributes with special cases.
+ var attributeName = propertyInfo.attributeName,
+ attributeNamespace = propertyInfo.attributeNamespace;
+
+ if (value === null) {
+ node.removeAttribute(attributeName);
+ } else {
+ var _type = propertyInfo.type;
+
+ var attributeValue = void 0;
+ if (_type === BOOLEAN || _type === OVERLOADED_BOOLEAN && value === true) {
+ attributeValue = '';
+ } else {
+ // `setAttribute` with objects becomes only `[object]` in IE8/9,
+ // ('' + value) makes it output the correct toString()-value.
+ attributeValue = '' + value;
+ }
+ if (attributeNamespace) {
+ node.setAttributeNS(attributeNamespace, attributeName, attributeValue);
+ } else {
+ node.setAttribute(attributeName, attributeValue);
+ }
+ }
+}
+
+// Flow does not allow string concatenation of most non-string types. To work
+// around this limitation, we use an opaque type that can only be obtained by
+// passing the value through getToStringValue first.
+function toString(value) {
+ return '' + value;
+}
+
+function getToStringValue(value) {
+ switch (typeof value) {
+ case 'boolean':
+ case 'number':
+ case 'object':
+ case 'string':
+ case 'undefined':
+ return value;
+ default:
+ // function, symbol are assigned as empty strings
+ return '';
+ }
+}
+
+/**
+ * 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 enableUserTimingAPI = false;
+
+// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
+
+
+// In some cases, StrictMode should also double-render lifecycles.
+// This can be confusing for tests though,
+// And it can be bad for performance in production.
+// This feature flag can be used to control the behavior:
+
+
+// To preserve the "Pause on caught exceptions" behavior of the debugger, we
+// replay the begin phase of a failed component inside invokeGuardedCallback.
+
+
+// Warn about deprecated, async-unsafe lifecycles; relates to RFC #6:
+
+
+// Gather advanced timing metrics for Profiler subtrees.
+var enableProfilerTimer = false;
+
+// Trace which interactions trigger each commit.
+var enableSchedulerTracing = false;
+
+// Only used in www builds.
+var enableSuspenseServerRenderer = false; // TODO: false? Here it might just be false.
+
+// Only used in www builds.
+
+
+// Only used in www builds.
+
+
+// React Fire: prevent the value and checked attributes from syncing
+// with their related DOM properties
+var disableInputAttributeSyncing = false;
+
+// These APIs will no longer be "unstable" in the upcoming 16.7 release,
+// Control this behavior with a flag to support 16.6 minor releases in the meanwhile.
+var enableStableConcurrentModeAPIs = false;
+
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+function isControlled(props) {
+ var usesChecked = props.type === 'checkbox' || props.type === 'radio';
+ return usesChecked ? props.checked != null : props.value != null;
+}
+
+/**
+ * Implements an <input> host component that allows setting these optional
+ * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
+ *
+ * If `checked` or `value` are not supplied (or null/undefined), user actions
+ * that affect the checked state or value will trigger updates to the element.
+ *
+ * If they are supplied (and not null/undefined), the rendered element will not
+ * trigger updates to the element. Instead, the props must change in order for
+ * the rendered element to be updated.
+ *
+ * The rendered element will be initialized as unchecked (or `defaultChecked`)
+ * with an empty value (or `defaultValue`).
+ *
+ * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
+ */
+
+function getHostProps(element, props) {
+ var node = element;
+ var checked = props.checked;
+
+ var hostProps = _assign({}, props, {
+ defaultChecked: undefined,
+ defaultValue: undefined,
+ value: undefined,
+ checked: checked != null ? checked : node._wrapperState.initialChecked
+ });
+
+ return hostProps;
+}
+
+function initWrapperState(element, props) {
+ var node = element;
+ var defaultValue = props.defaultValue == null ? '' : props.defaultValue;
+
+ node._wrapperState = {
+ initialChecked: props.checked != null ? props.checked : props.defaultChecked,
+ initialValue: getToStringValue(props.value != null ? props.value : defaultValue),
+ controlled: isControlled(props)
+ };
+}
+
+function updateChecked(element, props) {
+ var node = element;
+ var checked = props.checked;
+ if (checked != null) {
+ setValueForProperty(node, 'checked', checked, false);
+ }
+}
+
+function updateWrapper(element, props) {
+ var node = element;
+ updateChecked(element, props);
+
+ var value = getToStringValue(props.value);
+ var type = props.type;
+
+ if (value != null) {
+ if (type === 'number') {
+ if (value === 0 && node.value === '' ||
+ // We explicitly want to coerce to number here if possible.
+ // eslint-disable-next-line
+ node.value != value) {
+ node.value = toString(value);
+ }
+ } else if (node.value !== toString(value)) {
+ node.value = toString(value);
+ }
+ } else if (type === 'submit' || type === 'reset') {
+ // Submit/reset inputs need the attribute removed completely to avoid
+ // blank-text buttons.
+ node.removeAttribute('value');
+ return;
+ }
+
+ if (disableInputAttributeSyncing) {
+ // When not syncing the value attribute, React only assigns a new value
+ // whenever the defaultValue React prop has changed. When not present,
+ // React does nothing
+ if (props.hasOwnProperty('defaultValue')) {
+ setDefaultValue(node, props.type, getToStringValue(props.defaultValue));
+ }
+ } else {
+ // When syncing the value attribute, the value comes from a cascade of
+ // properties:
+ // 1. The value React property
+ // 2. The defaultValue React property
+ // 3. Otherwise there should be no change
+ if (props.hasOwnProperty('value')) {
+ setDefaultValue(node, props.type, value);
+ } else if (props.hasOwnProperty('defaultValue')) {
+ setDefaultValue(node, props.type, getToStringValue(props.defaultValue));
+ }
+ }
+
+ if (disableInputAttributeSyncing) {
+ // When not syncing the checked attribute, the attribute is directly
+ // controllable from the defaultValue React property. It needs to be
+ // updated as new props come in.
+ if (props.defaultChecked == null) {
+ node.removeAttribute('checked');
+ } else {
+ node.defaultChecked = !!props.defaultChecked;
+ }
+ } else {
+ // When syncing the checked attribute, it only changes when it needs
+ // to be removed, such as transitioning from a checkbox into a text input
+ if (props.checked == null && props.defaultChecked != null) {
+ node.defaultChecked = !!props.defaultChecked;
+ }
+ }
+}
+
+function postMountWrapper(element, props, isHydrating) {
+ var node = element;
+
+ // Do not assign value if it is already set. This prevents user text input
+ // from being lost during SSR hydration.
+ if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) {
+ var type = props.type;
+ var isButton = type === 'submit' || type === 'reset';
+
+ // Avoid setting value attribute on submit/reset inputs as it overrides the
+ // default value provided by the browser. See: #12872
+ if (isButton && (props.value === undefined || props.value === null)) {
+ return;
+ }
+
+ var _initialValue = toString(node._wrapperState.initialValue);
+
+ // Do not assign value if it is already set. This prevents user text input
+ // from being lost during SSR hydration.
+ if (!isHydrating) {
+ if (disableInputAttributeSyncing) {
+ var value = getToStringValue(props.value);
+
+ // When not syncing the value attribute, the value property points
+ // directly to the React prop. Only assign it if it exists.
+ if (value != null) {
+ // Always assign on buttons so that it is possible to assign an
+ // empty string to clear button text.
+ //
+ // Otherwise, do not re-assign the value property if is empty. This
+ // potentially avoids a DOM write and prevents Firefox (~60.0.1) from
+ // prematurely marking required inputs as invalid. Equality is compared
+ // to the current value in case the browser provided value is not an
+ // empty string.
+ if (isButton || value !== node.value) {
+ node.value = toString(value);
+ }
+ }
+ } else {
+ // When syncing the value attribute, the value property should use
+ // the wrapperState._initialValue property. This uses:
+ //
+ // 1. The value React property when present
+ // 2. The defaultValue React property when present
+ // 3. An empty string
+ if (_initialValue !== node.value) {
+ node.value = _initialValue;
+ }
+ }
+ }
+
+ if (disableInputAttributeSyncing) {
+ // When not syncing the value attribute, assign the value attribute
+ // directly from the defaultValue React property (when present)
+ var defaultValue = getToStringValue(props.defaultValue);
+ if (defaultValue != null) {
+ node.defaultValue = toString(defaultValue);
+ }
+ } else {
+ // Otherwise, the value attribute is synchronized to the property,
+ // so we assign defaultValue to the same thing as the value property
+ // assignment step above.
+ node.defaultValue = _initialValue;
+ }
+ }
+
+ // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
+ // this is needed to work around a chrome bug where setting defaultChecked
+ // will sometimes influence the value of checked (even after detachment).
+ // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
+ // We need to temporarily unset name to avoid disrupting radio button groups.
+ var name = node.name;
+ if (name !== '') {
+ node.name = '';
+ }
+
+ if (disableInputAttributeSyncing) {
+ // When not syncing the checked attribute, the checked property
+ // never gets assigned. It must be manually set. We don't want
+ // to do this when hydrating so that existing user input isn't
+ // modified
+ if (!isHydrating) {
+ updateChecked(element, props);
+ }
+
+ // Only assign the checked attribute if it is defined. This saves
+ // a DOM write when controlling the checked attribute isn't needed
+ // (text inputs, submit/reset)
+ if (props.hasOwnProperty('defaultChecked')) {
+ node.defaultChecked = !node.defaultChecked;
+ node.defaultChecked = !!props.defaultChecked;
+ }
+ } else {
+ // When syncing the checked attribute, both the checked property and
+ // attribute are assigned at the same time using defaultChecked. This uses:
+ //
+ // 1. The checked React property when present
+ // 2. The defaultChecked React property when present
+ // 3. Otherwise, false
+ node.defaultChecked = !node.defaultChecked;
+ node.defaultChecked = !!node._wrapperState.initialChecked;
+ }
+
+ if (name !== '') {
+ node.name = name;
+ }
+}
+
+function restoreControlledState(element, props) {
+ var node = element;
+ updateWrapper(node, props);
+ updateNamedCousins(node, props);
+}
+
+function updateNamedCousins(rootNode, props) {
+ var name = props.name;
+ if (props.type === 'radio' && name != null) {
+ var queryRoot = rootNode;
+
+ while (queryRoot.parentNode) {
+ queryRoot = queryRoot.parentNode;
+ }
+
+ // If `rootNode.form` was non-null, then we could try `form.elements`,
+ // but that sometimes behaves strangely in IE8. We could also try using
+ // `form.getElementsByName`, but that will only return direct children
+ // and won't include inputs that use the HTML5 `form=` attribute. Since
+ // the input might not even be in a form. It might not even be in the
+ // document. Let's just use the local `querySelectorAll` to ensure we don't
+ // miss anything.
+ var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
+
+ for (var i = 0; i < group.length; i++) {
+ var otherNode = group[i];
+ if (otherNode === rootNode || otherNode.form !== rootNode.form) {
+ continue;
+ }
+ // This will throw if radio buttons rendered by different copies of React
+ // and the same name are rendered into the same form (same as #1939).
+ // That's probably okay; we don't support it just as we don't support
+ // mixing React radio buttons with non-React ones.
+ var otherProps = getFiberCurrentPropsFromNode$1(otherNode);
+ !otherProps ? reactProdInvariant('90') : void 0;
+
+ // We need update the tracked value on the named cousin since the value
+ // was changed but the input saw no event or value set
+ updateValueIfChanged(otherNode);
+
+ // If this is a controlled radio button group, forcing the input that
+ // was previously checked to update will cause it to be come re-checked
+ // as appropriate.
+ updateWrapper(otherNode, otherProps);
+ }
+ }
+}
+
+// In Chrome, assigning defaultValue to certain input types triggers input validation.
+// For number inputs, the display value loses trailing decimal points. For email inputs,
+// Chrome raises "The specified value <x> is not a valid email address".
+//
+// Here we check to see if the defaultValue has actually changed, avoiding these problems
+// when the user is inputting text
+//
+// https://github.com/facebook/react/issues/7253
+function setDefaultValue(node, type, value) {
+ if (
+ // Focused number inputs synchronize on blur. See ChangeEventPlugin.js
+ type !== 'number' || node.ownerDocument.activeElement !== node) {
+ if (value == null) {
+ node.defaultValue = toString(node._wrapperState.initialValue);
+ } else if (node.defaultValue !== toString(value)) {
+ node.defaultValue = toString(value);
+ }
+ }
+}
+
+var eventTypes$1 = {
+ change: {
+ phasedRegistrationNames: {
+ bubbled: 'onChange',
+ captured: 'onChangeCapture'
+ },
+ dependencies: [TOP_BLUR, TOP_CHANGE, TOP_CLICK, TOP_FOCUS, TOP_INPUT, TOP_KEY_DOWN, TOP_KEY_UP, TOP_SELECTION_CHANGE]
+ }
+};
+
+function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
+ var event = SyntheticEvent.getPooled(eventTypes$1.change, inst, nativeEvent, target);
+ event.type = 'change';
+ // Flag this event loop as needing state restore.
+ enqueueStateRestore(target);
+ accumulateTwoPhaseDispatches(event);
+ return event;
+}
+/**
+ * For IE shims
+ */
+var activeElement = null;
+var activeElementInst = null;
+
+/**
+ * SECTION: handle `change` event
+ */
+function shouldUseChangeEvent(elem) {
+ var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
+ return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
+}
+
+function manualDispatchChangeEvent(nativeEvent) {
+ var event = createAndAccumulateChangeEvent(activeElementInst, nativeEvent, getEventTarget(nativeEvent));
+
+ // If change and propertychange bubbled, we'd just bind to it like all the
+ // other events and have it go through ReactBrowserEventEmitter. Since it
+ // doesn't, we manually listen for the events and so we have to enqueue and
+ // process the abstract event manually.
+ //
+ // Batching is necessary here in order to ensure that all event handlers run
+ // before the next rerender (including event handlers attached to ancestor
+ // elements instead of directly on the input). Without this, controlled
+ // components don't work properly in conjunction with event bubbling because
+ // the component is rerendered and the value reverted before all the event
+ // handlers can run. See https://github.com/facebook/react/issues/708.
+ batchedUpdates(runEventInBatch, event);
+}
+
+function runEventInBatch(event) {
+ runEventsInBatch(event);
+}
+
+function getInstIfValueChanged(targetInst) {
+ var targetNode = getNodeFromInstance$1(targetInst);
+ if (updateValueIfChanged(targetNode)) {
+ return targetInst;
+ }
+}
+
+function getTargetInstForChangeEvent(topLevelType, targetInst) {
+ if (topLevelType === TOP_CHANGE) {
+ return targetInst;
+ }
+}
+
+/**
+ * SECTION: handle `input` event
+ */
+var isInputEventSupported = false;
+if (canUseDOM) {
+ // IE9 claims to support the input event but fails to trigger it when
+ // deleting text, so we ignore its input events.
+ isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9);
+}
+
+/**
+ * (For IE <=9) Starts tracking propertychange events on the passed-in element
+ * and override the value property so that we can distinguish user events from
+ * value changes in JS.
+ */
+function startWatchingForValueChange(target, targetInst) {
+ activeElement = target;
+ activeElementInst = targetInst;
+ activeElement.attachEvent('onpropertychange', handlePropertyChange);
+}
+
+/**
+ * (For IE <=9) Removes the event listeners from the currently-tracked element,
+ * if any exists.
+ */
+function stopWatchingForValueChange() {
+ if (!activeElement) {
+ return;
+ }
+ activeElement.detachEvent('onpropertychange', handlePropertyChange);
+ activeElement = null;
+ activeElementInst = null;
+}
+
+/**
+ * (For IE <=9) Handles a propertychange event, sending a `change` event if
+ * the value of the active element has changed.
+ */
+function handlePropertyChange(nativeEvent) {
+ if (nativeEvent.propertyName !== 'value') {
+ return;
+ }
+ if (getInstIfValueChanged(activeElementInst)) {
+ manualDispatchChangeEvent(nativeEvent);
+ }
+}
+
+function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) {
+ if (topLevelType === TOP_FOCUS) {
+ // In IE9, propertychange fires for most input events but is buggy and
+ // doesn't fire when text is deleted, but conveniently, selectionchange
+ // appears to fire in all of the remaining cases so we catch those and
+ // forward the event if the value has changed
+ // In either case, we don't want to call the event handler if the value
+ // is changed from JS so we redefine a setter for `.value` that updates
+ // our activeElementValue variable, allowing us to ignore those changes
+ //
+ // stopWatching() should be a noop here but we call it just in case we
+ // missed a blur event somehow.
+ stopWatchingForValueChange();
+ startWatchingForValueChange(target, targetInst);
+ } else if (topLevelType === TOP_BLUR) {
+ stopWatchingForValueChange();
+ }
+}
+
+// For IE8 and IE9.
+function getTargetInstForInputEventPolyfill(topLevelType, targetInst) {
+ if (topLevelType === TOP_SELECTION_CHANGE || topLevelType === TOP_KEY_UP || topLevelType === TOP_KEY_DOWN) {
+ // On the selectionchange event, the target is just document which isn't
+ // helpful for us so just check activeElement instead.
+ //
+ // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
+ // propertychange on the first input event after setting `value` from a
+ // script and fires only keydown, keypress, keyup. Catching keyup usually
+ // gets it and catching keydown lets us fire an event for the first
+ // keystroke if user does a key repeat (it'll be a little delayed: right
+ // before the second keystroke). Other input methods (e.g., paste) seem to
+ // fire selectionchange normally.
+ return getInstIfValueChanged(activeElementInst);
+ }
+}
+
+/**
+ * SECTION: handle `click` event
+ */
+function shouldUseClickEvent(elem) {
+ // Use the `click` event to detect changes to checkbox and radio inputs.
+ // This approach works across all browsers, whereas `change` does not fire
+ // until `blur` in IE8.
+ var nodeName = elem.nodeName;
+ return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
+}
+
+function getTargetInstForClickEvent(topLevelType, targetInst) {
+ if (topLevelType === TOP_CLICK) {
+ return getInstIfValueChanged(targetInst);
+ }
+}
+
+function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) {
+ if (topLevelType === TOP_INPUT || topLevelType === TOP_CHANGE) {
+ return getInstIfValueChanged(targetInst);
+ }
+}
+
+function handleControlledInputBlur(node) {
+ var state = node._wrapperState;
+
+ if (!state || !state.controlled || node.type !== 'number') {
+ return;
+ }
+
+ if (!disableInputAttributeSyncing) {
+ // If controlled, assign the value attribute to the current value on blur
+ setDefaultValue(node, 'number', node.value);
+ }
+}
+
+/**
+ * This plugin creates an `onChange` event that normalizes change events
+ * across form elements. This event fires at a time when it's possible to
+ * change the element's value without seeing a flicker.
+ *
+ * Supported elements are:
+ * - input (see `isTextInputElement`)
+ * - textarea
+ * - select
+ */
+var ChangeEventPlugin = {
+ eventTypes: eventTypes$1,
+
+ _isInputEventSupported: isInputEventSupported,
+
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
+
+ var getTargetInstFunc = void 0,
+ handleEventFunc = void 0;
+ if (shouldUseChangeEvent(targetNode)) {
+ getTargetInstFunc = getTargetInstForChangeEvent;
+ } else if (isTextInputElement(targetNode)) {
+ if (isInputEventSupported) {
+ getTargetInstFunc = getTargetInstForInputOrChangeEvent;
+ } else {
+ getTargetInstFunc = getTargetInstForInputEventPolyfill;
+ handleEventFunc = handleEventsForInputEventPolyfill;
+ }
+ } else if (shouldUseClickEvent(targetNode)) {
+ getTargetInstFunc = getTargetInstForClickEvent;
+ }
+
+ if (getTargetInstFunc) {
+ var inst = getTargetInstFunc(topLevelType, targetInst);
+ if (inst) {
+ var event = createAndAccumulateChangeEvent(inst, nativeEvent, nativeEventTarget);
+ return event;
+ }
+ }
+
+ if (handleEventFunc) {
+ handleEventFunc(topLevelType, targetNode, targetInst);
+ }
+
+ // When blurring, set the value attribute for number inputs
+ if (topLevelType === TOP_BLUR) {
+ handleControlledInputBlur(targetNode);
+ }
+ }
+};
+
+/**
+ * Module that is injectable into `EventPluginHub`, that specifies a
+ * deterministic ordering of `EventPlugin`s. A convenient way to reason about
+ * plugins, without having to package every one of them. This is better than
+ * having plugins be ordered in the same order that they are injected because
+ * that ordering would be influenced by the packaging order.
+ * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
+ * preventing default on events is convenient in `SimpleEventPlugin` handlers.
+ */
+var DOMEventPluginOrder = ['ResponderEventPlugin', 'SimpleEventPlugin', 'EnterLeaveEventPlugin', 'ChangeEventPlugin', 'SelectEventPlugin', 'BeforeInputEventPlugin'];
+
+var SyntheticUIEvent = SyntheticEvent.extend({
+ view: null,
+ detail: null
+});
+
+var modifierKeyToProp = {
+ Alt: 'altKey',
+ Control: 'ctrlKey',
+ Meta: 'metaKey',
+ Shift: 'shiftKey'
+};
+
+// Older browsers (Safari <= 10, iOS Safari <= 10.2) do not support
+// getModifierState. If getModifierState is not supported, we map it to a set of
+// modifier keys exposed by the event. In this case, Lock-keys are not supported.
+/**
+ * Translation from modifier key to the associated property in the event.
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
+ */
+
+function modifierStateGetter(keyArg) {
+ var syntheticEvent = this;
+ var nativeEvent = syntheticEvent.nativeEvent;
+ if (nativeEvent.getModifierState) {
+ return nativeEvent.getModifierState(keyArg);
+ }
+ var keyProp = modifierKeyToProp[keyArg];
+ return keyProp ? !!nativeEvent[keyProp] : false;
+}
+
+function getEventModifierState(nativeEvent) {
+ return modifierStateGetter;
+}
+
+var previousScreenX = 0;
+var previousScreenY = 0;
+// Use flags to signal movementX/Y has already been set
+var isMovementXSet = false;
+var isMovementYSet = false;
+
+/**
+ * @interface MouseEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var SyntheticMouseEvent = SyntheticUIEvent.extend({
+ screenX: null,
+ screenY: null,
+ clientX: null,
+ clientY: null,
+ pageX: null,
+ pageY: null,
+ ctrlKey: null,
+ shiftKey: null,
+ altKey: null,
+ metaKey: null,
+ getModifierState: getEventModifierState,
+ button: null,
+ buttons: null,
+ relatedTarget: function (event) {
+ return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);
+ },
+ movementX: function (event) {
+ if ('movementX' in event) {
+ return event.movementX;
+ }
+
+ var screenX = previousScreenX;
+ previousScreenX = event.screenX;
+
+ if (!isMovementXSet) {
+ isMovementXSet = true;
+ return 0;
+ }
+
+ return event.type === 'mousemove' ? event.screenX - screenX : 0;
+ },
+ movementY: function (event) {
+ if ('movementY' in event) {
+ return event.movementY;
+ }
+
+ var screenY = previousScreenY;
+ previousScreenY = event.screenY;
+
+ if (!isMovementYSet) {
+ isMovementYSet = true;
+ return 0;
+ }
+
+ return event.type === 'mousemove' ? event.screenY - screenY : 0;
+ }
+});
+
+/**
+ * @interface PointerEvent
+ * @see http://www.w3.org/TR/pointerevents/
+ */
+var SyntheticPointerEvent = SyntheticMouseEvent.extend({
+ pointerId: null,
+ width: null,
+ height: null,
+ pressure: null,
+ tangentialPressure: null,
+ tiltX: null,
+ tiltY: null,
+ twist: null,
+ pointerType: null,
+ isPrimary: null
+});
+
+var eventTypes$2 = {
+ mouseEnter: {
+ registrationName: 'onMouseEnter',
+ dependencies: [TOP_MOUSE_OUT, TOP_MOUSE_OVER]
+ },
+ mouseLeave: {
+ registrationName: 'onMouseLeave',
+ dependencies: [TOP_MOUSE_OUT, TOP_MOUSE_OVER]
+ },
+ pointerEnter: {
+ registrationName: 'onPointerEnter',
+ dependencies: [TOP_POINTER_OUT, TOP_POINTER_OVER]
+ },
+ pointerLeave: {
+ registrationName: 'onPointerLeave',
+ dependencies: [TOP_POINTER_OUT, TOP_POINTER_OVER]
+ }
+};
+
+var EnterLeaveEventPlugin = {
+ eventTypes: eventTypes$2,
+
+ /**
+ * For almost every interaction we care about, there will be both a top-level
+ * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
+ * we do not extract duplicate events. However, moving the mouse into the
+ * browser from outside will not fire a `mouseout` event. In this case, we use
+ * the `mouseover` top-level event.
+ */
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var isOverEvent = topLevelType === TOP_MOUSE_OVER || topLevelType === TOP_POINTER_OVER;
+ var isOutEvent = topLevelType === TOP_MOUSE_OUT || topLevelType === TOP_POINTER_OUT;
+
+ if (isOverEvent && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
+ return null;
+ }
+
+ if (!isOutEvent && !isOverEvent) {
+ // Must not be a mouse or pointer in or out - ignoring.
+ return null;
+ }
+
+ var win = void 0;
+ if (nativeEventTarget.window === nativeEventTarget) {
+ // `nativeEventTarget` is probably a window object.
+ win = nativeEventTarget;
+ } else {
+ // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
+ var doc = nativeEventTarget.ownerDocument;
+ if (doc) {
+ win = doc.defaultView || doc.parentWindow;
+ } else {
+ win = window;
+ }
+ }
+
+ var from = void 0;
+ var to = void 0;
+ if (isOutEvent) {
+ from = targetInst;
+ var related = nativeEvent.relatedTarget || nativeEvent.toElement;
+ to = related ? getClosestInstanceFromNode(related) : null;
+ } else {
+ // Moving to a node from outside the window.
+ from = null;
+ to = targetInst;
+ }
+
+ if (from === to) {
+ // Nothing pertains to our managed components.
+ return null;
+ }
+
+ var eventInterface = void 0,
+ leaveEventType = void 0,
+ enterEventType = void 0,
+ eventTypePrefix = void 0;
+
+ if (topLevelType === TOP_MOUSE_OUT || topLevelType === TOP_MOUSE_OVER) {
+ eventInterface = SyntheticMouseEvent;
+ leaveEventType = eventTypes$2.mouseLeave;
+ enterEventType = eventTypes$2.mouseEnter;
+ eventTypePrefix = 'mouse';
+ } else if (topLevelType === TOP_POINTER_OUT || topLevelType === TOP_POINTER_OVER) {
+ eventInterface = SyntheticPointerEvent;
+ leaveEventType = eventTypes$2.pointerLeave;
+ enterEventType = eventTypes$2.pointerEnter;
+ eventTypePrefix = 'pointer';
+ }
+
+ var fromNode = from == null ? win : getNodeFromInstance$1(from);
+ var toNode = to == null ? win : getNodeFromInstance$1(to);
+
+ var leave = eventInterface.getPooled(leaveEventType, from, nativeEvent, nativeEventTarget);
+ leave.type = eventTypePrefix + 'leave';
+ leave.target = fromNode;
+ leave.relatedTarget = toNode;
+
+ var enter = eventInterface.getPooled(enterEventType, to, nativeEvent, nativeEventTarget);
+ enter.type = eventTypePrefix + 'enter';
+ enter.target = toNode;
+ enter.relatedTarget = fromNode;
+
+ accumulateEnterLeaveDispatches(leave, enter, from, to);
+
+ return [leave, enter];
+ }
+};
+
+/**
+ * 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$1 = 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$1.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * `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 has(key) {
+ return key._reactInternalFiber !== undefined;
+}
+
+function set(key, value) {
+ key._reactInternalFiber = value;
+}
+
+// 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$1 = 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;
+}
+
+function addEventBubbleListener(element, eventType, listener) {
+ element.addEventListener(eventType, listener, false);
+}
+
+function addEventCaptureListener(element, eventType, listener) {
+ element.addEventListener(eventType, listener, true);
+}
+
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
+ */
+var SyntheticAnimationEvent = SyntheticEvent.extend({
+ animationName: null,
+ elapsedTime: null,
+ pseudoElement: null
+});
+
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/clipboard-apis/
+ */
+var SyntheticClipboardEvent = SyntheticEvent.extend({
+ clipboardData: function (event) {
+ return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
+ }
+});
+
+/**
+ * @interface FocusEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var SyntheticFocusEvent = SyntheticUIEvent.extend({
+ relatedTarget: null
+});
+
+/**
+ * `charCode` represents the actual "character code" and is safe to use with
+ * `String.fromCharCode`. As such, only keys that correspond to printable
+ * characters produce a valid `charCode`, the only exception to this is Enter.
+ * The Tab-key is considered non-printable and does not have a `charCode`,
+ * presumably because it does not produce a tab-character in browsers.
+ *
+ * @param {object} nativeEvent Native browser event.
+ * @return {number} Normalized `charCode` property.
+ */
+function getEventCharCode(nativeEvent) {
+ var charCode = void 0;
+ var keyCode = nativeEvent.keyCode;
+
+ if ('charCode' in nativeEvent) {
+ charCode = nativeEvent.charCode;
+
+ // FF does not set `charCode` for the Enter-key, check against `keyCode`.
+ if (charCode === 0 && keyCode === 13) {
+ charCode = 13;
+ }
+ } else {
+ // IE8 does not implement `charCode`, but `keyCode` has the correct value.
+ charCode = keyCode;
+ }
+
+ // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux)
+ // report Enter as charCode 10 when ctrl is pressed.
+ if (charCode === 10) {
+ charCode = 13;
+ }
+
+ // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
+ // Must not discard the (non-)printable Enter-key.
+ if (charCode >= 32 || charCode === 13) {
+ return charCode;
+ }
+
+ return 0;
+}
+
+/**
+ * Normalization of deprecated HTML5 `key` values
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
+ */
+var normalizeKey = {
+ Esc: 'Escape',
+ Spacebar: ' ',
+ Left: 'ArrowLeft',
+ Up: 'ArrowUp',
+ Right: 'ArrowRight',
+ Down: 'ArrowDown',
+ Del: 'Delete',
+ Win: 'OS',
+ Menu: 'ContextMenu',
+ Apps: 'ContextMenu',
+ Scroll: 'ScrollLock',
+ MozPrintableKey: 'Unidentified'
+};
+
+/**
+ * Translation from legacy `keyCode` to HTML5 `key`
+ * Only special keys supported, all others depend on keyboard layout or browser
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
+ */
+var translateToKey = {
+ '8': 'Backspace',
+ '9': 'Tab',
+ '12': 'Clear',
+ '13': 'Enter',
+ '16': 'Shift',
+ '17': 'Control',
+ '18': 'Alt',
+ '19': 'Pause',
+ '20': 'CapsLock',
+ '27': 'Escape',
+ '32': ' ',
+ '33': 'PageUp',
+ '34': 'PageDown',
+ '35': 'End',
+ '36': 'Home',
+ '37': 'ArrowLeft',
+ '38': 'ArrowUp',
+ '39': 'ArrowRight',
+ '40': 'ArrowDown',
+ '45': 'Insert',
+ '46': 'Delete',
+ '112': 'F1',
+ '113': 'F2',
+ '114': 'F3',
+ '115': 'F4',
+ '116': 'F5',
+ '117': 'F6',
+ '118': 'F7',
+ '119': 'F8',
+ '120': 'F9',
+ '121': 'F10',
+ '122': 'F11',
+ '123': 'F12',
+ '144': 'NumLock',
+ '145': 'ScrollLock',
+ '224': 'Meta'
+};
+
+/**
+ * @param {object} nativeEvent Native browser event.
+ * @return {string} Normalized `key` property.
+ */
+function getEventKey(nativeEvent) {
+ if (nativeEvent.key) {
+ // Normalize inconsistent values reported by browsers due to
+ // implementations of a working draft specification.
+
+ // FireFox implements `key` but returns `MozPrintableKey` for all
+ // printable characters (normalized to `Unidentified`), ignore it.
+ var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
+ if (key !== 'Unidentified') {
+ return key;
+ }
+ }
+
+ // Browser does not implement `key`, polyfill as much of it as we can.
+ if (nativeEvent.type === 'keypress') {
+ var charCode = getEventCharCode(nativeEvent);
+
+ // The enter-key is technically both printable and non-printable and can
+ // thus be captured by `keypress`, no other non-printable key should.
+ return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
+ }
+ if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
+ // While user keyboard layout determines the actual meaning of each
+ // `keyCode` value, almost all function keys have a universal value.
+ return translateToKey[nativeEvent.keyCode] || 'Unidentified';
+ }
+ return '';
+}
+
+/**
+ * @interface KeyboardEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var SyntheticKeyboardEvent = SyntheticUIEvent.extend({
+ key: getEventKey,
+ location: null,
+ ctrlKey: null,
+ shiftKey: null,
+ altKey: null,
+ metaKey: null,
+ repeat: null,
+ locale: null,
+ getModifierState: getEventModifierState,
+ // Legacy Interface
+ charCode: function (event) {
+ // `charCode` is the result of a KeyPress event and represents the value of
+ // the actual printable character.
+
+ // KeyPress is deprecated, but its replacement is not yet final and not
+ // implemented in any major browser. Only KeyPress has charCode.
+ if (event.type === 'keypress') {
+ return getEventCharCode(event);
+ }
+ return 0;
+ },
+ keyCode: function (event) {
+ // `keyCode` is the result of a KeyDown/Up event and represents the value of
+ // physical keyboard key.
+
+ // The actual meaning of the value depends on the users' keyboard layout
+ // which cannot be detected. Assuming that it is a US keyboard layout
+ // provides a surprisingly accurate mapping for US and European users.
+ // Due to this, it is left to the user to implement at this time.
+ if (event.type === 'keydown' || event.type === 'keyup') {
+ return event.keyCode;
+ }
+ return 0;
+ },
+ which: function (event) {
+ // `which` is an alias for either `keyCode` or `charCode` depending on the
+ // type of the event.
+ if (event.type === 'keypress') {
+ return getEventCharCode(event);
+ }
+ if (event.type === 'keydown' || event.type === 'keyup') {
+ return event.keyCode;
+ }
+ return 0;
+ }
+});
+
+/**
+ * @interface DragEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var SyntheticDragEvent = SyntheticMouseEvent.extend({
+ dataTransfer: null
+});
+
+/**
+ * @interface TouchEvent
+ * @see http://www.w3.org/TR/touch-events/
+ */
+var SyntheticTouchEvent = SyntheticUIEvent.extend({
+ touches: null,
+ targetTouches: null,
+ changedTouches: null,
+ altKey: null,
+ metaKey: null,
+ ctrlKey: null,
+ shiftKey: null,
+ getModifierState: getEventModifierState
+});
+
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
+ */
+var SyntheticTransitionEvent = SyntheticEvent.extend({
+ propertyName: null,
+ elapsedTime: null,
+ pseudoElement: null
+});
+
+/**
+ * @interface WheelEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var SyntheticWheelEvent = SyntheticMouseEvent.extend({
+ deltaX: function (event) {
+ return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
+ 'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
+ },
+ deltaY: function (event) {
+ return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
+ 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
+ 'wheelDelta' in event ? -event.wheelDelta : 0;
+ },
+
+ deltaZ: null,
+
+ // Browsers without "deltaMode" is reporting in raw wheel delta where one
+ // notch on the scroll is always +/- 120, roughly equivalent to pixels.
+ // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
+ // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
+ deltaMode: null
+});
+
+/**
+ * Turns
+ * ['abort', ...]
+ * into
+ * eventTypes = {
+ * 'abort': {
+ * phasedRegistrationNames: {
+ * bubbled: 'onAbort',
+ * captured: 'onAbortCapture',
+ * },
+ * dependencies: [TOP_ABORT],
+ * },
+ * ...
+ * };
+ * topLevelEventsToDispatchConfig = new Map([
+ * [TOP_ABORT, { sameConfig }],
+ * ]);
+ */
+
+var interactiveEventTypeNames = [[TOP_BLUR, 'blur'], [TOP_CANCEL, 'cancel'], [TOP_CLICK, 'click'], [TOP_CLOSE, 'close'], [TOP_CONTEXT_MENU, 'contextMenu'], [TOP_COPY, 'copy'], [TOP_CUT, 'cut'], [TOP_AUX_CLICK, 'auxClick'], [TOP_DOUBLE_CLICK, 'doubleClick'], [TOP_DRAG_END, 'dragEnd'], [TOP_DRAG_START, 'dragStart'], [TOP_DROP, 'drop'], [TOP_FOCUS, 'focus'], [TOP_INPUT, 'input'], [TOP_INVALID, 'invalid'], [TOP_KEY_DOWN, 'keyDown'], [TOP_KEY_PRESS, 'keyPress'], [TOP_KEY_UP, 'keyUp'], [TOP_MOUSE_DOWN, 'mouseDown'], [TOP_MOUSE_UP, 'mouseUp'], [TOP_PASTE, 'paste'], [TOP_PAUSE, 'pause'], [TOP_PLAY, 'play'], [TOP_POINTER_CANCEL, 'pointerCancel'], [TOP_POINTER_DOWN, 'pointerDown'], [TOP_POINTER_UP, 'pointerUp'], [TOP_RATE_CHANGE, 'rateChange'], [TOP_RESET, 'reset'], [TOP_SEEKED, 'seeked'], [TOP_SUBMIT, 'submit'], [TOP_TOUCH_CANCEL, 'touchCancel'], [TOP_TOUCH_END, 'touchEnd'], [TOP_TOUCH_START, 'touchStart'], [TOP_VOLUME_CHANGE, 'volumeChange']];
+var nonInteractiveEventTypeNames = [[TOP_ABORT, 'abort'], [TOP_ANIMATION_END, 'animationEnd'], [TOP_ANIMATION_ITERATION, 'animationIteration'], [TOP_ANIMATION_START, 'animationStart'], [TOP_CAN_PLAY, 'canPlay'], [TOP_CAN_PLAY_THROUGH, 'canPlayThrough'], [TOP_DRAG, 'drag'], [TOP_DRAG_ENTER, 'dragEnter'], [TOP_DRAG_EXIT, 'dragExit'], [TOP_DRAG_LEAVE, 'dragLeave'], [TOP_DRAG_OVER, 'dragOver'], [TOP_DURATION_CHANGE, 'durationChange'], [TOP_EMPTIED, 'emptied'], [TOP_ENCRYPTED, 'encrypted'], [TOP_ENDED, 'ended'], [TOP_ERROR, 'error'], [TOP_GOT_POINTER_CAPTURE, 'gotPointerCapture'], [TOP_LOAD, 'load'], [TOP_LOADED_DATA, 'loadedData'], [TOP_LOADED_METADATA, 'loadedMetadata'], [TOP_LOAD_START, 'loadStart'], [TOP_LOST_POINTER_CAPTURE, 'lostPointerCapture'], [TOP_MOUSE_MOVE, 'mouseMove'], [TOP_MOUSE_OUT, 'mouseOut'], [TOP_MOUSE_OVER, 'mouseOver'], [TOP_PLAYING, 'playing'], [TOP_POINTER_MOVE, 'pointerMove'], [TOP_POINTER_OUT, 'pointerOut'], [TOP_POINTER_OVER, 'pointerOver'], [TOP_PROGRESS, 'progress'], [TOP_SCROLL, 'scroll'], [TOP_SEEKING, 'seeking'], [TOP_STALLED, 'stalled'], [TOP_SUSPEND, 'suspend'], [TOP_TIME_UPDATE, 'timeUpdate'], [TOP_TOGGLE, 'toggle'], [TOP_TOUCH_MOVE, 'touchMove'], [TOP_TRANSITION_END, 'transitionEnd'], [TOP_WAITING, 'waiting'], [TOP_WHEEL, 'wheel']];
+
+var eventTypes$4 = {};
+var topLevelEventsToDispatchConfig = {};
+
+function addEventTypeNameToConfig(_ref, isInteractive) {
+ var topEvent = _ref[0],
+ event = _ref[1];
+
+ var capitalizedEvent = event[0].toUpperCase() + event.slice(1);
+ var onEvent = 'on' + capitalizedEvent;
+
+ var type = {
+ phasedRegistrationNames: {
+ bubbled: onEvent,
+ captured: onEvent + 'Capture'
+ },
+ dependencies: [topEvent],
+ isInteractive: isInteractive
+ };
+ eventTypes$4[event] = type;
+ topLevelEventsToDispatchConfig[topEvent] = type;
+}
+
+interactiveEventTypeNames.forEach(function (eventTuple) {
+ addEventTypeNameToConfig(eventTuple, true);
+});
+nonInteractiveEventTypeNames.forEach(function (eventTuple) {
+ addEventTypeNameToConfig(eventTuple, false);
+});
+
+var SimpleEventPlugin = {
+ eventTypes: eventTypes$4,
+
+ isInteractiveTopLevelEventType: function (topLevelType) {
+ var config = topLevelEventsToDispatchConfig[topLevelType];
+ return config !== undefined && config.isInteractive === true;
+ },
+
+
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
+ if (!dispatchConfig) {
+ return null;
+ }
+ var EventConstructor = void 0;
+ switch (topLevelType) {
+ case TOP_KEY_PRESS:
+ // Firefox creates a keypress event for function keys too. This removes
+ // the unwanted keypress events. Enter is however both printable and
+ // non-printable. One would expect Tab to be as well (but it isn't).
+ if (getEventCharCode(nativeEvent) === 0) {
+ return null;
+ }
+ /* falls through */
+ case TOP_KEY_DOWN:
+ case TOP_KEY_UP:
+ EventConstructor = SyntheticKeyboardEvent;
+ break;
+ case TOP_BLUR:
+ case TOP_FOCUS:
+ EventConstructor = SyntheticFocusEvent;
+ break;
+ case TOP_CLICK:
+ // Firefox creates a click event on right mouse clicks. This removes the
+ // unwanted click events.
+ if (nativeEvent.button === 2) {
+ return null;
+ }
+ /* falls through */
+ case TOP_AUX_CLICK:
+ case TOP_DOUBLE_CLICK:
+ case TOP_MOUSE_DOWN:
+ case TOP_MOUSE_MOVE:
+ case TOP_MOUSE_UP:
+ // TODO: Disabled elements should not respond to mouse events
+ /* falls through */
+ case TOP_MOUSE_OUT:
+ case TOP_MOUSE_OVER:
+ case TOP_CONTEXT_MENU:
+ EventConstructor = SyntheticMouseEvent;
+ break;
+ case TOP_DRAG:
+ case TOP_DRAG_END:
+ case TOP_DRAG_ENTER:
+ case TOP_DRAG_EXIT:
+ case TOP_DRAG_LEAVE:
+ case TOP_DRAG_OVER:
+ case TOP_DRAG_START:
+ case TOP_DROP:
+ EventConstructor = SyntheticDragEvent;
+ break;
+ case TOP_TOUCH_CANCEL:
+ case TOP_TOUCH_END:
+ case TOP_TOUCH_MOVE:
+ case TOP_TOUCH_START:
+ EventConstructor = SyntheticTouchEvent;
+ break;
+ case TOP_ANIMATION_END:
+ case TOP_ANIMATION_ITERATION:
+ case TOP_ANIMATION_START:
+ EventConstructor = SyntheticAnimationEvent;
+ break;
+ case TOP_TRANSITION_END:
+ EventConstructor = SyntheticTransitionEvent;
+ break;
+ case TOP_SCROLL:
+ EventConstructor = SyntheticUIEvent;
+ break;
+ case TOP_WHEEL:
+ EventConstructor = SyntheticWheelEvent;
+ break;
+ case TOP_COPY:
+ case TOP_CUT:
+ case TOP_PASTE:
+ EventConstructor = SyntheticClipboardEvent;
+ break;
+ case TOP_GOT_POINTER_CAPTURE:
+ case TOP_LOST_POINTER_CAPTURE:
+ case TOP_POINTER_CANCEL:
+ case TOP_POINTER_DOWN:
+ case TOP_POINTER_MOVE:
+ case TOP_POINTER_OUT:
+ case TOP_POINTER_OVER:
+ case TOP_POINTER_UP:
+ EventConstructor = SyntheticPointerEvent;
+ break;
+ default:
+
+ // HTML Events
+ // @see http://www.w3.org/TR/html5/index.html#events-0
+ EventConstructor = SyntheticEvent;
+ break;
+ }
+ var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
+ accumulateTwoPhaseDispatches(event);
+ return event;
+ }
+};
+
+var isInteractiveTopLevelEventType = SimpleEventPlugin.isInteractiveTopLevelEventType;
+
+
+var CALLBACK_BOOKKEEPING_POOL_SIZE = 10;
+var callbackBookkeepingPool = [];
+
+/**
+ * Find the deepest React component completely containing the root of the
+ * passed-in instance (for use when entire React trees are nested within each
+ * other). If React trees are not nested, returns null.
+ */
+function findRootContainerNode(inst) {
+ // TODO: It may be a good idea to cache this to prevent unnecessary DOM
+ // traversal, but caching is difficult to do correctly without using a
+ // mutation observer to listen for all DOM changes.
+ while (inst.return) {
+ inst = inst.return;
+ }
+ if (inst.tag !== HostRoot) {
+ // This can happen if we're in a detached tree.
+ return null;
+ }
+ return inst.stateNode.containerInfo;
+}
+
+// Used to store ancestor hierarchy in top level callback
+function getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst) {
+ if (callbackBookkeepingPool.length) {
+ var instance = callbackBookkeepingPool.pop();
+ instance.topLevelType = topLevelType;
+ instance.nativeEvent = nativeEvent;
+ instance.targetInst = targetInst;
+ return instance;
+ }
+ return {
+ topLevelType: topLevelType,
+ nativeEvent: nativeEvent,
+ targetInst: targetInst,
+ ancestors: []
+ };
+}
+
+function releaseTopLevelCallbackBookKeeping(instance) {
+ instance.topLevelType = null;
+ instance.nativeEvent = null;
+ instance.targetInst = null;
+ instance.ancestors.length = 0;
+ if (callbackBookkeepingPool.length < CALLBACK_BOOKKEEPING_POOL_SIZE) {
+ callbackBookkeepingPool.push(instance);
+ }
+}
+
+function handleTopLevel(bookKeeping) {
+ var targetInst = bookKeeping.targetInst;
+
+ // Loop through the hierarchy, in case there's any nested components.
+ // It's important that we build the array of ancestors before calling any
+ // event handlers, because event handlers can modify the DOM, leading to
+ // inconsistencies with ReactMount's node cache. See #1105.
+ var ancestor = targetInst;
+ do {
+ if (!ancestor) {
+ bookKeeping.ancestors.push(ancestor);
+ break;
+ }
+ var root = findRootContainerNode(ancestor);
+ if (!root) {
+ break;
+ }
+ bookKeeping.ancestors.push(ancestor);
+ ancestor = getClosestInstanceFromNode(root);
+ } while (ancestor);
+
+ for (var i = 0; i < bookKeeping.ancestors.length; i++) {
+ targetInst = bookKeeping.ancestors[i];
+ runExtractedEventsInBatch(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
+ }
+}
+
+// TODO: can we stop exporting these?
+var _enabled = true;
+
+function setEnabled(enabled) {
+ _enabled = !!enabled;
+}
+
+function isEnabled() {
+ return _enabled;
+}
+
+/**
+ * Traps top-level events by using event bubbling.
+ *
+ * @param {number} topLevelType Number from `TopLevelEventTypes`.
+ * @param {object} element Element on which to attach listener.
+ * @return {?object} An object with a remove function which will forcefully
+ * remove the listener.
+ * @internal
+ */
+function trapBubbledEvent(topLevelType, element) {
+ if (!element) {
+ return null;
+ }
+ var dispatch = isInteractiveTopLevelEventType(topLevelType) ? dispatchInteractiveEvent : dispatchEvent;
+
+ addEventBubbleListener(element, getRawEventName(topLevelType),
+ // Check if interactive and wrap in interactiveUpdates
+ dispatch.bind(null, topLevelType));
+}
+
+/**
+ * Traps a top-level event by using event capturing.
+ *
+ * @param {number} topLevelType Number from `TopLevelEventTypes`.
+ * @param {object} element Element on which to attach listener.
+ * @return {?object} An object with a remove function which will forcefully
+ * remove the listener.
+ * @internal
+ */
+function trapCapturedEvent(topLevelType, element) {
+ if (!element) {
+ return null;
+ }
+ var dispatch = isInteractiveTopLevelEventType(topLevelType) ? dispatchInteractiveEvent : dispatchEvent;
+
+ addEventCaptureListener(element, getRawEventName(topLevelType),
+ // Check if interactive and wrap in interactiveUpdates
+ dispatch.bind(null, topLevelType));
+}
+
+function dispatchInteractiveEvent(topLevelType, nativeEvent) {
+ interactiveUpdates(dispatchEvent, topLevelType, nativeEvent);
+}
+
+function dispatchEvent(topLevelType, nativeEvent) {
+ if (!_enabled) {
+ return;
+ }
+
+ var nativeEventTarget = getEventTarget(nativeEvent);
+ var targetInst = getClosestInstanceFromNode(nativeEventTarget);
+ if (targetInst !== null && typeof targetInst.tag === 'number' && !isFiberMounted(targetInst)) {
+ // If we get an event (ex: img onload) before committing that
+ // component's mount, ignore it for now (that is, treat it as if it was an
+ // event on a non-React tree). We might also consider queueing events and
+ // dispatching them after the mount.
+ targetInst = null;
+ }
+
+ var bookKeeping = getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst);
+
+ try {
+ // Event queue being processed in the same cycle allows
+ // `preventDefault`.
+ batchedUpdates(handleTopLevel, bookKeeping);
+ } finally {
+ releaseTopLevelCallbackBookKeeping(bookKeeping);
+ }
+}
+
+/**
+ * Summary of `ReactBrowserEventEmitter` event handling:
+ *
+ * - Top-level delegation is used to trap most native browser events. This
+ * may only occur in the main thread and is the responsibility of
+ * ReactDOMEventListener, which is injected and can therefore support
+ * pluggable event sources. This is the only work that occurs in the main
+ * thread.
+ *
+ * - We normalize and de-duplicate events to account for browser quirks. This
+ * may be done in the worker thread.
+ *
+ * - Forward these native events (with the associated top-level type used to
+ * trap it) to `EventPluginHub`, which in turn will ask plugins if they want
+ * to extract any synthetic events.
+ *
+ * - The `EventPluginHub` will then process each event by annotating them with
+ * "dispatches", a sequence of listeners and IDs that care about that event.
+ *
+ * - The `EventPluginHub` then dispatches the events.
+ *
+ * Overview of React and the event system:
+ *
+ * +------------+ .
+ * | DOM | .
+ * +------------+ .
+ * | .
+ * v .
+ * +------------+ .
+ * | ReactEvent | .
+ * | Listener | .
+ * +------------+ . +-----------+
+ * | . +--------+|SimpleEvent|
+ * | . | |Plugin |
+ * +-----|------+ . v +-----------+
+ * | | | . +--------------+ +------------+
+ * | +-----------.--->|EventPluginHub| | Event |
+ * | | . | | +-----------+ | Propagators|
+ * | ReactEvent | . | | |TapEvent | |------------|
+ * | Emitter | . | |<---+|Plugin | |other plugin|
+ * | | . | | +-----------+ | utilities |
+ * | +-----------.--->| | +------------+
+ * | | | . +--------------+
+ * +-----|------+ . ^ +-----------+
+ * | . | |Enter/Leave|
+ * + . +-------+|Plugin |
+ * +-------------+ . +-----------+
+ * | application | .
+ * |-------------| .
+ * | | .
+ * | | .
+ * +-------------+ .
+ * .
+ * React Core . General Purpose Event Plugin System
+ */
+
+var alreadyListeningTo = {};
+var reactTopListenersCounter = 0;
+
+/**
+ * To ensure no conflicts with other potential React instances on the page
+ */
+var topListenersIDKey = '_reactListenersID' + ('' + Math.random()).slice(2);
+
+function getListeningForDocument(mountAt) {
+ // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
+ // directly.
+ if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
+ mountAt[topListenersIDKey] = reactTopListenersCounter++;
+ alreadyListeningTo[mountAt[topListenersIDKey]] = {};
+ }
+ return alreadyListeningTo[mountAt[topListenersIDKey]];
+}
+
+/**
+ * We listen for bubbled touch events on the document object.
+ *
+ * Firefox v8.01 (and possibly others) exhibited strange behavior when
+ * mounting `onmousemove` events at some node that was not the document
+ * element. The symptoms were that if your mouse is not moving over something
+ * contained within that mount point (for example on the background) the
+ * top-level listeners for `onmousemove` won't be called. However, if you
+ * register the `mousemove` on the document object, then it will of course
+ * catch all `mousemove`s. This along with iOS quirks, justifies restricting
+ * top-level listeners to the document object only, at least for these
+ * movement types of events and possibly all events.
+ *
+ * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
+ *
+ * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
+ * they bubble to document.
+ *
+ * @param {string} registrationName Name of listener (e.g. `onClick`).
+ * @param {object} mountAt Container where to mount the listener
+ */
+function listenTo(registrationName, mountAt) {
+ var isListening = getListeningForDocument(mountAt);
+ var dependencies = registrationNameDependencies[registrationName];
+
+ for (var i = 0; i < dependencies.length; i++) {
+ var dependency = dependencies[i];
+ if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
+ switch (dependency) {
+ case TOP_SCROLL:
+ trapCapturedEvent(TOP_SCROLL, mountAt);
+ break;
+ case TOP_FOCUS:
+ case TOP_BLUR:
+ trapCapturedEvent(TOP_FOCUS, mountAt);
+ trapCapturedEvent(TOP_BLUR, mountAt);
+ // We set the flag for a single dependency later in this function,
+ // but this ensures we mark both as attached rather than just one.
+ isListening[TOP_BLUR] = true;
+ isListening[TOP_FOCUS] = true;
+ break;
+ case TOP_CANCEL:
+ case TOP_CLOSE:
+ if (isEventSupported(getRawEventName(dependency))) {
+ trapCapturedEvent(dependency, mountAt);
+ }
+ break;
+ case TOP_INVALID:
+ case TOP_SUBMIT:
+ case TOP_RESET:
+ // We listen to them on the target DOM elements.
+ // Some of them bubble so we don't want them to fire twice.
+ break;
+ default:
+ // By default, listen on the top level to all non-media events.
+ // Media events don't bubble so adding the listener wouldn't do anything.
+ var isMediaEvent = mediaEventTypes.indexOf(dependency) !== -1;
+ if (!isMediaEvent) {
+ trapBubbledEvent(dependency, mountAt);
+ }
+ break;
+ }
+ isListening[dependency] = true;
+ }
+ }
+}
+
+function isListeningToAllDependencies(registrationName, mountAt) {
+ var isListening = getListeningForDocument(mountAt);
+ var dependencies = registrationNameDependencies[registrationName];
+ for (var i = 0; i < dependencies.length; i++) {
+ var dependency = dependencies[i];
+ if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function getActiveElement(doc) {
+ doc = doc || (typeof document !== 'undefined' ? document : undefined);
+ if (typeof doc === 'undefined') {
+ return null;
+ }
+ try {
+ return doc.activeElement || doc.body;
+ } catch (e) {
+ return doc.body;
+ }
+}
+
+/**
+ * Given any node return the first leaf node without children.
+ *
+ * @param {DOMElement|DOMTextNode} node
+ * @return {DOMElement|DOMTextNode}
+ */
+function getLeafNode(node) {
+ while (node && node.firstChild) {
+ node = node.firstChild;
+ }
+ return node;
+}
+
+/**
+ * Get the next sibling within a container. This will walk up the
+ * DOM if a node's siblings have been exhausted.
+ *
+ * @param {DOMElement|DOMTextNode} node
+ * @return {?DOMElement|DOMTextNode}
+ */
+function getSiblingNode(node) {
+ while (node) {
+ if (node.nextSibling) {
+ return node.nextSibling;
+ }
+ node = node.parentNode;
+ }
+}
+
+/**
+ * Get object describing the nodes which contain characters at offset.
+ *
+ * @param {DOMElement|DOMTextNode} root
+ * @param {number} offset
+ * @return {?object}
+ */
+function getNodeForCharacterOffset(root, offset) {
+ var node = getLeafNode(root);
+ var nodeStart = 0;
+ var nodeEnd = 0;
+
+ while (node) {
+ if (node.nodeType === TEXT_NODE) {
+ nodeEnd = nodeStart + node.textContent.length;
+
+ if (nodeStart <= offset && nodeEnd >= offset) {
+ return {
+ node: node,
+ offset: offset - nodeStart
+ };
+ }
+
+ nodeStart = nodeEnd;
+ }
+
+ node = getLeafNode(getSiblingNode(node));
+ }
+}
+
+/**
+ * @param {DOMElement} outerNode
+ * @return {?object}
+ */
+function getOffsets(outerNode) {
+ var ownerDocument = outerNode.ownerDocument;
+
+ var win = ownerDocument && ownerDocument.defaultView || window;
+ var selection = win.getSelection && win.getSelection();
+
+ if (!selection || selection.rangeCount === 0) {
+ return null;
+ }
+
+ var anchorNode = selection.anchorNode,
+ anchorOffset = selection.anchorOffset,
+ focusNode = selection.focusNode,
+ focusOffset = selection.focusOffset;
+
+ // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the
+ // up/down buttons on an <input type="number">. Anonymous divs do not seem to
+ // expose properties, triggering a "Permission denied error" if any of its
+ // properties are accessed. The only seemingly possible way to avoid erroring
+ // is to access a property that typically works for non-anonymous divs and
+ // catch any error that may otherwise arise. See
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
+
+ try {
+ /* eslint-disable no-unused-expressions */
+ anchorNode.nodeType;
+ focusNode.nodeType;
+ /* eslint-enable no-unused-expressions */
+ } catch (e) {
+ return null;
+ }
+
+ return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset);
+}
+
+/**
+ * Returns {start, end} where `start` is the character/codepoint index of
+ * (anchorNode, anchorOffset) within the textContent of `outerNode`, and
+ * `end` is the index of (focusNode, focusOffset).
+ *
+ * Returns null if you pass in garbage input but we should probably just crash.
+ *
+ * Exported only for testing.
+ */
+function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) {
+ var length = 0;
+ var start = -1;
+ var end = -1;
+ var indexWithinAnchor = 0;
+ var indexWithinFocus = 0;
+ var node = outerNode;
+ var parentNode = null;
+
+ outer: while (true) {
+ var next = null;
+
+ while (true) {
+ if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) {
+ start = length + anchorOffset;
+ }
+ if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) {
+ end = length + focusOffset;
+ }
+
+ if (node.nodeType === TEXT_NODE) {
+ length += node.nodeValue.length;
+ }
+
+ if ((next = node.firstChild) === null) {
+ break;
+ }
+ // Moving from `node` to its first child `next`.
+ parentNode = node;
+ node = next;
+ }
+
+ while (true) {
+ if (node === outerNode) {
+ // If `outerNode` has children, this is always the second time visiting
+ // it. If it has no children, this is still the first loop, and the only
+ // valid selection is anchorNode and focusNode both equal to this node
+ // and both offsets 0, in which case we will have handled above.
+ break outer;
+ }
+ if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) {
+ start = length;
+ }
+ if (parentNode === focusNode && ++indexWithinFocus === focusOffset) {
+ end = length;
+ }
+ if ((next = node.nextSibling) !== null) {
+ break;
+ }
+ node = parentNode;
+ parentNode = node.parentNode;
+ }
+
+ // Moving from `node` to its next sibling `next`.
+ node = next;
+ }
+
+ if (start === -1 || end === -1) {
+ // This should never happen. (Would happen if the anchor/focus nodes aren't
+ // actually inside the passed-in node.)
+ return null;
+ }
+
+ return {
+ start: start,
+ end: end
+ };
+}
+
+/**
+ * In modern non-IE browsers, we can support both forward and backward
+ * selections.
+ *
+ * Note: IE10+ supports the Selection object, but it does not support
+ * the `extend` method, which means that even in modern IE, it's not possible
+ * to programmatically create a backward selection. Thus, for all IE
+ * versions, we use the old IE API to create our selections.
+ *
+ * @param {DOMElement|DOMTextNode} node
+ * @param {object} offsets
+ */
+function setOffsets(node, offsets) {
+ var doc = node.ownerDocument || document;
+ var win = doc && doc.defaultView || window;
+
+ // Edge fails with "Object expected" in some scenarios.
+ // (For instance: TinyMCE editor used in a list component that supports pasting to add more,
+ // fails when pasting 100+ items)
+ if (!win.getSelection) {
+ return;
+ }
+
+ var selection = win.getSelection();
+ var length = node.textContent.length;
+ var start = Math.min(offsets.start, length);
+ var end = offsets.end === undefined ? start : Math.min(offsets.end, length);
+
+ // IE 11 uses modern selection, but doesn't support the extend method.
+ // Flip backward selections, so we can set with a single range.
+ if (!selection.extend && start > end) {
+ var temp = end;
+ end = start;
+ start = temp;
+ }
+
+ var startMarker = getNodeForCharacterOffset(node, start);
+ var endMarker = getNodeForCharacterOffset(node, end);
+
+ if (startMarker && endMarker) {
+ if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) {
+ return;
+ }
+ var range = doc.createRange();
+ range.setStart(startMarker.node, startMarker.offset);
+ selection.removeAllRanges();
+
+ if (start > end) {
+ selection.addRange(range);
+ selection.extend(endMarker.node, endMarker.offset);
+ } else {
+ range.setEnd(endMarker.node, endMarker.offset);
+ selection.addRange(range);
+ }
+ }
+}
+
+function isTextNode(node) {
+ return node && node.nodeType === TEXT_NODE;
+}
+
+function containsNode(outerNode, innerNode) {
+ if (!outerNode || !innerNode) {
+ return false;
+ } else if (outerNode === innerNode) {
+ return true;
+ } else if (isTextNode(outerNode)) {
+ return false;
+ } else if (isTextNode(innerNode)) {
+ return containsNode(outerNode, innerNode.parentNode);
+ } else if ('contains' in outerNode) {
+ return outerNode.contains(innerNode);
+ } else if (outerNode.compareDocumentPosition) {
+ return !!(outerNode.compareDocumentPosition(innerNode) & 16);
+ } else {
+ return false;
+ }
+}
+
+function isInDocument(node) {
+ return node && node.ownerDocument && containsNode(node.ownerDocument.documentElement, node);
+}
+
+function isSameOriginFrame(iframe) {
+ try {
+ // Accessing the contentDocument of a HTMLIframeElement can cause the browser
+ // to throw, e.g. if it has a cross-origin src attribute.
+ // Safari will show an error in the console when the access results in "Blocked a frame with origin". e.g:
+ // iframe.contentDocument.defaultView;
+ // A safety way is to access one of the cross origin properties: Window or Location
+ // Which might result in "SecurityError" DOM Exception and it is compatible to Safari.
+ // https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl
+
+ return typeof iframe.contentWindow.location.href === 'string';
+ } catch (err) {
+ return false;
+ }
+}
+
+function getActiveElementDeep() {
+ var win = window;
+ var element = getActiveElement();
+ while (element instanceof win.HTMLIFrameElement) {
+ if (isSameOriginFrame(element)) {
+ win = element.contentWindow;
+ } else {
+ return element;
+ }
+ element = getActiveElement(win.document);
+ }
+ return element;
+}
+
+/**
+ * @ReactInputSelection: React input selection module. Based on Selection.js,
+ * but modified to be suitable for react and has a couple of bug fixes (doesn't
+ * assume buttons have range selections allowed).
+ * Input selection module for React.
+ */
+
+/**
+ * @hasSelectionCapabilities: we get the element types that support selection
+ * from https://html.spec.whatwg.org/#do-not-apply, looking at `selectionStart`
+ * and `selectionEnd` rows.
+ */
+function hasSelectionCapabilities(elem) {
+ var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
+ return nodeName && (nodeName === 'input' && (elem.type === 'text' || elem.type === 'search' || elem.type === 'tel' || elem.type === 'url' || elem.type === 'password') || nodeName === 'textarea' || elem.contentEditable === 'true');
+}
+
+function getSelectionInformation() {
+ var focusedElem = getActiveElementDeep();
+ return {
+ focusedElem: focusedElem,
+ selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection$1(focusedElem) : null
+ };
+}
+
+/**
+ * @restoreSelection: If any selection information was potentially lost,
+ * restore it. This is useful when performing operations that could remove dom
+ * nodes and place them back in, resulting in focus being lost.
+ */
+function restoreSelection(priorSelectionInformation) {
+ var curFocusedElem = getActiveElementDeep();
+ var priorFocusedElem = priorSelectionInformation.focusedElem;
+ var priorSelectionRange = priorSelectionInformation.selectionRange;
+ if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
+ if (priorSelectionRange !== null && hasSelectionCapabilities(priorFocusedElem)) {
+ setSelection(priorFocusedElem, priorSelectionRange);
+ }
+
+ // Focusing a node can change the scroll position, which is undesirable
+ var ancestors = [];
+ var ancestor = priorFocusedElem;
+ while (ancestor = ancestor.parentNode) {
+ if (ancestor.nodeType === ELEMENT_NODE) {
+ ancestors.push({
+ element: ancestor,
+ left: ancestor.scrollLeft,
+ top: ancestor.scrollTop
+ });
+ }
+ }
+
+ if (typeof priorFocusedElem.focus === 'function') {
+ priorFocusedElem.focus();
+ }
+
+ for (var i = 0; i < ancestors.length; i++) {
+ var info = ancestors[i];
+ info.element.scrollLeft = info.left;
+ info.element.scrollTop = info.top;
+ }
+ }
+}
+
+/**
+ * @getSelection: Gets the selection bounds of a focused textarea, input or
+ * contentEditable node.
+ * -@input: Look up selection bounds of this input
+ * -@return {start: selectionStart, end: selectionEnd}
+ */
+function getSelection$1(input) {
+ var selection = void 0;
+
+ if ('selectionStart' in input) {
+ // Modern browser with input or textarea.
+ selection = {
+ start: input.selectionStart,
+ end: input.selectionEnd
+ };
+ } else {
+ // Content editable or old IE textarea.
+ selection = getOffsets(input);
+ }
+
+ return selection || { start: 0, end: 0 };
+}
+
+/**
+ * @setSelection: Sets the selection bounds of a textarea or input and focuses
+ * the input.
+ * -@input Set selection bounds of this input or textarea
+ * -@offsets Object of same form that is returned from get*
+ */
+function setSelection(input, offsets) {
+ var start = offsets.start,
+ end = offsets.end;
+
+ if (end === undefined) {
+ end = start;
+ }
+
+ if ('selectionStart' in input) {
+ input.selectionStart = start;
+ input.selectionEnd = Math.min(end, input.value.length);
+ } else {
+ setOffsets(input, offsets);
+ }
+}
+
+var skipSelectionChangeEvent = canUseDOM && 'documentMode' in document && document.documentMode <= 11;
+
+var eventTypes$3 = {
+ select: {
+ phasedRegistrationNames: {
+ bubbled: 'onSelect',
+ captured: 'onSelectCapture'
+ },
+ dependencies: [TOP_BLUR, TOP_CONTEXT_MENU, TOP_DRAG_END, TOP_FOCUS, TOP_KEY_DOWN, TOP_KEY_UP, TOP_MOUSE_DOWN, TOP_MOUSE_UP, TOP_SELECTION_CHANGE]
+ }
+};
+
+var activeElement$1 = null;
+var activeElementInst$1 = null;
+var lastSelection = null;
+var mouseDown = false;
+
+/**
+ * Get an object which is a unique representation of the current selection.
+ *
+ * The return value will not be consistent across nodes or browsers, but
+ * two identical selections on the same node will return identical objects.
+ *
+ * @param {DOMElement} node
+ * @return {object}
+ */
+function getSelection(node) {
+ if ('selectionStart' in node && hasSelectionCapabilities(node)) {
+ return {
+ start: node.selectionStart,
+ end: node.selectionEnd
+ };
+ } else {
+ var win = node.ownerDocument && node.ownerDocument.defaultView || window;
+ var selection = win.getSelection();
+ return {
+ anchorNode: selection.anchorNode,
+ anchorOffset: selection.anchorOffset,
+ focusNode: selection.focusNode,
+ focusOffset: selection.focusOffset
+ };
+ }
+}
+
+/**
+ * Get document associated with the event target.
+ *
+ * @param {object} nativeEventTarget
+ * @return {Document}
+ */
+function getEventTargetDocument(eventTarget) {
+ return eventTarget.window === eventTarget ? eventTarget.document : eventTarget.nodeType === DOCUMENT_NODE ? eventTarget : eventTarget.ownerDocument;
+}
+
+/**
+ * Poll selection to see whether it's changed.
+ *
+ * @param {object} nativeEvent
+ * @param {object} nativeEventTarget
+ * @return {?SyntheticEvent}
+ */
+function constructSelectEvent(nativeEvent, nativeEventTarget) {
+ // Ensure we have the right element, and that the user is not dragging a
+ // selection (this matches native `select` event behavior). In HTML5, select
+ // fires only on input and textarea thus if there's no focused element we
+ // won't dispatch.
+ var doc = getEventTargetDocument(nativeEventTarget);
+
+ if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement(doc)) {
+ return null;
+ }
+
+ // Only fire when selection has actually changed.
+ var currentSelection = getSelection(activeElement$1);
+ if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {
+ lastSelection = currentSelection;
+
+ var syntheticEvent = SyntheticEvent.getPooled(eventTypes$3.select, activeElementInst$1, nativeEvent, nativeEventTarget);
+
+ syntheticEvent.type = 'select';
+ syntheticEvent.target = activeElement$1;
+
+ accumulateTwoPhaseDispatches(syntheticEvent);
+
+ return syntheticEvent;
+ }
+
+ return null;
+}
+
+/**
+ * This plugin creates an `onSelect` event that normalizes select events
+ * across form elements.
+ *
+ * Supported elements are:
+ * - input (see `isTextInputElement`)
+ * - textarea
+ * - contentEditable
+ *
+ * This differs from native browser implementations in the following ways:
+ * - Fires on contentEditable fields as well as inputs.
+ * - Fires for collapsed selection.
+ * - Fires after user input.
+ */
+var SelectEventPlugin = {
+ eventTypes: eventTypes$3,
+
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var doc = getEventTargetDocument(nativeEventTarget);
+ // Track whether all listeners exists for this plugin. If none exist, we do
+ // not extract events. See #3639.
+ if (!doc || !isListeningToAllDependencies('onSelect', doc)) {
+ return null;
+ }
+
+ var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
+
+ switch (topLevelType) {
+ // Track the input node that has focus.
+ case TOP_FOCUS:
+ if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {
+ activeElement$1 = targetNode;
+ activeElementInst$1 = targetInst;
+ lastSelection = null;
+ }
+ break;
+ case TOP_BLUR:
+ activeElement$1 = null;
+ activeElementInst$1 = null;
+ lastSelection = null;
+ break;
+ // Don't fire the event while the user is dragging. This matches the
+ // semantics of the native select event.
+ case TOP_MOUSE_DOWN:
+ mouseDown = true;
+ break;
+ case TOP_CONTEXT_MENU:
+ case TOP_MOUSE_UP:
+ case TOP_DRAG_END:
+ mouseDown = false;
+ return constructSelectEvent(nativeEvent, nativeEventTarget);
+ // Chrome and IE fire non-standard event when selection is changed (and
+ // sometimes when it hasn't). IE's event fires out of order with respect
+ // to key and input events on deletion, so we discard it.
+ //
+ // Firefox doesn't support selectionchange, so check selection status
+ // after each key entry. The selection changes after keydown and before
+ // keyup, but we check on keydown as well in the case of holding down a
+ // key, when multiple keydown events are fired but only one keyup is.
+ // This is also our approach for IE handling, for the reason above.
+ case TOP_SELECTION_CHANGE:
+ if (skipSelectionChangeEvent) {
+ break;
+ }
+ // falls through
+ case TOP_KEY_DOWN:
+ case TOP_KEY_UP:
+ return constructSelectEvent(nativeEvent, nativeEventTarget);
+ }
+
+ return null;
+ }
+};
+
+/**
+ * Inject modules for resolving DOM hierarchy and plugin ordering.
+ */
+injection.injectEventPluginOrder(DOMEventPluginOrder);
+setComponentTree(getFiberCurrentPropsFromNode$1, getInstanceFromNode$1, getNodeFromInstance$1);
+
+/**
+ * Some important event plugins included by default (without having to require
+ * them).
+ */
+injection.injectEventPluginsByName({
+ SimpleEventPlugin: SimpleEventPlugin,
+ EnterLeaveEventPlugin: EnterLeaveEventPlugin,
+ ChangeEventPlugin: ChangeEventPlugin,
+ SelectEventPlugin: SelectEventPlugin,
+ BeforeInputEventPlugin: BeforeInputEventPlugin
+});
+
+function flattenChildren(children) {
+ var content = '';
+
+ // Flatten children. We'll warn if they are invalid
+ // during validateProps() which runs for hydration too.
+ // Note that this would throw on non-element objects.
+ // Elements are stringified (which is normally irrelevant
+ // but matters for <fbt>).
+ React.Children.forEach(children, function (child) {
+ if (child == null) {
+ return;
+ }
+ content += child;
+ // Note: we don't warn about invalid children here.
+ // Instead, this is done separately below so that
+ // it happens during the hydration codepath too.
+ });
+
+ return content;
+}
+
+/**
+ * Implements an <option> host component that warns when `selected` is set.
+ */
+
+
+
+function postMountWrapper$1(element, props) {
+ // value="" should make a value attribute (#6219)
+ if (props.value != null) {
+ element.setAttribute('value', toString(getToStringValue(props.value)));
+ }
+}
+
+function getHostProps$1(element, props) {
+ var hostProps = _assign({ children: undefined }, props);
+ var content = flattenChildren(props.children);
+
+ if (content) {
+ hostProps.children = content;
+ }
+
+ return hostProps;
+}
+
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+function updateOptions(node, multiple, propValue, setDefaultSelected) {
+ var options = node.options;
+
+ if (multiple) {
+ var selectedValues = propValue;
+ var selectedValue = {};
+ for (var i = 0; i < selectedValues.length; i++) {
+ // Prefix to avoid chaos with special keys.
+ selectedValue['$' + selectedValues[i]] = true;
+ }
+ for (var _i = 0; _i < options.length; _i++) {
+ var selected = selectedValue.hasOwnProperty('$' + options[_i].value);
+ if (options[_i].selected !== selected) {
+ options[_i].selected = selected;
+ }
+ if (selected && setDefaultSelected) {
+ options[_i].defaultSelected = true;
+ }
+ }
+ } else {
+ // Do not set `select.value` as exact behavior isn't consistent across all
+ // browsers for all cases.
+ var _selectedValue = toString(getToStringValue(propValue));
+ var defaultSelected = null;
+ for (var _i2 = 0; _i2 < options.length; _i2++) {
+ if (options[_i2].value === _selectedValue) {
+ options[_i2].selected = true;
+ if (setDefaultSelected) {
+ options[_i2].defaultSelected = true;
+ }
+ return;
+ }
+ if (defaultSelected === null && !options[_i2].disabled) {
+ defaultSelected = options[_i2];
+ }
+ }
+ if (defaultSelected !== null) {
+ defaultSelected.selected = true;
+ }
+ }
+}
+
+/**
+ * Implements a <select> host component that allows optionally setting the
+ * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
+ * stringable. If `multiple` is true, the prop must be an array of stringables.
+ *
+ * If `value` is not supplied (or null/undefined), user actions that change the
+ * selected option will trigger updates to the rendered options.
+ *
+ * If it is supplied (and not null/undefined), the rendered options will not
+ * update in response to user actions. Instead, the `value` prop must change in
+ * order for the rendered options to update.
+ *
+ * If `defaultValue` is provided, any options with the supplied values will be
+ * selected.
+ */
+
+function getHostProps$2(element, props) {
+ return _assign({}, props, {
+ value: undefined
+ });
+}
+
+function initWrapperState$1(element, props) {
+ var node = element;
+ node._wrapperState = {
+ wasMultiple: !!props.multiple
+ };
+
+
+}
+
+function postMountWrapper$2(element, props) {
+ var node = element;
+ node.multiple = !!props.multiple;
+ var value = props.value;
+ if (value != null) {
+ updateOptions(node, !!props.multiple, value, false);
+ } else if (props.defaultValue != null) {
+ updateOptions(node, !!props.multiple, props.defaultValue, true);
+ }
+}
+
+function postUpdateWrapper(element, props) {
+ var node = element;
+ var wasMultiple = node._wrapperState.wasMultiple;
+ node._wrapperState.wasMultiple = !!props.multiple;
+
+ var value = props.value;
+ if (value != null) {
+ updateOptions(node, !!props.multiple, value, false);
+ } else if (wasMultiple !== !!props.multiple) {
+ // For simplicity, reapply `defaultValue` if `multiple` is toggled.
+ if (props.defaultValue != null) {
+ updateOptions(node, !!props.multiple, props.defaultValue, true);
+ } else {
+ // Revert the select back to its default unselected state.
+ updateOptions(node, !!props.multiple, props.multiple ? [] : '', false);
+ }
+ }
+}
+
+function restoreControlledState$2(element, props) {
+ var node = element;
+ var value = props.value;
+
+ if (value != null) {
+ updateOptions(node, !!props.multiple, value, false);
+ }
+}
+
+/**
+ * Implements a <textarea> host component that allows setting `value`, and
+ * `defaultValue`. This differs from the traditional DOM API because value is
+ * usually set as PCDATA children.
+ *
+ * If `value` is not supplied (or null/undefined), user actions that affect the
+ * value will trigger updates to the element.
+ *
+ * If `value` is supplied (and not null/undefined), the rendered element will
+ * not trigger updates to the element. Instead, the `value` prop must change in
+ * order for the rendered element to be updated.
+ *
+ * The rendered element will be initialized with an empty value, the prop
+ * `defaultValue` if specified, or the children content (deprecated).
+ */
+
+function getHostProps$3(element, props) {
+ var node = element;
+ !(props.dangerouslySetInnerHTML == null) ? reactProdInvariant('91') : void 0;
+
+ // Always set children to the same thing. In IE9, the selection range will
+ // get reset if `textContent` is mutated. We could add a check in setTextContent
+ // to only set the value if/when the value differs from the node value (which would
+ // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this
+ // solution. The value can be a boolean or object so that's why it's forced
+ // to be a string.
+ var hostProps = _assign({}, props, {
+ value: undefined,
+ defaultValue: undefined,
+ children: toString(node._wrapperState.initialValue)
+ });
+
+ return hostProps;
+}
+
+function initWrapperState$2(element, props) {
+ var node = element;
+ var initialValue = props.value;
+
+ // Only bother fetching default value if we're going to use it
+ if (initialValue == null) {
+ var defaultValue = props.defaultValue;
+ // TODO (yungsters): Remove support for children content in <textarea>.
+ var children = props.children;
+ if (children != null) {
+ !(defaultValue == null) ? reactProdInvariant('92') : void 0;
+ if (Array.isArray(children)) {
+ !(children.length <= 1) ? reactProdInvariant('93') : void 0;
+ children = children[0];
+ }
+
+ defaultValue = children;
+ }
+ if (defaultValue == null) {
+ defaultValue = '';
+ }
+ initialValue = defaultValue;
+ }
+
+ node._wrapperState = {
+ initialValue: getToStringValue(initialValue)
+ };
+}
+
+function updateWrapper$1(element, props) {
+ var node = element;
+ var value = getToStringValue(props.value);
+ var defaultValue = getToStringValue(props.defaultValue);
+ if (value != null) {
+ // Cast `value` to a string to ensure the value is set correctly. While
+ // browsers typically do this as necessary, jsdom doesn't.
+ var newValue = toString(value);
+ // To avoid side effects (such as losing text selection), only set value if changed
+ if (newValue !== node.value) {
+ node.value = newValue;
+ }
+ if (props.defaultValue == null && node.defaultValue !== newValue) {
+ node.defaultValue = newValue;
+ }
+ }
+ if (defaultValue != null) {
+ node.defaultValue = toString(defaultValue);
+ }
+}
+
+function postMountWrapper$3(element, props) {
+ var node = element;
+ // This is in postMount because we need access to the DOM node, which is not
+ // available until after the component has mounted.
+ var textContent = node.textContent;
+
+ // Only set node.value if textContent is equal to the expected
+ // initial value. In IE10/IE11 there is a bug where the placeholder attribute
+ // will populate textContent as well.
+ // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
+ if (textContent === node._wrapperState.initialValue) {
+ node.value = textContent;
+ }
+}
+
+function restoreControlledState$3(element, props) {
+ // DOM component is still mounted; update
+ updateWrapper$1(element, props);
+}
+
+var HTML_NAMESPACE$1 = 'http://www.w3.org/1999/xhtml';
+var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
+var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
+
+var Namespaces = {
+ html: HTML_NAMESPACE$1,
+ mathml: MATH_NAMESPACE,
+ svg: SVG_NAMESPACE
+};
+
+// Assumes there is no parent namespace.
+function getIntrinsicNamespace(type) {
+ switch (type) {
+ case 'svg':
+ return SVG_NAMESPACE;
+ case 'math':
+ return MATH_NAMESPACE;
+ default:
+ return HTML_NAMESPACE$1;
+ }
+}
+
+function getChildNamespace(parentNamespace, type) {
+ if (parentNamespace == null || parentNamespace === HTML_NAMESPACE$1) {
+ // No (or default) parent namespace: potential entry point.
+ return getIntrinsicNamespace(type);
+ }
+ if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') {
+ // We're leaving SVG.
+ return HTML_NAMESPACE$1;
+ }
+ // By default, pass namespace below.
+ return parentNamespace;
+}
+
+/* globals MSApp */
+
+/**
+ * Create a function which has 'unsafe' privileges (required by windows8 apps)
+ */
+var createMicrosoftUnsafeLocalFunction = function (func) {
+ if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
+ return function (arg0, arg1, arg2, arg3) {
+ MSApp.execUnsafeLocalFunction(function () {
+ return func(arg0, arg1, arg2, arg3);
+ });
+ };
+ } else {
+ return func;
+ }
+};
+
+// SVG temp container for IE lacking innerHTML
+var reusableSVGContainer = void 0;
+
+/**
+ * Set the innerHTML property of a node
+ *
+ * @param {DOMElement} node
+ * @param {string} html
+ * @internal
+ */
+var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
+ // IE does not have innerHTML for SVG nodes, so instead we inject the
+ // new markup in a temp node and then move the child nodes across into
+ // the target node
+
+ if (node.namespaceURI === Namespaces.svg && !('innerHTML' in node)) {
+ reusableSVGContainer = reusableSVGContainer || document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
+ var svgNode = reusableSVGContainer.firstChild;
+ while (node.firstChild) {
+ node.removeChild(node.firstChild);
+ }
+ while (svgNode.firstChild) {
+ node.appendChild(svgNode.firstChild);
+ }
+ } else {
+ node.innerHTML = html;
+ }
+});
+
+/**
+ * Set the textContent property of a node. For text updates, it's faster
+ * to set the `nodeValue` of the Text node directly instead of using
+ * `.textContent` which will remove the existing node and create a new one.
+ *
+ * @param {DOMElement} node
+ * @param {string} text
+ * @internal
+ */
+var setTextContent = function (node, text) {
+ if (text) {
+ var firstChild = node.firstChild;
+
+ if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) {
+ firstChild.nodeValue = text;
+ return;
+ }
+ }
+ node.textContent = text;
+};
+
+// List derived from Gecko source code:
+// https://github.com/mozilla/gecko-dev/blob/4e638efc71/layout/style/test/property_database.js
+
+/**
+ * CSS properties which accept numbers but are not in units of "px".
+ */
+var isUnitlessNumber = {
+ animationIterationCount: true,
+ borderImageOutset: true,
+ borderImageSlice: true,
+ borderImageWidth: true,
+ boxFlex: true,
+ boxFlexGroup: true,
+ boxOrdinalGroup: true,
+ columnCount: true,
+ columns: true,
+ flex: true,
+ flexGrow: true,
+ flexPositive: true,
+ flexShrink: true,
+ flexNegative: true,
+ flexOrder: true,
+ gridArea: true,
+ gridRow: true,
+ gridRowEnd: true,
+ gridRowSpan: true,
+ gridRowStart: true,
+ gridColumn: true,
+ gridColumnEnd: true,
+ gridColumnSpan: true,
+ gridColumnStart: true,
+ fontWeight: true,
+ lineClamp: true,
+ lineHeight: true,
+ opacity: true,
+ order: true,
+ orphans: true,
+ tabSize: true,
+ widows: true,
+ zIndex: true,
+ zoom: true,
+
+ // SVG-related properties
+ fillOpacity: true,
+ floodOpacity: true,
+ stopOpacity: true,
+ strokeDasharray: true,
+ strokeDashoffset: true,
+ strokeMiterlimit: true,
+ strokeOpacity: true,
+ strokeWidth: true
+};
+
+/**
+ * @param {string} prefix vendor-specific prefix, eg: Webkit
+ * @param {string} key style name, eg: transitionDuration
+ * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
+ * WebkitTransitionDuration
+ */
+function prefixKey(prefix, key) {
+ return prefix + key.charAt(0).toUpperCase() + key.substring(1);
+}
+
+/**
+ * Support style names that may come passed in prefixed by adding permutations
+ * of vendor prefixes.
+ */
+var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
+
+// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
+// infinite loop, because it iterates over the newly added props too.
+Object.keys(isUnitlessNumber).forEach(function (prop) {
+ prefixes.forEach(function (prefix) {
+ isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
+ });
+});
+
+/**
+ * Convert a value into the proper css writable value. The style name `name`
+ * should be logical (no hyphens), as specified
+ * in `CSSProperty.isUnitlessNumber`.
+ *
+ * @param {string} name CSS property name such as `topMargin`.
+ * @param {*} value CSS property value such as `10px`.
+ * @return {string} Normalized style value with dimensions applied.
+ */
+function dangerousStyleValue(name, value, isCustomProperty) {
+ // Note that we've removed escapeTextForBrowser() calls here since the
+ // whole string will be escaped when the attribute is injected into
+ // the markup. If you provide unsafe user data here they can inject
+ // arbitrary CSS which may be problematic (I couldn't repro this):
+ // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
+ // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
+ // This is not an XSS hole but instead a potential CSS injection issue
+ // which has lead to a greater discussion about how we're going to
+ // trust URLs moving forward. See #2115901
+
+ var isEmpty = value == null || typeof value === 'boolean' || value === '';
+ if (isEmpty) {
+ return '';
+ }
+
+ if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) {
+ return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
+ }
+
+ return ('' + value).trim();
+}
+
+/**
+ * Operations for dealing with CSS properties.
+ */
+
+/**
+ * This creates a string that is expected to be equivalent to the style
+ * attribute generated by server-side rendering. It by-passes warnings and
+ * security checks so it's not safe to use this value for anything other than
+ * comparison. It is only used in DEV for SSR validation.
+ */
+
+
+/**
+ * Sets the value for multiple styles on a node. If a value is specified as
+ * '' (empty string), the corresponding style property will be unset.
+ *
+ * @param {DOMElement} node
+ * @param {object} styles
+ */
+function setValueForStyles(node, styles) {
+ var style = node.style;
+ for (var styleName in styles) {
+ if (!styles.hasOwnProperty(styleName)) {
+ continue;
+ }
+ var isCustomProperty = styleName.indexOf('--') === 0;
+ var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty);
+ if (styleName === 'float') {
+ styleName = 'cssFloat';
+ }
+ if (isCustomProperty) {
+ style.setProperty(styleName, styleValue);
+ } else {
+ style[styleName] = styleValue;
+ }
+ }
+}
+
+/**
+ * When mixing shorthand and longhand property names, we warn during updates if
+ * we expect an incorrect result to occur. In particular, we warn for:
+ *
+ * Updating a shorthand property (longhand gets overwritten):
+ * {font: 'foo', fontVariant: 'bar'} -> {font: 'baz', fontVariant: 'bar'}
+ * becomes .style.font = 'baz'
+ * Removing a shorthand property (longhand gets lost too):
+ * {font: 'foo', fontVariant: 'bar'} -> {fontVariant: 'bar'}
+ * becomes .style.font = ''
+ * Removing a longhand property (should revert to shorthand; doesn't):
+ * {font: 'foo', fontVariant: 'bar'} -> {font: 'foo'}
+ * becomes .style.fontVariant = ''
+ */
+
+// For HTML, certain tags should omit their close tag. We keep a whitelist for
+// those special-case tags.
+
+var omittedCloseTags = {
+ area: true,
+ base: true,
+ br: true,
+ col: true,
+ embed: true,
+ hr: true,
+ img: true,
+ input: true,
+ keygen: true,
+ link: true,
+ meta: true,
+ param: true,
+ source: true,
+ track: true,
+ wbr: true
+ // NOTE: menuitem's close tag should be omitted, but that causes problems.
+};
+
+// For HTML, certain tags cannot have children. This has the same purpose as
+// `omittedCloseTags` except that `menuitem` should still have its closing tag.
+
+var voidElementTags = _assign({
+ menuitem: true
+}, omittedCloseTags);
+
+// TODO: We can remove this if we add invariantWithStack()
+// or add stack by default to invariants where possible.
+var HTML$1 = '__html';
+
+function assertValidProps(tag, props) {
+ if (!props) {
+ return;
+ }
+ // Note the use of `==` which checks for null or undefined.
+ if (voidElementTags[tag]) {
+ !(props.children == null && props.dangerouslySetInnerHTML == null) ? reactProdInvariant('137', tag, '') : void 0;
+ }
+ if (props.dangerouslySetInnerHTML != null) {
+ !(props.children == null) ? reactProdInvariant('60') : void 0;
+ !(typeof props.dangerouslySetInnerHTML === 'object' && HTML$1 in props.dangerouslySetInnerHTML) ? reactProdInvariant('61') : void 0;
+ }
+ !(props.style == null || typeof props.style === 'object') ? reactProdInvariant('62', '') : void 0;
+}
+
+function isCustomComponent(tagName, props) {
+ if (tagName.indexOf('-') === -1) {
+ return typeof props.is === 'string';
+ }
+ switch (tagName) {
+ // These are reserved SVG and MathML elements.
+ // We don't mind this whitelist too much because we expect it to never grow.
+ // The alternative is to track the namespace in a few places which is convoluted.
+ // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
+ case 'annotation-xml':
+ case 'color-profile':
+ case 'font-face':
+ case 'font-face-src':
+ case 'font-face-uri':
+ case 'font-face-format':
+ case 'font-face-name':
+ case 'missing-glyph':
+ return false;
+ default:
+ return true;
+ }
+}
+
+// When adding attributes to the HTML or SVG whitelist, be sure to
+// also add them to this module to ensure casing and incorrect name
+// warnings.
+
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
+var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
+var SUPPRESS_HYDRATION_WARNING$1 = 'suppressHydrationWarning';
+var AUTOFOCUS = 'autoFocus';
+var CHILDREN = 'children';
+var STYLE$1 = 'style';
+var HTML = '__html';
+
+var HTML_NAMESPACE = Namespaces.html;
+
+
+function ensureListeningTo(rootContainerElement, registrationName) {
+ var isDocumentOrFragment = rootContainerElement.nodeType === DOCUMENT_NODE || rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE;
+ var doc = isDocumentOrFragment ? rootContainerElement : rootContainerElement.ownerDocument;
+ listenTo(registrationName, doc);
+}
+
+function getOwnerDocumentFromRootContainer(rootContainerElement) {
+ return rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument;
+}
+
+function noop() {}
+
+function trapClickOnNonInteractiveElement(node) {
+ // Mobile Safari does not fire properly bubble click events on
+ // non-interactive elements, which means delegated click listeners do not
+ // fire. The workaround for this bug involves attaching an empty click
+ // listener on the target node.
+ // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
+ // Just set it using the onclick property so that we don't have to manage any
+ // bookkeeping for it. Not sure if we need to clear it when the listener is
+ // removed.
+ // TODO: Only do this for the relevant Safaris maybe?
+ node.onclick = noop;
+}
+
+function setInitialDOMProperties(tag, domElement, rootContainerElement, nextProps, isCustomComponentTag) {
+ for (var propKey in nextProps) {
+ if (!nextProps.hasOwnProperty(propKey)) {
+ continue;
+ }
+ var nextProp = nextProps[propKey];
+ if (propKey === STYLE$1) {
+ setValueForStyles(domElement, nextProp);
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
+ var nextHtml = nextProp ? nextProp[HTML] : undefined;
+ if (nextHtml != null) {
+ setInnerHTML(domElement, nextHtml);
+ }
+ } else if (propKey === CHILDREN) {
+ if (typeof nextProp === 'string') {
+ // Avoid setting initial textContent when the text is empty. In IE11 setting
+ // textContent on a <textarea> will cause the placeholder to not
+ // show within the <textarea> until it has been focused and blurred again.
+ // https://github.com/facebook/react/issues/6731#issuecomment-254874553
+ var canSetTextContent = tag !== 'textarea' || nextProp !== '';
+ if (canSetTextContent) {
+ setTextContent(domElement, nextProp);
+ }
+ } else if (typeof nextProp === 'number') {
+ setTextContent(domElement, '' + nextProp);
+ }
+ } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
+ // Noop
+ } else if (propKey === AUTOFOCUS) {
+ // We polyfill it separately on the client during commit.
+ // We could have excluded it in the property list instead of
+ // adding a special case here, but then it wouldn't be emitted
+ // on server rendering (but we *do* want to emit it in SSR).
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
+ if (nextProp != null) {
+ ensureListeningTo(rootContainerElement, propKey);
+ }
+ } else if (nextProp != null) {
+ setValueForProperty(domElement, propKey, nextProp, isCustomComponentTag);
+ }
+ }
+}
+
+function updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag) {
+ // TODO: Handle wasCustomComponentTag
+ for (var i = 0; i < updatePayload.length; i += 2) {
+ var propKey = updatePayload[i];
+ var propValue = updatePayload[i + 1];
+ if (propKey === STYLE$1) {
+ setValueForStyles(domElement, propValue);
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
+ setInnerHTML(domElement, propValue);
+ } else if (propKey === CHILDREN) {
+ setTextContent(domElement, propValue);
+ } else {
+ setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);
+ }
+ }
+}
+
+function createElement(type, props, rootContainerElement, parentNamespace) {
+ var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement);
+ var domElement = void 0;
+ var namespaceURI = parentNamespace;
+ if (namespaceURI === HTML_NAMESPACE) {
+ namespaceURI = getIntrinsicNamespace(type);
+ }
+ if (namespaceURI === HTML_NAMESPACE) {
+ if (type === 'script') {
+ // Create the script via .innerHTML so its "parser-inserted" flag is
+ // set to true and it does not execute
+ var div = ownerDocument.createElementNS('http://www.w3.org/1999/xhtml', 'div');
+ div.innerHTML = '<script><' + '/script>'; // eslint-disable-line
+ // This is guaranteed to yield a script element.
+ var firstChild = div.firstChild;
+ domElement = div.removeChild(firstChild);
+ } else if (typeof props.is === 'string') {
+ // $FlowIssue `createElement` should be updated for Web Components
+ domElement = ownerDocument.createElementNS('http://www.w3.org/1999/xhtml', type, { is: props.is });
+ } else {
+ // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
+ // See discussion in https://github.com/facebook/react/pull/6896
+ // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
+ domElement = ownerDocument.createElementNS('http://www.w3.org/1999/xhtml', type);
+ // Normally attributes are assigned in `setInitialDOMProperties`, however the `multiple` and `size`
+ // attributes on `select`s needs to be added before `option`s are inserted.
+ // This prevents:
+ // - a bug where the `select` does not scroll to the correct option because singular
+ // `select` elements automatically pick the first item #13222
+ // - a bug where the `select` set the first item as selected despite the `size` attribute #14239
+ // See https://github.com/facebook/react/issues/13222
+ // and https://github.com/facebook/react/issues/14239
+ if (type === 'select') {
+ var node = domElement;
+ if (props.multiple) {
+ node.multiple = true;
+ } else if (props.size) {
+ // Setting a size greater than 1 causes a select to behave like `multiple=true`, where
+ // it is possible that no option is selected.
+ //
+ // This is only necessary when a select in "single selection mode".
+ node.size = props.size;
+ }
+ }
+ }
+ } else {
+ domElement = ownerDocument.createElementNS(namespaceURI, type);
+ }
+
+ return domElement;
+}
+
+function createTextNode(text, rootContainerElement) {
+ return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(text);
+}
+
+function setInitialProperties(domElement, tag, rawProps, rootContainerElement) {
+ var isCustomComponentTag = isCustomComponent(tag, rawProps);
+ var props = void 0;
+ switch (tag) {
+ case 'iframe':
+ case 'object':
+ trapBubbledEvent(TOP_LOAD, domElement);
+ props = rawProps;
+ break;
+ case 'video':
+ case 'audio':
+ // Create listener for each media event
+ for (var i = 0; i < mediaEventTypes.length; i++) {
+ trapBubbledEvent(mediaEventTypes[i], domElement);
+ }
+ props = rawProps;
+ break;
+ case 'source':
+ trapBubbledEvent(TOP_ERROR, domElement);
+ props = rawProps;
+ break;
+ case 'img':
+ case 'image':
+ case 'link':
+ trapBubbledEvent(TOP_ERROR, domElement);
+ trapBubbledEvent(TOP_LOAD, domElement);
+ props = rawProps;
+ break;
+ case 'form':
+ trapBubbledEvent(TOP_RESET, domElement);
+ trapBubbledEvent(TOP_SUBMIT, domElement);
+ props = rawProps;
+ break;
+ case 'details':
+ trapBubbledEvent(TOP_TOGGLE, domElement);
+ props = rawProps;
+ break;
+ case 'input':
+ initWrapperState(domElement, rawProps);
+ props = getHostProps(domElement, rawProps);
+ trapBubbledEvent(TOP_INVALID, domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ case 'option':
+
+ props = getHostProps$1(domElement, rawProps);
+ break;
+ case 'select':
+ initWrapperState$1(domElement, rawProps);
+ props = getHostProps$2(domElement, rawProps);
+ trapBubbledEvent(TOP_INVALID, domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ case 'textarea':
+ initWrapperState$2(domElement, rawProps);
+ props = getHostProps$3(domElement, rawProps);
+ trapBubbledEvent(TOP_INVALID, domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ default:
+ props = rawProps;
+ }
+
+ assertValidProps(tag, props);
+
+ setInitialDOMProperties(tag, domElement, rootContainerElement, props, isCustomComponentTag);
+
+ switch (tag) {
+ case 'input':
+ // TODO: Make sure we check if this is still unmounted or do any clean
+ // up necessary since we never stop tracking anymore.
+ track(domElement);
+ postMountWrapper(domElement, rawProps, false);
+ break;
+ case 'textarea':
+ // TODO: Make sure we check if this is still unmounted or do any clean
+ // up necessary since we never stop tracking anymore.
+ track(domElement);
+ postMountWrapper$3(domElement, rawProps);
+ break;
+ case 'option':
+ postMountWrapper$1(domElement, rawProps);
+ break;
+ case 'select':
+ postMountWrapper$2(domElement, rawProps);
+ break;
+ default:
+ if (typeof props.onClick === 'function') {
+ // TODO: This cast may not be sound for SVG, MathML or custom elements.
+ trapClickOnNonInteractiveElement(domElement);
+ }
+ break;
+ }
+}
+
+// Calculate the diff between the two objects.
+function diffProperties(domElement, tag, lastRawProps, nextRawProps, rootContainerElement) {
+ var updatePayload = null;
+
+ var lastProps = void 0;
+ var nextProps = void 0;
+ switch (tag) {
+ case 'input':
+ lastProps = getHostProps(domElement, lastRawProps);
+ nextProps = getHostProps(domElement, nextRawProps);
+ updatePayload = [];
+ break;
+ case 'option':
+ lastProps = getHostProps$1(domElement, lastRawProps);
+ nextProps = getHostProps$1(domElement, nextRawProps);
+ updatePayload = [];
+ break;
+ case 'select':
+ lastProps = getHostProps$2(domElement, lastRawProps);
+ nextProps = getHostProps$2(domElement, nextRawProps);
+ updatePayload = [];
+ break;
+ case 'textarea':
+ lastProps = getHostProps$3(domElement, lastRawProps);
+ nextProps = getHostProps$3(domElement, nextRawProps);
+ updatePayload = [];
+ break;
+ default:
+ lastProps = lastRawProps;
+ nextProps = nextRawProps;
+ if (typeof lastProps.onClick !== 'function' && typeof nextProps.onClick === 'function') {
+ // TODO: This cast may not be sound for SVG, MathML or custom elements.
+ trapClickOnNonInteractiveElement(domElement);
+ }
+ break;
+ }
+
+ assertValidProps(tag, nextProps);
+
+ var propKey = void 0;
+ var styleName = void 0;
+ var styleUpdates = null;
+ for (propKey in lastProps) {
+ if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
+ continue;
+ }
+ if (propKey === STYLE$1) {
+ var lastStyle = lastProps[propKey];
+ for (styleName in lastStyle) {
+ if (lastStyle.hasOwnProperty(styleName)) {
+ if (!styleUpdates) {
+ styleUpdates = {};
+ }
+ styleUpdates[styleName] = '';
+ }
+ }
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN) {
+ // Noop. This is handled by the clear text mechanism.
+ } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
+ // Noop
+ } else if (propKey === AUTOFOCUS) {
+ // Noop. It doesn't work on updates anyway.
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
+ // This is a special case. If any listener updates we need to ensure
+ // that the "current" fiber pointer gets updated so we need a commit
+ // to update this element.
+ if (!updatePayload) {
+ updatePayload = [];
+ }
+ } else {
+ // For all other deleted properties we add it to the queue. We use
+ // the whitelist in the commit phase instead.
+ (updatePayload = updatePayload || []).push(propKey, null);
+ }
+ }
+ for (propKey in nextProps) {
+ var nextProp = nextProps[propKey];
+ var lastProp = lastProps != null ? lastProps[propKey] : undefined;
+ if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
+ continue;
+ }
+ if (propKey === STYLE$1) {
+ if (lastProp) {
+ // Unset styles on `lastProp` but not on `nextProp`.
+ for (styleName in lastProp) {
+ if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
+ if (!styleUpdates) {
+ styleUpdates = {};
+ }
+ styleUpdates[styleName] = '';
+ }
+ }
+ // Update styles that changed since `lastProp`.
+ for (styleName in nextProp) {
+ if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
+ if (!styleUpdates) {
+ styleUpdates = {};
+ }
+ styleUpdates[styleName] = nextProp[styleName];
+ }
+ }
+ } else {
+ // Relies on `updateStylesByID` not mutating `styleUpdates`.
+ if (!styleUpdates) {
+ if (!updatePayload) {
+ updatePayload = [];
+ }
+ updatePayload.push(propKey, styleUpdates);
+ }
+ styleUpdates = nextProp;
+ }
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
+ var nextHtml = nextProp ? nextProp[HTML] : undefined;
+ var lastHtml = lastProp ? lastProp[HTML] : undefined;
+ if (nextHtml != null) {
+ if (lastHtml !== nextHtml) {
+ (updatePayload = updatePayload || []).push(propKey, '' + nextHtml);
+ }
+ } else {
+ // TODO: It might be too late to clear this if we have children
+ // inserted already.
+ }
+ } else if (propKey === CHILDREN) {
+ if (lastProp !== nextProp && (typeof nextProp === 'string' || typeof nextProp === 'number')) {
+ (updatePayload = updatePayload || []).push(propKey, '' + nextProp);
+ }
+ } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
+ // Noop
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
+ if (nextProp != null) {
+ // We eagerly listen to this even though we haven't committed yet.
+ ensureListeningTo(rootContainerElement, propKey);
+ }
+ if (!updatePayload && lastProp !== nextProp) {
+ // This is a special case. If any listener updates we need to ensure
+ // that the "current" props pointer gets updated so we need a commit
+ // to update this element.
+ updatePayload = [];
+ }
+ } else {
+ // For any other property we always add it to the queue and then we
+ // filter it out using the whitelist during the commit.
+ (updatePayload = updatePayload || []).push(propKey, nextProp);
+ }
+ }
+ if (styleUpdates) {
+ (updatePayload = updatePayload || []).push(STYLE$1, styleUpdates);
+ }
+ return updatePayload;
+}
+
+// Apply the diff.
+function updateProperties(domElement, updatePayload, tag, lastRawProps, nextRawProps) {
+ // Update checked *before* name.
+ // In the middle of an update, it is possible to have multiple checked.
+ // When a checked radio tries to change name, browser makes another radio's checked false.
+ if (tag === 'input' && nextRawProps.type === 'radio' && nextRawProps.name != null) {
+ updateChecked(domElement, nextRawProps);
+ }
+
+ var wasCustomComponentTag = isCustomComponent(tag, lastRawProps);
+ var isCustomComponentTag = isCustomComponent(tag, nextRawProps);
+ // Apply the diff.
+ updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag);
+
+ // TODO: Ensure that an update gets scheduled if any of the special props
+ // changed.
+ switch (tag) {
+ case 'input':
+ // Update the wrapper around inputs *after* updating props. This has to
+ // happen after `updateDOMProperties`. Otherwise HTML5 input validations
+ // raise warnings and prevent the new value from being assigned.
+ updateWrapper(domElement, nextRawProps);
+ break;
+ case 'textarea':
+ updateWrapper$1(domElement, nextRawProps);
+ break;
+ case 'select':
+ // <select> value update needs to occur after <option> children
+ // reconciliation
+ postUpdateWrapper(domElement, nextRawProps);
+ break;
+ }
+}
+
+function diffHydratedProperties(domElement, tag, rawProps, parentNamespace, rootContainerElement) {
+ var isCustomComponentTag = void 0;
+ switch (tag) {
+ case 'iframe':
+ case 'object':
+ trapBubbledEvent(TOP_LOAD, domElement);
+ break;
+ case 'video':
+ case 'audio':
+ // Create listener for each media event
+ for (var i = 0; i < mediaEventTypes.length; i++) {
+ trapBubbledEvent(mediaEventTypes[i], domElement);
+ }
+ break;
+ case 'source':
+ trapBubbledEvent(TOP_ERROR, domElement);
+ break;
+ case 'img':
+ case 'image':
+ case 'link':
+ trapBubbledEvent(TOP_ERROR, domElement);
+ trapBubbledEvent(TOP_LOAD, domElement);
+ break;
+ case 'form':
+ trapBubbledEvent(TOP_RESET, domElement);
+ trapBubbledEvent(TOP_SUBMIT, domElement);
+ break;
+ case 'details':
+ trapBubbledEvent(TOP_TOGGLE, domElement);
+ break;
+ case 'input':
+ initWrapperState(domElement, rawProps);
+ trapBubbledEvent(TOP_INVALID, domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ case 'option':
+
+ break;
+ case 'select':
+ initWrapperState$1(domElement, rawProps);
+ trapBubbledEvent(TOP_INVALID, domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ case 'textarea':
+ initWrapperState$2(domElement, rawProps);
+ trapBubbledEvent(TOP_INVALID, domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ }
+
+ assertValidProps(tag, rawProps);
+
+ var updatePayload = null;
+ for (var propKey in rawProps) {
+ if (!rawProps.hasOwnProperty(propKey)) {
+ continue;
+ }
+ var nextProp = rawProps[propKey];
+ if (propKey === CHILDREN) {
+ // For text content children we compare against textContent. This
+ // might match additional HTML that is hidden when we read it using
+ // textContent. E.g. "foo" will match "f<span>oo</span>" but that still
+ // satisfies our requirement. Our requirement is not to produce perfect
+ // HTML and attributes. Ideally we should preserve structure but it's
+ // ok not to if the visible content is still enough to indicate what
+ // even listeners these nodes might be wired up to.
+ // TODO: Warn if there is more than a single textNode as a child.
+ // TODO: Should we use domElement.firstChild.nodeValue to compare?
+ if (typeof nextProp === 'string') {
+ if (domElement.textContent !== nextProp) {
+ updatePayload = [CHILDREN, nextProp];
+ }
+ } else if (typeof nextProp === 'number') {
+ if (domElement.textContent !== '' + nextProp) {
+ updatePayload = [CHILDREN, '' + nextProp];
+ }
+ }
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
+ if (nextProp != null) {
+ ensureListeningTo(rootContainerElement, propKey);
+ }
+ } else {}
+ }
+
+ switch (tag) {
+ case 'input':
+ // TODO: Make sure we check if this is still unmounted or do any clean
+ // up necessary since we never stop tracking anymore.
+ track(domElement);
+ postMountWrapper(domElement, rawProps, true);
+ break;
+ case 'textarea':
+ // TODO: Make sure we check if this is still unmounted or do any clean
+ // up necessary since we never stop tracking anymore.
+ track(domElement);
+ postMountWrapper$3(domElement, rawProps);
+ break;
+ case 'select':
+ case 'option':
+ // For input and textarea we current always set the value property at
+ // post mount to force it to diverge from attributes. However, for
+ // option and select we don't quite do the same thing and select
+ // is not resilient to the DOM state changing so we don't do that here.
+ // TODO: Consider not doing this for input and textarea.
+ break;
+ default:
+ if (typeof rawProps.onClick === 'function') {
+ // TODO: This cast may not be sound for SVG, MathML or custom elements.
+ trapClickOnNonInteractiveElement(domElement);
+ }
+ break;
+ }
+
+ return updatePayload;
+}
+
+function diffHydratedText(textNode, text) {
+ var isDifferent = textNode.nodeValue !== text;
+ return isDifferent;
+}
+
+
+
+
+
+
+
+
+
+
+
+function restoreControlledState$1(domElement, tag, props) {
+ switch (tag) {
+ case 'input':
+ restoreControlledState(domElement, props);
+ return;
+ case 'textarea':
+ restoreControlledState$3(domElement, props);
+ return;
+ case 'select':
+ restoreControlledState$2(domElement, props);
+ return;
+ }
+}
+
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+
+var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+var _ReactInternals$Sched = ReactInternals$1.Scheduler;
+var unstable_cancelCallback = _ReactInternals$Sched.unstable_cancelCallback;
+var unstable_now = _ReactInternals$Sched.unstable_now;
+var unstable_scheduleCallback = _ReactInternals$Sched.unstable_scheduleCallback;
+var unstable_shouldYield = _ReactInternals$Sched.unstable_shouldYield;
+var unstable_getFirstCallbackNode = _ReactInternals$Sched.unstable_getFirstCallbackNode;
+var unstable_runWithPriority = _ReactInternals$Sched.unstable_runWithPriority;
+var unstable_next = _ReactInternals$Sched.unstable_next;
+var unstable_continueExecution = _ReactInternals$Sched.unstable_continueExecution;
+var unstable_pauseExecution = _ReactInternals$Sched.unstable_pauseExecution;
+var unstable_getCurrentPriorityLevel = _ReactInternals$Sched.unstable_getCurrentPriorityLevel;
+var unstable_ImmediatePriority = _ReactInternals$Sched.unstable_ImmediatePriority;
+var unstable_UserBlockingPriority = _ReactInternals$Sched.unstable_UserBlockingPriority;
+var unstable_NormalPriority = _ReactInternals$Sched.unstable_NormalPriority;
+var unstable_LowPriority = _ReactInternals$Sched.unstable_LowPriority;
+var unstable_IdlePriority = _ReactInternals$Sched.unstable_IdlePriority;
+
+// 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;
+
+var SUSPENSE_START_DATA = '$';
+var SUSPENSE_END_DATA = '/$';
+
+var STYLE = 'style';
+
+var eventsEnabled = null;
+var selectionInformation = null;
+
+function shouldAutoFocusHostComponent(type, props) {
+ switch (type) {
+ case 'button':
+ case 'input':
+ case 'select':
+ case 'textarea':
+ return !!props.autoFocus;
+ }
+ return false;
+}
+
+function getRootHostContext(rootContainerInstance) {
+ var type = void 0;
+ var namespace = void 0;
+ var nodeType = rootContainerInstance.nodeType;
+ switch (nodeType) {
+ case DOCUMENT_NODE:
+ case DOCUMENT_FRAGMENT_NODE:
+ {
+ type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment';
+ var root = rootContainerInstance.documentElement;
+ namespace = root ? root.namespaceURI : getChildNamespace(null, '');
+ break;
+ }
+ default:
+ {
+ var container = nodeType === COMMENT_NODE ? rootContainerInstance.parentNode : rootContainerInstance;
+ var ownNamespace = container.namespaceURI || null;
+ type = container.tagName;
+ namespace = getChildNamespace(ownNamespace, type);
+ break;
+ }
+ }
+ return namespace;
+}
+
+function getChildHostContext(parentHostContext, type, rootContainerInstance) {
+ var parentNamespace = parentHostContext;
+ return getChildNamespace(parentNamespace, type);
+}
+
+function getPublicInstance(instance) {
+ return instance;
+}
+
+function prepareForCommit(containerInfo) {
+ eventsEnabled = isEnabled();
+ selectionInformation = getSelectionInformation();
+ setEnabled(false);
+}
+
+function resetAfterCommit(containerInfo) {
+ restoreSelection(selectionInformation);
+ selectionInformation = null;
+ setEnabled(eventsEnabled);
+ eventsEnabled = null;
+}
+
+function createInstance(type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
+ var parentNamespace = void 0;
+ {
+ parentNamespace = hostContext;
+ }
+ var domElement = createElement(type, props, rootContainerInstance, parentNamespace);
+ precacheFiberNode(internalInstanceHandle, domElement);
+ updateFiberProps(domElement, props);
+ return domElement;
+}
+
+function appendInitialChild(parentInstance, child) {
+ parentInstance.appendChild(child);
+}
+
+function finalizeInitialChildren(domElement, type, props, rootContainerInstance, hostContext) {
+ setInitialProperties(domElement, type, props, rootContainerInstance);
+ return shouldAutoFocusHostComponent(type, props);
+}
+
+function prepareUpdate(domElement, type, oldProps, newProps, rootContainerInstance, hostContext) {
+ return diffProperties(domElement, type, oldProps, newProps, rootContainerInstance);
+}
+
+function shouldSetTextContent(type, props) {
+ return type === 'textarea' || type === 'option' || type === 'noscript' || typeof props.children === 'string' || typeof props.children === 'number' || typeof props.dangerouslySetInnerHTML === 'object' && props.dangerouslySetInnerHTML !== null && props.dangerouslySetInnerHTML.__html != null;
+}
+
+function shouldDeprioritizeSubtree(type, props) {
+ return !!props.hidden;
+}
+
+function createTextInstance(text, rootContainerInstance, hostContext, internalInstanceHandle) {
+ var textNode = createTextNode(text, rootContainerInstance);
+ precacheFiberNode(internalInstanceHandle, textNode);
+ return textNode;
+}
+
+var isPrimaryRenderer = true;
+// This initialization code may run even on server environments
+// if a component just imports ReactDOM (e.g. for findDOMNode).
+// Some environments might not have setTimeout or clearTimeout.
+var scheduleTimeout = typeof setTimeout === 'function' ? setTimeout : undefined;
+var cancelTimeout = typeof clearTimeout === 'function' ? clearTimeout : undefined;
+var noTimeout = -1;
+var schedulePassiveEffects = unstable_scheduleCallback;
+var cancelPassiveEffects = unstable_cancelCallback;
+
+// -------------------
+// Mutation
+// -------------------
+
+var supportsMutation = true;
+
+function commitMount(domElement, type, newProps, internalInstanceHandle) {
+ // Despite the naming that might imply otherwise, this method only
+ // fires if there is an `Update` effect scheduled during mounting.
+ // This happens if `finalizeInitialChildren` returns `true` (which it
+ // does to implement the `autoFocus` attribute on the client). But
+ // there are also other cases when this might happen (such as patching
+ // up text content during hydration mismatch). So we'll check this again.
+ if (shouldAutoFocusHostComponent(type, newProps)) {
+ domElement.focus();
+ }
+}
+
+function commitUpdate(domElement, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
+ // Update the props handle so that we know which props are the ones with
+ // with current event handlers.
+ updateFiberProps(domElement, newProps);
+ // Apply the diff to the DOM node.
+ updateProperties(domElement, updatePayload, type, oldProps, newProps);
+}
+
+function resetTextContent(domElement) {
+ setTextContent(domElement, '');
+}
+
+function commitTextUpdate(textInstance, oldText, newText) {
+ textInstance.nodeValue = newText;
+}
+
+function appendChild(parentInstance, child) {
+ parentInstance.appendChild(child);
+}
+
+function appendChildToContainer(container, child) {
+ var parentNode = void 0;
+ if (container.nodeType === COMMENT_NODE) {
+ parentNode = container.parentNode;
+ parentNode.insertBefore(child, container);
+ } else {
+ parentNode = container;
+ parentNode.appendChild(child);
+ }
+ // This container might be used for a portal.
+ // If something inside a portal is clicked, that click should bubble
+ // through the React tree. However, on Mobile Safari the click would
+ // never bubble through the *DOM* tree unless an ancestor with onclick
+ // event exists. So we wouldn't see it and dispatch it.
+ // This is why we ensure that non React root containers have inline onclick
+ // defined.
+ // https://github.com/facebook/react/issues/11918
+ var reactRootContainer = container._reactRootContainer;
+ if ((reactRootContainer === null || reactRootContainer === undefined) && parentNode.onclick === null) {
+ // TODO: This cast may not be sound for SVG, MathML or custom elements.
+ trapClickOnNonInteractiveElement(parentNode);
+ }
+}
+
+function insertBefore(parentInstance, child, beforeChild) {
+ parentInstance.insertBefore(child, beforeChild);
+}
+
+function insertInContainerBefore(container, child, beforeChild) {
+ if (container.nodeType === COMMENT_NODE) {
+ container.parentNode.insertBefore(child, beforeChild);
+ } else {
+ container.insertBefore(child, beforeChild);
+ }
+}
+
+function removeChild(parentInstance, child) {
+ parentInstance.removeChild(child);
+}
+
+function removeChildFromContainer(container, child) {
+ if (container.nodeType === COMMENT_NODE) {
+ container.parentNode.removeChild(child);
+ } else {
+ container.removeChild(child);
+ }
+}
+
+function clearSuspenseBoundary(parentInstance, suspenseInstance) {
+ var node = suspenseInstance;
+ // Delete all nodes within this suspense boundary.
+ // There might be nested nodes so we need to keep track of how
+ // deep we are and only break out when we're back on top.
+ var depth = 0;
+ do {
+ var nextNode = node.nextSibling;
+ parentInstance.removeChild(node);
+ if (nextNode && nextNode.nodeType === COMMENT_NODE) {
+ var data = nextNode.data;
+ if (data === SUSPENSE_END_DATA) {
+ if (depth === 0) {
+ parentInstance.removeChild(nextNode);
+ return;
+ } else {
+ depth--;
+ }
+ } else if (data === SUSPENSE_START_DATA) {
+ depth++;
+ }
+ }
+ node = nextNode;
+ } while (node);
+ // TODO: Warn, we didn't find the end comment boundary.
+}
+
+function clearSuspenseBoundaryFromContainer(container, suspenseInstance) {
+ if (container.nodeType === COMMENT_NODE) {
+ clearSuspenseBoundary(container.parentNode, suspenseInstance);
+ } else if (container.nodeType === ELEMENT_NODE) {
+ clearSuspenseBoundary(container, suspenseInstance);
+ } else {
+ // Document nodes should never contain suspense boundaries.
+ }
+}
+
+function hideInstance(instance) {
+ // TODO: Does this work for all element types? What about MathML? Should we
+ // pass host context to this method?
+ instance = instance;
+ instance.style.display = 'none';
+}
+
+function hideTextInstance(textInstance) {
+ textInstance.nodeValue = '';
+}
+
+function unhideInstance(instance, props) {
+ instance = instance;
+ var styleProp = props[STYLE];
+ var display = styleProp !== undefined && styleProp !== null && styleProp.hasOwnProperty('display') ? styleProp.display : null;
+ instance.style.display = dangerousStyleValue('display', display);
+}
+
+function unhideTextInstance(textInstance, text) {
+ textInstance.nodeValue = text;
+}
+
+// -------------------
+// Hydration
+// -------------------
+
+var supportsHydration = true;
+
+function canHydrateInstance(instance, type, props) {
+ if (instance.nodeType !== ELEMENT_NODE || type.toLowerCase() !== instance.nodeName.toLowerCase()) {
+ return null;
+ }
+ // This has now been refined to an element node.
+ return instance;
+}
+
+function canHydrateTextInstance(instance, text) {
+ if (text === '' || instance.nodeType !== TEXT_NODE) {
+ // Empty strings are not parsed by HTML so there won't be a correct match here.
+ return null;
+ }
+ // This has now been refined to a text node.
+ return instance;
+}
+
+function canHydrateSuspenseInstance(instance) {
+ if (instance.nodeType !== COMMENT_NODE) {
+ // Empty strings are not parsed by HTML so there won't be a correct match here.
+ return null;
+ }
+ // This has now been refined to a suspense node.
+ return instance;
+}
+
+function getNextHydratableSibling(instance) {
+ var node = instance.nextSibling;
+ // Skip non-hydratable nodes.
+ while (node && node.nodeType !== ELEMENT_NODE && node.nodeType !== TEXT_NODE && (!enableSuspenseServerRenderer || node.nodeType !== COMMENT_NODE || node.data !== SUSPENSE_START_DATA)) {
+ node = node.nextSibling;
+ }
+ return node;
+}
+
+function getFirstHydratableChild(parentInstance) {
+ var next = parentInstance.firstChild;
+ // Skip non-hydratable nodes.
+ while (next && next.nodeType !== ELEMENT_NODE && next.nodeType !== TEXT_NODE && (!enableSuspenseServerRenderer || next.nodeType !== COMMENT_NODE || next.data !== SUSPENSE_START_DATA)) {
+ next = next.nextSibling;
+ }
+ return next;
+}
+
+function hydrateInstance(instance, type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
+ precacheFiberNode(internalInstanceHandle, instance);
+ // TODO: Possibly defer this until the commit phase where all the events
+ // get attached.
+ updateFiberProps(instance, props);
+ var parentNamespace = void 0;
+ {
+ parentNamespace = hostContext;
+ }
+ return diffHydratedProperties(instance, type, props, parentNamespace, rootContainerInstance);
+}
+
+function hydrateTextInstance(textInstance, text, internalInstanceHandle) {
+ precacheFiberNode(internalInstanceHandle, textInstance);
+ return diffHydratedText(textInstance, text);
+}
+
+function getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance) {
+ var node = suspenseInstance.nextSibling;
+ // Skip past all nodes within this suspense boundary.
+ // There might be nested nodes so we need to keep track of how
+ // deep we are and only break out when we're back on top.
+ var depth = 0;
+ while (node) {
+ if (node.nodeType === COMMENT_NODE) {
+ var data = node.data;
+ if (data === SUSPENSE_END_DATA) {
+ if (depth === 0) {
+ return getNextHydratableSibling(node);
+ } else {
+ depth--;
+ }
+ } else if (data === SUSPENSE_START_DATA) {
+ depth++;
+ }
+ }
+ node = node.nextSibling;
+ }
+ // TODO: Warn, we didn't find the end comment boundary.
+ return null;
+}
+
+// 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$2 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+var _ReactInternals$Sched$1 = ReactInternals$2.SchedulerTracing;
+var __interactionsRef = _ReactInternals$Sched$1.__interactionsRef;
+var __subscriberRef = _ReactInternals$Sched$1.__subscriberRef;
+var unstable_clear = _ReactInternals$Sched$1.unstable_clear;
+var unstable_getCurrent = _ReactInternals$Sched$1.unstable_getCurrent;
+var unstable_getThreadID = _ReactInternals$Sched$1.unstable_getThreadID;
+var unstable_subscribe = _ReactInternals$Sched$1.unstable_subscribe;
+var unstable_trace = _ReactInternals$Sched$1.unstable_trace;
+var unstable_unsubscribe = _ReactInternals$Sched$1.unstable_unsubscribe;
+var unstable_wrap = _ReactInternals$Sched$1.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;
+}
+
+/**
+ * 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;
+}
+
+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();
+ 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();
+ 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();
+ 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 = {};
+
+var contextStackCursor$1 = createCursor(NO_CONTEXT);
+var contextFiberStackCursor = createCursor(NO_CONTEXT);
+var rootInstanceStackCursor = createCursor(NO_CONTEXT);
+
+function requiredContext(c) {
+ !(c !== NO_CONTEXT) ? 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, 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();
+
+ 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 = unstable_now();
+}
+
+function startProfilerTimer(fiber) {
+ if (!enableProfilerTimer) {
+ return;
+ }
+
+ profilerStartTime = unstable_now();
+
+ if (fiber.actualStartTime < 0) {
+ fiber.actualStartTime = unstable_now();
+ }
+}
+
+function stopProfilerTimerIfRunning(fiber) {
+ if (!enableProfilerTimer) {
+ return;
+ }
+ profilerStartTime = -1;
+}
+
+function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) {
+ if (!enableProfilerTimer) {
+ return;
+ }
+
+ if (profilerStartTime >= 0) {
+ var elapsedTime = unstable_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$3 = 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$3.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;
+ commitMount(_instance2, type, props, finishedWork);
+ }
+
+ 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
+ resetTextContent(parent);
+ // Clear ContentReset from the effect tag
+ 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$2 = 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;
+}
+
+// Used to ensure computeUniqueAsyncExpiration is monotonically decreasing.
+var lastUniqueAsyncExpiration = Sync - 1;
+
+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() {
+ 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$2.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$2.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();
+
+ 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;
+}
+
+// Creates a unique async expiration time.
+function computeUniqueAsyncExpiration() {
+ var currentTime = requestCurrentTime();
+ var result = computeAsyncExpiration(currentTime);
+ if (result >= lastUniqueAsyncExpiration) {
+ // Since we assume the current time monotonically increases, we only hit
+ // this branch when computeUniqueAsyncExpiration is fired multiple times
+ // within a 200ms window (or whatever the async bucket size is).
+ result = lastUniqueAsyncExpiration - 1;
+ }
+ lastUniqueAsyncExpiration = result;
+ return lastUniqueAsyncExpiration;
+}
+
+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?
+ if (priorityLevel === unstable_UserBlockingPriority && (lowestPriorityPendingInteractiveExpirationTime === NoWork || expirationTime < lowestPriorityPendingInteractiveExpirationTime)) {
+ lowestPriorityPendingInteractiveExpirationTime = expirationTime;
+ }
+
+ 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 lowestPriorityPendingInteractiveExpirationTime = NoWork;
+var hasUnhandledError = false;
+var unhandledError = null;
+
+var isBatchingUpdates = false;
+var isUnbatchingUpdates = false;
+
+var completedBatches = null;
+
+var originalStartTimeMs = unstable_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 = unstable_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.
+ unstable_cancelCallback(callbackID);
+ }
+ }
+ // The request callback timer is already running. Don't start a new one.
+ } else {
+ startRequestCallbackTimer();
+ }
+
+ callbackExpirationTime = expirationTime;
+ var currentMs = unstable_now() - originalStartTimeMs;
+ var expirationTimeMs = expirationTimeToMs(expirationTime);
+ var timeout = expirationTimeMs - currentMs;
+ callbackID = unstable_scheduleCallback(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 (unstable_shouldYield()) {
+ 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$1(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 inside
+// the reconciler.
+function unbatchedUpdates(fn, a) {
+ if (isBatchingUpdates && !isUnbatchingUpdates) {
+ isUnbatchingUpdates = true;
+ try {
+ return fn(a);
+ } finally {
+ isUnbatchingUpdates = false;
+ }
+ }
+ return fn(a);
+}
+
+// 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 interactiveUpdates$1(fn, a, b) {
+ // If there are any pending interactive updates, synchronously flush them.
+ // This needs to happen before we read any handlers, because the effect of
+ // the previous event may influence which handlers are called during
+ // this event.
+ if (!isBatchingUpdates && !isRendering && lowestPriorityPendingInteractiveExpirationTime !== NoWork) {
+ // Synchronously flush pending interactive updates.
+ performWork(lowestPriorityPendingInteractiveExpirationTime, false);
+ lowestPriorityPendingInteractiveExpirationTime = NoWork;
+ }
+ var previousIsBatchingUpdates = isBatchingUpdates;
+ isBatchingUpdates = true;
+ try {
+ return unstable_runWithPriority(unstable_UserBlockingPriority, function () {
+ return fn(a, b);
+ });
+ } finally {
+ isBatchingUpdates = previousIsBatchingUpdates;
+ if (!isBatchingUpdates && !isRendering) {
+ performSyncWork();
+ }
+ }
+}
+
+function flushInteractiveUpdates$1() {
+ if (!isRendering && lowestPriorityPendingInteractiveExpirationTime !== NoWork) {
+ // Synchronously flush pending interactive updates.
+ performWork(lowestPriorityPendingInteractiveExpirationTime, false);
+ lowestPriorityPendingInteractiveExpirationTime = NoWork;
+ }
+}
+
+function flushControlled(fn) {
+ var previousIsBatchingUpdates = isBatchingUpdates;
+ isBatchingUpdates = true;
+ try {
+ syncUpdates(fn);
+ } finally {
+ isBatchingUpdates = previousIsBatchingUpdates;
+ if (!isBatchingUpdates && !isRendering) {
+ 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();
+ 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 findHostInstance(component) {
+ var fiber = get(component);
+ if (fiber === undefined) {
+ if (typeof component.render === 'function') {
+ reactProdInvariant('188');
+ } else {
+ reactProdInvariant('268', Object.keys(component));
+ }
+ }
+ var hostFiber = findCurrentHostFiber(fiber);
+ if (hostFiber === null) {
+ return null;
+ }
+ return hostFiber.stateNode;
+}
+
+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.
+
+function createPortal$1(children, containerInfo,
+// TODO: figure out the API for cross-renderer implementation.
+implementation) {
+ var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
+
+ return {
+ // This tag allow us to uniquely identify this as a React Portal
+ $$typeof: REACT_PORTAL_TYPE,
+ key: key == null ? null : '' + key,
+ children: children,
+ containerInfo: containerInfo,
+ implementation: implementation
+ };
+}
+
+// TODO: this is special because it gets imported during build.
+
+var ReactVersion = '16.8.6';
+
+// TODO: This type is shared between the reconciler and ReactDOM, but will
+// eventually be lifted out to the renderer.
+
+var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
+
+setRestoreImplementation(restoreControlledState$1);
+
+function ReactBatch(root) {
+ var expirationTime = computeUniqueAsyncExpiration();
+ this._expirationTime = expirationTime;
+ this._root = root;
+ this._next = null;
+ this._callbacks = null;
+ this._didComplete = false;
+ this._hasChildren = false;
+ this._children = null;
+ this._defer = true;
+}
+ReactBatch.prototype.render = function (children) {
+ !this._defer ? reactProdInvariant('250') : void 0;
+ this._hasChildren = true;
+ this._children = children;
+ var internalRoot = this._root._internalRoot;
+ var expirationTime = this._expirationTime;
+ var work = new ReactWork();
+ updateContainerAtExpirationTime(children, internalRoot, null, expirationTime, work._onCommit);
+ return work;
+};
+ReactBatch.prototype.then = function (onComplete) {
+ if (this._didComplete) {
+ onComplete();
+ return;
+ }
+ var callbacks = this._callbacks;
+ if (callbacks === null) {
+ callbacks = this._callbacks = [];
+ }
+ callbacks.push(onComplete);
+};
+ReactBatch.prototype.commit = function () {
+ var internalRoot = this._root._internalRoot;
+ var firstBatch = internalRoot.firstBatch;
+ !(this._defer && firstBatch !== null) ? reactProdInvariant('251') : void 0;
+
+ if (!this._hasChildren) {
+ // This batch is empty. Return.
+ this._next = null;
+ this._defer = false;
+ return;
+ }
+
+ var expirationTime = this._expirationTime;
+
+ // Ensure this is the first batch in the list.
+ if (firstBatch !== this) {
+ // This batch is not the earliest batch. We need to move it to the front.
+ // Update its expiration time to be the expiration time of the earliest
+ // batch, so that we can flush it without flushing the other batches.
+ if (this._hasChildren) {
+ expirationTime = this._expirationTime = firstBatch._expirationTime;
+ // Rendering this batch again ensures its children will be the final state
+ // when we flush (updates are processed in insertion order: last
+ // update wins).
+ // TODO: This forces a restart. Should we print a warning?
+ this.render(this._children);
+ }
+
+ // Remove the batch from the list.
+ var previous = null;
+ var batch = firstBatch;
+ while (batch !== this) {
+ previous = batch;
+ batch = batch._next;
+ }
+ !(previous !== null) ? reactProdInvariant('251') : void 0;
+ previous._next = batch._next;
+
+ // Add it to the front.
+ this._next = firstBatch;
+ firstBatch = internalRoot.firstBatch = this;
+ }
+
+ // Synchronously flush all the work up to this batch's expiration time.
+ this._defer = false;
+ flushRoot(internalRoot, expirationTime);
+
+ // Pop the batch from the list.
+ var next = this._next;
+ this._next = null;
+ firstBatch = internalRoot.firstBatch = next;
+
+ // Append the next earliest batch's children to the update queue.
+ if (firstBatch !== null && firstBatch._hasChildren) {
+ firstBatch.render(firstBatch._children);
+ }
+};
+ReactBatch.prototype._onComplete = function () {
+ if (this._didComplete) {
+ return;
+ }
+ this._didComplete = true;
+ var callbacks = this._callbacks;
+ if (callbacks === null) {
+ return;
+ }
+ // TODO: Error handling.
+ for (var i = 0; i < callbacks.length; i++) {
+ var _callback = callbacks[i];
+ _callback();
+ }
+};
+
+function ReactWork() {
+ this._callbacks = null;
+ this._didCommit = false;
+ // TODO: Avoid need to bind by replacing callbacks in the update queue with
+ // list of Work objects.
+ this._onCommit = this._onCommit.bind(this);
+}
+ReactWork.prototype.then = function (onCommit) {
+ if (this._didCommit) {
+ onCommit();
+ return;
+ }
+ var callbacks = this._callbacks;
+ if (callbacks === null) {
+ callbacks = this._callbacks = [];
+ }
+ callbacks.push(onCommit);
+};
+ReactWork.prototype._onCommit = function () {
+ if (this._didCommit) {
+ return;
+ }
+ this._didCommit = true;
+ var callbacks = this._callbacks;
+ if (callbacks === null) {
+ return;
+ }
+ // TODO: Error handling.
+ for (var i = 0; i < callbacks.length; i++) {
+ var _callback2 = callbacks[i];
+ !(typeof _callback2 === 'function') ? reactProdInvariant('191', _callback2) : void 0;
+ _callback2();
+ }
+};
+
+function ReactRoot(container, isConcurrent, hydrate) {
+ var root = createContainer(container, isConcurrent, hydrate);
+ this._internalRoot = root;
+}
+ReactRoot.prototype.render = function (children, callback) {
+ var root = this._internalRoot;
+ var work = new ReactWork();
+ callback = callback === undefined ? null : callback;
+ if (callback !== null) {
+ work.then(callback);
+ }
+ updateContainer(children, root, null, work._onCommit);
+ return work;
+};
+ReactRoot.prototype.unmount = function (callback) {
+ var root = this._internalRoot;
+ var work = new ReactWork();
+ callback = callback === undefined ? null : callback;
+ if (callback !== null) {
+ work.then(callback);
+ }
+ updateContainer(null, root, null, work._onCommit);
+ return work;
+};
+ReactRoot.prototype.legacy_renderSubtreeIntoContainer = function (parentComponent, children, callback) {
+ var root = this._internalRoot;
+ var work = new ReactWork();
+ callback = callback === undefined ? null : callback;
+ if (callback !== null) {
+ work.then(callback);
+ }
+ updateContainer(children, root, parentComponent, work._onCommit);
+ return work;
+};
+ReactRoot.prototype.createBatch = function () {
+ var batch = new ReactBatch(this);
+ var expirationTime = batch._expirationTime;
+
+ var internalRoot = this._internalRoot;
+ var firstBatch = internalRoot.firstBatch;
+ if (firstBatch === null) {
+ internalRoot.firstBatch = batch;
+ batch._next = null;
+ } else {
+ // Insert sorted by expiration time then insertion order
+ var insertAfter = null;
+ var insertBefore = firstBatch;
+ while (insertBefore !== null && insertBefore._expirationTime >= expirationTime) {
+ insertAfter = insertBefore;
+ insertBefore = insertBefore._next;
+ }
+ batch._next = insertBefore;
+ if (insertAfter !== null) {
+ insertAfter._next = batch;
+ }
+ }
+
+ return batch;
+};
+
+/**
+ * True if the supplied DOM node is a valid node element.
+ *
+ * @param {?DOMElement} node The candidate DOM node.
+ * @return {boolean} True if the DOM is a valid DOM node.
+ * @internal
+ */
+function isValidContainer(node) {
+ return !!(node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || node.nodeType === COMMENT_NODE && node.nodeValue === ' react-mount-point-unstable '));
+}
+
+function getReactRootElementInContainer(container) {
+ if (!container) {
+ return null;
+ }
+
+ if (container.nodeType === DOCUMENT_NODE) {
+ return container.documentElement;
+ } else {
+ return container.firstChild;
+ }
+}
+
+function shouldHydrateDueToLegacyHeuristic(container) {
+ var rootElement = getReactRootElementInContainer(container);
+ return !!(rootElement && rootElement.nodeType === ELEMENT_NODE && rootElement.hasAttribute(ROOT_ATTRIBUTE_NAME));
+}
+
+setBatchingImplementation(batchedUpdates$1, interactiveUpdates$1, flushInteractiveUpdates$1);
+
+function legacyCreateRootFromDOMContainer(container, forceHydrate) {
+ var shouldHydrate = forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
+ // First clear any existing content.
+ if (!shouldHydrate) {
+ var rootSibling = void 0;
+ while (rootSibling = container.lastChild) {
+ container.removeChild(rootSibling);
+ }
+ }
+ var isConcurrent = false;
+ return new ReactRoot(container, isConcurrent, shouldHydrate);
+}
+
+function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {
+ var root = container._reactRootContainer;
+ if (!root) {
+ // Initial mount
+ root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate);
+ if (typeof callback === 'function') {
+ var originalCallback = callback;
+ callback = function () {
+ var instance = getPublicRootInstance(root._internalRoot);
+ originalCallback.call(instance);
+ };
+ }
+ // Initial mount should not be batched.
+ unbatchedUpdates(function () {
+ if (parentComponent != null) {
+ root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
+ } else {
+ root.render(children, callback);
+ }
+ });
+ } else {
+ if (typeof callback === 'function') {
+ var _originalCallback = callback;
+ callback = function () {
+ var instance = getPublicRootInstance(root._internalRoot);
+ _originalCallback.call(instance);
+ };
+ }
+ // Update
+ if (parentComponent != null) {
+ root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
+ } else {
+ root.render(children, callback);
+ }
+ }
+ return getPublicRootInstance(root._internalRoot);
+}
+
+function createPortal$$1(children, container) {
+ var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
+
+ !isValidContainer(container) ? reactProdInvariant('200') : void 0;
+ // TODO: pass ReactDOM portal implementation as third argument
+ return createPortal$1(children, container, null, key);
+}
+
+var ReactDOM = {
+ createPortal: createPortal$$1,
+
+ findDOMNode: function (componentOrElement) {
+ if (componentOrElement == null) {
+ return null;
+ }
+ if (componentOrElement.nodeType === ELEMENT_NODE) {
+ return componentOrElement;
+ }
+ return findHostInstance(componentOrElement);
+ },
+ hydrate: function (element, container, callback) {
+ !isValidContainer(container) ? reactProdInvariant('200') : void 0;
+ return legacyRenderSubtreeIntoContainer(null, element, container, true, callback);
+ },
+ render: function (element, container, callback) {
+ !isValidContainer(container) ? reactProdInvariant('200') : void 0;
+ return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
+ },
+ unstable_renderSubtreeIntoContainer: function (parentComponent, element, containerNode, callback) {
+ !isValidContainer(containerNode) ? reactProdInvariant('200') : void 0;
+ !(parentComponent != null && has(parentComponent)) ? reactProdInvariant('38') : void 0;
+ return legacyRenderSubtreeIntoContainer(parentComponent, element, containerNode, false, callback);
+ },
+ unmountComponentAtNode: function (container) {
+ !isValidContainer(container) ? reactProdInvariant('40') : void 0;
+
+ if (container._reactRootContainer) {
+ unbatchedUpdates(function () {
+ legacyRenderSubtreeIntoContainer(null, null, container, false, function () {
+ container._reactRootContainer = null;
+ });
+ });
+ // If you call unmountComponentAtNode twice in quick succession, you'll
+ // get `true` twice. That's probably fine?
+ return true;
+ } else {
+ return false;
+ }
+ },
+
+
+ // Temporary alias since we already shipped React 16 RC with it.
+ // TODO: remove in React 17.
+ unstable_createPortal: function () {
+ return createPortal$$1.apply(undefined, arguments);
+ },
+
+
+ unstable_batchedUpdates: batchedUpdates$1,
+
+ unstable_interactiveUpdates: interactiveUpdates$1,
+
+ flushSync: flushSync,
+
+ unstable_createRoot: createRoot,
+ unstable_flushControlled: flushControlled,
+
+ __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
+ // Keep in sync with ReactDOMUnstableNativeDependencies.js
+ // and ReactTestUtils.js. This is an array for better minification.
+ Events: [getInstanceFromNode$1, getNodeFromInstance$1, getFiberCurrentPropsFromNode$1, injection.injectEventPluginsByName, eventNameDispatchConfigs, accumulateTwoPhaseDispatches, accumulateDirectDispatches, enqueueStateRestore, restoreStateIfNeeded, dispatchEvent, runEventsInBatch]
+ }
+};
+
+function createRoot(container, options) {
+ var functionName = enableStableConcurrentModeAPIs ? 'createRoot' : 'unstable_createRoot';
+ !isValidContainer(container) ? reactProdInvariant('299', functionName) : void 0;
+ var hydrate = options != null && options.hydrate === true;
+ return new ReactRoot(container, true, hydrate);
+}
+
+if (enableStableConcurrentModeAPIs) {
+ ReactDOM.createRoot = createRoot;
+ ReactDOM.unstable_createRoot = undefined;
+}
+
+var foundDevTools = injectIntoDevTools({
+ findFiberByHostInstance: getClosestInstanceFromNode,
+ bundleType: 0,
+ version: ReactVersion,
+ rendererPackageName: 'react-dom'
+});
+
+
+
+var ReactDOM$2 = ({
+ default: ReactDOM
+});
+
+var ReactDOM$3 = ( ReactDOM$2 && ReactDOM ) || ReactDOM$2;
+
+// TODO: decide on the top-level export form.
+// This is hacky but makes it work with both Rollup and Jest.
+var reactDom = ReactDOM$3.default || ReactDOM$3;
+
+return reactDom;
+
+})));