text: /**
   * 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.
   *
   * @noflow
   * @providesModule ReactFabric-dev
   * @preventMunge
   */
  
  'use strict';
  
  if (__DEV__) {
    (function() {
  "use strict";
  
  require("InitializeCore");
  var invariant = require("fbjs/lib/invariant");
  var warning = require("fbjs/lib/warning");
  var emptyFunction = require("fbjs/lib/emptyFunction");
  var RCTEventEmitter = require("RCTEventEmitter");
  var UIManager = require("UIManager");
  var React = require("react");
  var TextInputState = require("TextInputState");
  var deepDiffer = require("deepDiffer");
  var flattenStyle = require("flattenStyle");
  var emptyObject = require("fbjs/lib/emptyObject");
  var checkPropTypes = require("prop-types/checkPropTypes");
  var shallowEqual = require("fbjs/lib/shallowEqual");
  var deepFreezeAndThrowOnMutationInDev = require("deepFreezeAndThrowOnMutationInDev");
  var FabricUIManager = require("FabricUIManager");
  
  var invokeGuardedCallback = function(name, func, context, a, b, c, d, e, f) {
    this._hasCaughtError = false;
    this._caughtError = null;
    var funcArgs = Array.prototype.slice.call(arguments, 3);
    try {
      func.apply(context, funcArgs);
    } catch (error) {
      this._caughtError = error;
      this._hasCaughtError = true;
    }
  };
  
  {
    // In DEV mode, we swap out invokeGuardedCallback for a special version
    // that plays more nicely with the browser's DevTools. The idea is to preserve
    // "Pause on exceptions" behavior. Because React wraps all user-provided
    // functions in invokeGuardedCallback, and the production version of
    // invokeGuardedCallback uses a try-catch, all user exceptions are treated
    // like caught exceptions, and the DevTools won't pause unless the developer
    // takes the extra step of enabling pause on caught exceptions. This is
    // untintuitive, though, because even though React has caught the error, from
    // the developer's perspective, the error is uncaught.
    //
    // To preserve the expected "Pause on exceptions" behavior, we don't use a
    // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake
    // DOM node, and call the user-provided callback from inside an event handler
    // for that fake event. If the callback throws, the error is "captured" using
    // a global event handler. But because the error happens in a different
    // event loop context, it does not interrupt the normal program flow.
    // Effectively, this gives us try-catch behavior without actually using
    // try-catch. Neat!
  
    // Check that the browser supports the APIs we need to implement our special
    // DEV version of invokeGuardedCallback
    if (
      typeof window !== "undefined" &&
      typeof window.dispatchEvent === "function" &&
      typeof document !== "undefined" &&
      typeof document.createEvent === "function"
    ) {
      var fakeNode = document.createElement("react");
  
      var invokeGuardedCallbackDev = function(
        name,
        func,
        context,
        a,
        b,
        c,
        d,
        e,
        f
      ) {
        // If document doesn't exist we know for sure we will crash in this method
        // when we call document.createEvent(). However this can cause confusing
        // errors: https://github.com/facebookincubator/create-react-app/issues/3482
        // So we preemptively throw with a better message instead.
        invariant(
          typeof document !== "undefined",
          "The `document` global was defined when React was initialized, but is not " +
            "defined anymore. This can happen in a test environment if a component " +
            "schedules an update from an asynchronous callback, but the test has already " +
            "finished running. To solve this, you can either unmount the component at " +
            "the end of your test (and ensure that any asynchronous operations get " +
            "canceled in `componentWillUnmount`), or you can change the test itself " +
            "to be asynchronous."
        );
        var evt = document.createEvent("Event");
  
        // Keeps track of whether the user-provided callback threw an error. We
        // set this to true at the beginning, then set it to false right after
        // calling the function. If the function errors, `didError` will never be
        // set to false. This strategy works even if the browser is flaky and
        // fails to call our global error handler, because it doesn't rely on
        // the error event at all.
        var didError = true;
  
        // Create an event handler for our fake event. We will synchronously
        // dispatch our fake event using `dispatchEvent`. Inside the handler, we
        // call the user-provided callback.
        var funcArgs = Array.prototype.slice.call(arguments, 3);
        function callCallback() {
          // We immediately remove the callback from event listeners so that
          // nested `invokeGuardedCallback` calls do not clash. Otherwise, a
          // nested call would trigger the fake event handlers of any call higher
          // in the stack.
          fakeNode.removeEventListener(evtType, callCallback, false);
          func.apply(context, funcArgs);
          didError = false;
        }
  
        // Create a global error event handler. We use this to capture the value
        // that was thrown. It's possible that this error handler will fire more
        // than once; for example, if non-React code also calls `dispatchEvent`
        // and a handler for that event throws. We should be resilient to most of
        // those cases. Even if our error event handler fires more than once, the
        // last error event is always used. If the callback actually does error,
        // we know that the last error event is the correct one, because it's not
        // possible for anything else to have happened in between our callback
        // erroring and the code that follows the `dispatchEvent` call below. If
        // the callback doesn't error, but the error event was fired, we know to
        // ignore it because `didError` will be false, as described above.
        var error = void 0;
        // Use this to track whether the error event is ever called.
        var didSetError = false;
        var isCrossOriginError = false;
  
        function onError(event) {
          error = event.error;
          didSetError = true;
          if (error === null && event.colno === 0 && event.lineno === 0) {
            isCrossOriginError = true;
          }
        }
  
        // Create a fake event type.
        var evtType = "react-" + (name ? name : "invokeguardedcallback");
  
        // Attach our event handlers
        window.addEventListener("error", onError);
        fakeNode.addEventListener(evtType, callCallback, false);
  
        // Synchronously dispatch our fake event. If the user-provided function
        // errors, it will trigger our global error handler.
        evt.initEvent(evtType, false, false);
        fakeNode.dispatchEvent(evt);
  
        if (didError) {
          if (!didSetError) {
            // The callback errored, but the error event never fired.
            error = new Error(
              "An error was thrown inside one of your components, but React " +
                "doesn't know what it was. This is likely due to browser " +
                'flakiness. React does its best to preserve the "Pause on ' +
                'exceptions" behavior of the DevTools, which requires some ' +
                "DEV-mode only tricks. It's possible that these don't work in " +
                "your browser. Try triggering the error in production mode, " +
                "or switching to a modern browser. If you suspect that this is " +
                "actually an issue with React, please file an issue."
            );
          } else if (isCrossOriginError) {
            error = new Error(
              "A cross-origin error was thrown. React doesn't have access to " +
                "the actual error object in development. " +
                "See https://fb.me/react-crossorigin-error for more information."
            );
          }
          this._hasCaughtError = true;
          this._caughtError = error;
        } else {
          this._hasCaughtError = false;
          this._caughtError = null;
        }
  
        // Remove our event listeners
        window.removeEventListener("error", onError);
      };
  
      invokeGuardedCallback = invokeGuardedCallbackDev;
    }
  }
  
  var invokeGuardedCallback$1 = invokeGuardedCallback;
  
  var ReactErrorUtils = {
    // Used by Fiber to simulate a try-catch.
    _caughtError: null,
    _hasCaughtError: false,
  
    // Used by event system to capture/rethrow the first error.
    _rethrowError: null,
    _hasRethrowError: false,
  
    /**
     * 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
     */
    invokeGuardedCallback: function(name, func, context, a, b, c, d, e, f) {
      invokeGuardedCallback$1.apply(ReactErrorUtils, 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
     */
    invokeGuardedCallbackAndCatchFirstError: function(
      name,
      func,
      context,
      a,
      b,
      c,
      d,
      e,
      f
    ) {
      ReactErrorUtils.invokeGuardedCallback.apply(this, arguments);
      if (ReactErrorUtils.hasCaughtError()) {
        var error = ReactErrorUtils.clearCaughtError();
        if (!ReactErrorUtils._hasRethrowError) {
          ReactErrorUtils._hasRethrowError = true;
          ReactErrorUtils._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.
     */
    rethrowCaughtError: function() {
      return rethrowCaughtError.apply(ReactErrorUtils, arguments);
    },
  
    hasCaughtError: function() {
      return ReactErrorUtils._hasCaughtError;
    },
  
    clearCaughtError: function() {
      if (ReactErrorUtils._hasCaughtError) {
        var error = ReactErrorUtils._caughtError;
        ReactErrorUtils._caughtError = null;
        ReactErrorUtils._hasCaughtError = false;
        return error;
      } else {
        invariant(
          false,
          "clearCaughtError was called but no error was captured. This error " +
            "is likely caused by a bug in React. Please file an issue."
        );
      }
    }
  };
  
  var rethrowCaughtError = function() {
    if (ReactErrorUtils._hasRethrowError) {
      var error = ReactErrorUtils._rethrowError;
      ReactErrorUtils._rethrowError = null;
      ReactErrorUtils._hasRethrowError = false;
      throw error;
    }
  };
  
  /**
   * Forked from fbjs/warning:
   * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js
   *
   * Only change is we use console.warn instead of console.error,
   * and do nothing when 'console' is not supported.
   * This really simplifies the code.
   * ---
   * Similar to invariant but only logs a warning if the condition is not met.
   * This can be used to log issues in development environments in critical
   * paths. Removing the logging code for production environments will keep the
   * same logic and follow the same code paths.
   */
  
  var lowPriorityWarning = function() {};
  
  {
    var printWarning = function(format) {
      for (
        var _len = arguments.length,
          args = Array(_len > 1 ? _len - 1 : 0),
          _key = 1;
        _key < _len;
        _key++
      ) {
        args[_key - 1] = arguments[_key];
      }
  
      var argIndex = 0;
      var message =
        "Warning: " +
        format.replace(/%s/g, function() {
          return args[argIndex++];
        });
      if (typeof console !== "undefined") {
        console.warn(message);
      }
      try {
        // --- Welcome to debugging React ---
        // This error was thrown as a convenience so that you can use this stack
        // to find the callsite that caused this warning to fire.
        throw new Error(message);
      } catch (x) {}
    };
  
    lowPriorityWarning = function(condition, format) {
      if (format === undefined) {
        throw new Error(
          "`warning(condition, format, ...args)` requires a warning " +
            "message argument"
        );
      }
      if (!condition) {
        for (
          var _len2 = arguments.length,
            args = Array(_len2 > 2 ? _len2 - 2 : 0),
            _key2 = 2;
          _key2 < _len2;
          _key2++
        ) {
          args[_key2 - 2] = arguments[_key2];
        }
  
        printWarning.apply(undefined, [format].concat(args));
      }
    };
  }
  
  var lowPriorityWarning$1 = lowPriorityWarning;
  
  var shouldWarnOnInjection = false;
  
  /**
   * 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);
      invariant(
        pluginIndex > -1,
        "EventPluginRegistry: Cannot inject event plugins that do not exist in " +
          "the plugin ordering, `%s`.",
        pluginName
      );
      if (plugins[pluginIndex]) {
        continue;
      }
      invariant(
        pluginModule.extractEvents,
        "EventPluginRegistry: Event plugins must implement an `extractEvents` " +
          "method, but `%s` does not.",
        pluginName
      );
      plugins[pluginIndex] = pluginModule;
      var publishedEvents = pluginModule.eventTypes;
      for (var eventName in publishedEvents) {
        invariant(
          publishEventForPlugin(
            publishedEvents[eventName],
            pluginModule,
            eventName
          ),
          "EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.",
          eventName,
          pluginName
        );
      }
    }
  }
  
  /**
   * 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) {
    invariant(
      !eventNameDispatchConfigs.hasOwnProperty(eventName),
      "EventPluginHub: More than one plugin attempted to publish the same " +
        "event name, `%s`.",
      eventName
    );
    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) {
    invariant(
      !registrationNameModules[registrationName],
      "EventPluginHub: More than one plugin attempted to publish the same " +
        "registration name, `%s`.",
      registrationName
    );
    registrationNameModules[registrationName] = pluginModule;
    registrationNameDependencies[registrationName] =
      pluginModule.eventTypes[eventName].dependencies;
  
    {
      var lowerCasedName = registrationName.toLowerCase();
    }
  }
  
  /**
   * 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 true.
   * @type {Object}
   */
  
  // Trust the developer to only use possibleRegistrationNames in true
  
  /**
   * 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) {
    invariant(
      !eventPluginOrder,
      "EventPluginRegistry: Cannot inject event plugin ordering more than " +
        "once. You are likely trying to load more than one copy of React."
    );
    // 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) {
    {
      if (shouldWarnOnInjection) {
        var names = Object.keys(injectedNamesToPlugins).join(", ");
        lowPriorityWarning$1(
          false,
          "Injecting custom event plugins (%s) is deprecated " +
            "and will not work in React 17+. Please update your code " +
            "to not depend on React internals. The stack trace for this " +
            "warning should reveal the library that is using them. " +
            "See https://github.com/facebook/react/issues/11689 for a discussion.",
          names
        );
      }
    }
  
    var isOrderingDirty = false;
    for (var pluginName in injectedNamesToPlugins) {
      if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
        continue;
      }
      var pluginModule = injectedNamesToPlugins[pluginName];
      if (
        !namesToPlugins.hasOwnProperty(pluginName) ||
        namesToPlugins[pluginName] !== pluginModule
      ) {
        invariant(
          !namesToPlugins[pluginName],
          "EventPluginRegistry: Cannot inject two different event plugins " +
            "using the same name, `%s`.",
          pluginName
        );
        namesToPlugins[pluginName] = pluginModule;
        isOrderingDirty = true;
      }
    }
    if (isOrderingDirty) {
      recomputePluginOrdering();
    }
  }
  
  var getFiberCurrentPropsFromNode = null;
  var getInstanceFromNode = null;
  var getNodeFromInstance = null;
  
  var injection$1 = {
    injectComponentTree: function(Injected) {
      getFiberCurrentPropsFromNode = Injected.getFiberCurrentPropsFromNode;
      getInstanceFromNode = Injected.getInstanceFromNode;
      getNodeFromInstance = Injected.getNodeFromInstance;
  
      {
        warning(
          getNodeFromInstance && getInstanceFromNode,
          "EventPluginUtils.injection.injectComponentTree(...): Injected " +
            "module is missing getNodeFromInstance or getInstanceFromNode."
        );
      }
    }
  };
  
  function isEndish(topLevelType) {
    return (
      topLevelType === "topMouseUp" ||
      topLevelType === "topTouchEnd" ||
      topLevelType === "topTouchCancel"
    );
  }
  
  function isMoveish(topLevelType) {
    return topLevelType === "topMouseMove" || topLevelType === "topTouchMove";
  }
  function isStartish(topLevelType) {
    return topLevelType === "topMouseDown" || topLevelType === "topTouchStart";
  }
  
  var validateEventDispatches = void 0;
  {
    validateEventDispatches = function(event) {
      var dispatchListeners = event._dispatchListeners;
      var dispatchInstances = event._dispatchInstances;
  
      var listenersIsArr = Array.isArray(dispatchListeners);
      var listenersLen = listenersIsArr
        ? dispatchListeners.length
        : dispatchListeners ? 1 : 0;
  
      var instancesIsArr = Array.isArray(dispatchInstances);
      var instancesLen = instancesIsArr
        ? dispatchInstances.length
        : dispatchInstances ? 1 : 0;
  
      warning(
        instancesIsArr === listenersIsArr && instancesLen === listenersLen,
        "EventPluginUtils: Invalid `event`."
      );
    };
  }
  
  /**
   * Dispatch the event to the listener.
   * @param {SyntheticEvent} event SyntheticEvent to handle
   * @param {boolean} simulated If the event is simulated (changes exn behavior)
   * @param {function} listener Application-level callback
   * @param {*} inst Internal component instance
   */
  function executeDispatch(event, simulated, listener, inst) {
    var type = event.type || "unknown-event";
    event.currentTarget = getNodeFromInstance(inst);
    ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError(
      type,
      listener,
      undefined,
      event
    );
    event.currentTarget = null;
  }
  
  /**
   * Standard/simple iteration through an event's collected dispatches.
   */
  function executeDispatchesInOrder(event, simulated) {
    var dispatchListeners = event._dispatchListeners;
    var dispatchInstances = event._dispatchInstances;
    {
      validateEventDispatches(event);
    }
    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,
          simulated,
          dispatchListeners[i],
          dispatchInstances[i]
        );
      }
    } else if (dispatchListeners) {
      executeDispatch(event, simulated, dispatchListeners, dispatchInstances);
    }
    event._dispatchListeners = null;
    event._dispatchInstances = null;
  }
  
  /**
   * Standard/simple iteration through an event's collected dispatches, but stops
   * at the first dispatch execution returning true, and returns that id.
   *
   * @return {?string} id of the first dispatch execution who's listener returns
   * true, or null if no listener returned true.
   */
  function executeDispatchesInOrderStopAtTrueImpl(event) {
    var dispatchListeners = event._dispatchListeners;
    var dispatchInstances = event._dispatchInstances;
    {
      validateEventDispatches(event);
    }
    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.
        if (dispatchListeners[i](event, dispatchInstances[i])) {
          return dispatchInstances[i];
        }
      }
    } else if (dispatchListeners) {
      if (dispatchListeners(event, dispatchInstances)) {
        return dispatchInstances;
      }
    }
    return null;
  }
  
  /**
   * @see executeDispatchesInOrderStopAtTrueImpl
   */
  function executeDispatchesInOrderStopAtTrue(event) {
    var ret = executeDispatchesInOrderStopAtTrueImpl(event);
    event._dispatchInstances = null;
    event._dispatchListeners = null;
    return ret;
  }
  
  /**
   * 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.
   */
  function executeDirectDispatch(event) {
    {
      validateEventDispatches(event);
    }
    var dispatchListener = event._dispatchListeners;
    var dispatchInstance = event._dispatchInstances;
    invariant(
      !Array.isArray(dispatchListener),
      "executeDirectDispatch(...): Invalid `event`."
    );
    event.currentTarget = dispatchListener
      ? getNodeFromInstance(dispatchInstance)
      : null;
    var res = dispatchListener ? dispatchListener(event) : null;
    event.currentTarget = null;
    event._dispatchListeners = null;
    event._dispatchInstances = null;
    return res;
  }
  
  /**
   * @param {SyntheticEvent} event
   * @return {boolean} True iff number of dispatches accumulated is greater than 0.
   */
  function hasDispatches(event) {
    return !!event._dispatchListeners;
  }
  
  /**
   * 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) {
    invariant(
      next != null,
      "accumulateInto(...): Accumulated items must not be null or undefined."
    );
  
    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.
   * @param {boolean} simulated If the event is simulated (changes exn behavior)
   * @private
   */
  var executeDispatchesAndRelease = function(event, simulated) {
    if (event) {
      executeDispatchesInOrder(event, simulated);
  
      if (!event.isPersistent()) {
        event.constructor.release(event);
      }
    }
  };
  var executeDispatchesAndReleaseSimulated = function(e) {
    return executeDispatchesAndRelease(e, true);
  };
  var executeDispatchesAndReleaseTopLevel = function(e) {
    return executeDispatchesAndRelease(e, false);
  };
  
  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;
    }
    invariant(
      !listener || typeof listener === "function",
      "Expected `%s` listener to be a function, instead got a value of `%s` type.",
      registrationName,
      typeof listener
    );
    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, simulated) {
    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;
    }
  
    if (simulated) {
      forEachAccumulated(
        processingEventQueue,
        executeDispatchesAndReleaseSimulated
      );
    } else {
      forEachAccumulated(
        processingEventQueue,
        executeDispatchesAndReleaseTopLevel
      );
    }
    invariant(
      !eventQueue,
      "processEventQueue(): Additional events were enqueued while processing " +
        "an event queue. Support for this has not yet been implemented."
    );
    // This would be a good time to rethrow if any of the event handlers threw.
    ReactErrorUtils.rethrowCaughtError();
  }
  
  function runExtractedEventsInBatch(
    topLevelType,
    targetInst,
    nativeEvent,
    nativeEventTarget
  ) {
    var events = extractEvents(
      topLevelType,
      targetInst,
      nativeEvent,
      nativeEventTarget
    );
    runEventsInBatch(events, false);
  }
  
  var IndeterminateComponent = 0; // Before we know whether it is functional or class
  var FunctionalComponent = 1;
  var ClassComponent = 2;
  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 CallComponent = 7;
  var CallHandlerPhase = 8;
  var ReturnComponent = 9;
  var Fragment = 10;
  var Mode = 11;
  var ContextConsumer = 12;
  var ContextProvider = 13;
  
  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.
   */
  function isAncestor(instA, instB) {
    while (instB) {
      if (instA === instB || instA === instB.alternate) {
        return true;
      }
      instB = getParent(instB);
    }
    return false;
  }
  
  /**
   * Return the parent instance of the passed-in instance.
   */
  function getParentInstance(inst) {
    return getParent(inst);
  }
  
  /**
   * 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.
   */
  
  /**
   * 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) {
    {
      warning(inst, "Dispatching inst must not be null");
    }
    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);
    }
  }
  
  /**
   * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
   */
  function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
    if (event && event.dispatchConfig.phasedRegistrationNames) {
      var targetInst = event._targetInst;
      var parentInst = targetInst ? getParentInstance(targetInst) : null;
      traverseTwoPhase(parentInst, 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 accumulateTwoPhaseDispatchesSkipTarget(events) {
    forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
  }
  
  function accumulateDirectDispatches(events) {
    forEachAccumulated(events, accumulateDirectDispatchesSingle);
  }
  
  /* eslint valid-typeof: 0 */
  
  var didWarnForAddedNewProperty = false;
  var EVENT_POOL_SIZE = 10;
  
  var shouldBeReleasedProperties = [
    "dispatchConfig",
    "_targetInst",
    "nativeEvent",
    "isDefaultPrevented",
    "isPropagationStopped",
    "_dispatchListeners",
    "_dispatchInstances"
  ];
  
  /**
   * @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: emptyFunction.thatReturnsNull,
    eventPhase: null,
    bubbles: null,
    cancelable: null,
    timeStamp: function(event) {
      return event.timeStamp || Date.now();
    },
    defaultPrevented: null,
    isTrusted: null
  };
  
  /**
   * 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
  ) {
    {
      // these have a getter/setter for warnings
      delete this.nativeEvent;
      delete this.preventDefault;
      delete this.stopPropagation;
    }
  
    this.dispatchConfig = dispatchConfig;
    this._targetInst = targetInst;
    this.nativeEvent = nativeEvent;
  
    var Interface = this.constructor.Interface;
    for (var propName in Interface) {
      if (!Interface.hasOwnProperty(propName)) {
        continue;
      }
      {
        delete this[propName]; // this has a getter/setter for warnings
      }
      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 = emptyFunction.thatReturnsTrue;
    } else {
      this.isDefaultPrevented = emptyFunction.thatReturnsFalse;
    }
    this.isPropagationStopped = emptyFunction.thatReturnsFalse;
    return this;
  }
  
  Object.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 = emptyFunction.thatReturnsTrue;
    },
  
    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 = emptyFunction.thatReturnsTrue;
    },
  
    /**
     * 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 = emptyFunction.thatReturnsTrue;
    },
  
    /**
     * Checks if this event should be released back into the pool.
     *
     * @return {boolean} True if this should not be released, false otherwise.
     */
    isPersistent: emptyFunction.thatReturnsFalse,
  
    /**
     * `PooledClass` looks for `destructor` on each instance it releases.
     */
    destructor: function() {
      var Interface = this.constructor.Interface;
      for (var propName in Interface) {
        {
          Object.defineProperty(
            this,
            propName,
            getPooledWarningPropertyDefinition(propName, Interface[propName])
          );
        }
      }
      for (var i = 0; i < shouldBeReleasedProperties.length; i++) {
        this[shouldBeReleasedProperties[i]] = null;
      }
      {
        Object.defineProperty(
          this,
          "nativeEvent",
          getPooledWarningPropertyDefinition("nativeEvent", null)
        );
        Object.defineProperty(
          this,
          "preventDefault",
          getPooledWarningPropertyDefinition("preventDefault", emptyFunction)
        );
        Object.defineProperty(
          this,
          "stopPropagation",
          getPooledWarningPropertyDefinition("stopPropagation", emptyFunction)
        );
      }
    }
  });
  
  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);
    }
    Object.assign(prototype, Class.prototype);
    Class.prototype = prototype;
    Class.prototype.constructor = Class;
  
    Class.Interface = Object.assign({}, Super.Interface, Interface);
    Class.extend = Super.extend;
    addEventPoolingTo(Class);
  
    return Class;
  };
  
  /** Proxying after everything set on SyntheticEvent
   * to resolve Proxy issue on some WebKit browsers
   * in which some Event properties are set to undefined (GH#10010)
   */
  {
    var isProxySupported =
      typeof Proxy === "function" &&
      // https://github.com/facebook/react/issues/12011
      !Object.isSealed(new Proxy({}, {}));
  
    if (isProxySupported) {
      /*eslint-disable no-func-assign */
      SyntheticEvent = new Proxy(SyntheticEvent, {
        construct: function(target, args) {
          return this.apply(target, Object.create(target.prototype), args);
        },
        apply: function(constructor, that, args) {
          return new Proxy(constructor.apply(that, args), {
            set: function(target, prop, value) {
              if (
                prop !== "isPersistent" &&
                !target.constructor.Interface.hasOwnProperty(prop) &&
                shouldBeReleasedProperties.indexOf(prop) === -1
              ) {
                warning(
                  didWarnForAddedNewProperty || target.isPersistent(),
                  "This synthetic event is reused for performance reasons. If you're " +
                    "seeing this, you're adding a new property in the synthetic event object. " +
                    "The property is never released. See " +
                    "https://fb.me/react-event-pooling for more information."
                );
                didWarnForAddedNewProperty = true;
              }
              target[prop] = value;
              return true;
            }
          });
        }
      });
      /*eslint-enable no-func-assign */
    }
  }
  
  addEventPoolingTo(SyntheticEvent);
  
  /**
   * Helper to nullify syntheticEvent instance properties when destructing
   *
   * @param {String} propName
   * @param {?object} getVal
   * @return {object} defineProperty object
   */
  function getPooledWarningPropertyDefinition(propName, getVal) {
    var isFunction = typeof getVal === "function";
    return {
      configurable: true,
      set: set,
      get: get
    };
  
    function set(val) {
      var action = isFunction ? "setting the method" : "setting the property";
      warn(action, "This is effectively a no-op");
      return val;
    }
  
    function get() {
      var action = isFunction ? "accessing the method" : "accessing the property";
      var result = isFunction
        ? "This is a no-op function"
        : "This is set to null";
      warn(action, result);
      return getVal;
    }
  
    function warn(action, result) {
      var warningCondition = false;
      warning(
        warningCondition,
        "This synthetic event is reused for performance reasons. If you're seeing this, " +
          "you're %s `%s` on a released/nullified synthetic event. %s. " +
          "If you must keep the original synthetic event around, use event.persist(). " +
          "See https://fb.me/react-event-pooling for more information.",
        action,
        propName,
        result
      );
    }
  }
  
  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;
    invariant(
      event instanceof EventConstructor,
      "Trying to release an event instance  into a pool of a different type."
    );
    event.destructor();
    if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
      EventConstructor.eventPool.push(event);
    }
  }
  
  function addEventPoolingTo(EventConstructor) {
    EventConstructor.eventPool = [];
    EventConstructor.getPooled = getPooledEvent;
    EventConstructor.release = releasePooledEvent;
  }
  
  var SyntheticEvent$1 = SyntheticEvent;
  
  /**
   * `touchHistory` isn't actually on the native event, but putting it in the
   * interface will ensure that it is cleaned up when pooled/destroyed. The
   * `ResponderEventPlugin` will populate it appropriately.
   */
  var ResponderSyntheticEvent = SyntheticEvent$1.extend({
    touchHistory: function(nativeEvent) {
      return null; // Actually doesn't even look at the native event.
    }
  });
  
  /**
   * Tracks the position and time of each active touch by `touch.identifier`. We
   * should typically only see IDs in the range of 1-20 because IDs get recycled
   * when touches end and start again.
   */
  
  var MAX_TOUCH_BANK = 20;
  var touchBank = [];
  var touchHistory = {
    touchBank: touchBank,
    numberActiveTouches: 0,
    // If there is only one active touch, we remember its location. This prevents
    // us having to loop through all of the touches all the time in the most
    // common case.
    indexOfSingleActiveTouch: -1,
    mostRecentTimeStamp: 0
  };
  
  function timestampForTouch(touch) {
    // The legacy internal implementation provides "timeStamp", which has been
    // renamed to "timestamp". Let both work for now while we iron it out
    // TODO (evv): rename timeStamp to timestamp in internal code
    return touch.timeStamp || touch.timestamp;
  }
  
  /**
   * TODO: Instead of making gestures recompute filtered velocity, we could
   * include a built in velocity computation that can be reused globally.
   */
  function createTouchRecord(touch) {
    return {
      touchActive: true,
      startPageX: touch.pageX,
      startPageY: touch.pageY,
      startTimeStamp: timestampForTouch(touch),
      currentPageX: touch.pageX,
      currentPageY: touch.pageY,
      currentTimeStamp: timestampForTouch(touch),
      previousPageX: touch.pageX,
      previousPageY: touch.pageY,
      previousTimeStamp: timestampForTouch(touch)
    };
  }
  
  function resetTouchRecord(touchRecord, touch) {
    touchRecord.touchActive = true;
    touchRecord.startPageX = touch.pageX;
    touchRecord.startPageY = touch.pageY;
    touchRecord.startTimeStamp = timestampForTouch(touch);
    touchRecord.currentPageX = touch.pageX;
    touchRecord.currentPageY = touch.pageY;
    touchRecord.currentTimeStamp = timestampForTouch(touch);
    touchRecord.previousPageX = touch.pageX;
    touchRecord.previousPageY = touch.pageY;
    touchRecord.previousTimeStamp = timestampForTouch(touch);
  }
  
  function getTouchIdentifier(_ref) {
    var identifier = _ref.identifier;
  
    invariant(identifier != null, "Touch object is missing identifier.");
    {
      warning(
        identifier <= MAX_TOUCH_BANK,
        "Touch identifier %s is greater than maximum supported %s which causes " +
          "performance issues backfilling array locations for all of the indices.",
        identifier,
        MAX_TOUCH_BANK
      );
    }
    return identifier;
  }
  
  function recordTouchStart(touch) {
    var identifier = getTouchIdentifier(touch);
    var touchRecord = touchBank[identifier];
    if (touchRecord) {
      resetTouchRecord(touchRecord, touch);
    } else {
      touchBank[identifier] = createTouchRecord(touch);
    }
    touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
  }
  
  function recordTouchMove(touch) {
    var touchRecord = touchBank[getTouchIdentifier(touch)];
    if (touchRecord) {
      touchRecord.touchActive = true;
      touchRecord.previousPageX = touchRecord.currentPageX;
      touchRecord.previousPageY = touchRecord.currentPageY;
      touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
      touchRecord.currentPageX = touch.pageX;
      touchRecord.currentPageY = touch.pageY;
      touchRecord.currentTimeStamp = timestampForTouch(touch);
      touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
    } else {
      console.error(
        "Cannot record touch move without a touch start.\n" + "Touch Move: %s\n",
        "Touch Bank: %s",
        printTouch(touch),
        printTouchBank()
      );
    }
  }
  
  function recordTouchEnd(touch) {
    var touchRecord = touchBank[getTouchIdentifier(touch)];
    if (touchRecord) {
      touchRecord.touchActive = false;
      touchRecord.previousPageX = touchRecord.currentPageX;
      touchRecord.previousPageY = touchRecord.currentPageY;
      touchRecord.previousTimeStamp = touchRecord.currentTimeStamp;
      touchRecord.currentPageX = touch.pageX;
      touchRecord.currentPageY = touch.pageY;
      touchRecord.currentTimeStamp = timestampForTouch(touch);
      touchHistory.mostRecentTimeStamp = timestampForTouch(touch);
    } else {
      console.error(
        "Cannot record touch end without a touch start.\n" + "Touch End: %s\n",
        "Touch Bank: %s",
        printTouch(touch),
        printTouchBank()
      );
    }
  }
  
  function printTouch(touch) {
    return JSON.stringify({
      identifier: touch.identifier,
      pageX: touch.pageX,
      pageY: touch.pageY,
      timestamp: timestampForTouch(touch)
    });
  }
  
  function printTouchBank() {
    var printed = JSON.stringify(touchBank.slice(0, MAX_TOUCH_BANK));
    if (touchBank.length > MAX_TOUCH_BANK) {
      printed += " (original size: " + touchBank.length + ")";
    }
    return printed;
  }
  
  var ResponderTouchHistoryStore = {
    recordTouchTrack: function(topLevelType, nativeEvent) {
      if (isMoveish(topLevelType)) {
        nativeEvent.changedTouches.forEach(recordTouchMove);
      } else if (isStartish(topLevelType)) {
        nativeEvent.changedTouches.forEach(recordTouchStart);
        touchHistory.numberActiveTouches = nativeEvent.touches.length;
        if (touchHistory.numberActiveTouches === 1) {
          touchHistory.indexOfSingleActiveTouch =
            nativeEvent.touches[0].identifier;
        }
      } else if (isEndish(topLevelType)) {
        nativeEvent.changedTouches.forEach(recordTouchEnd);
        touchHistory.numberActiveTouches = nativeEvent.touches.length;
        if (touchHistory.numberActiveTouches === 1) {
          for (var i = 0; i < touchBank.length; i++) {
            var touchTrackToCheck = touchBank[i];
            if (touchTrackToCheck != null && touchTrackToCheck.touchActive) {
              touchHistory.indexOfSingleActiveTouch = i;
              break;
            }
          }
          {
            var activeRecord = touchBank[touchHistory.indexOfSingleActiveTouch];
            warning(
              activeRecord != null && activeRecord.touchActive,
              "Cannot find single active touch."
            );
          }
        }
      }
    },
  
    touchHistory: touchHistory
  };
  
  /**
   * Accumulates items that must not be null or undefined.
   *
   * This is used to conserve memory by avoiding array allocations.
   *
   * @return {*|array<*>} An accumulation of items.
   */
  function accumulate(current, next) {
    invariant(
      next != null,
      "accumulate(...): Accumulated items must be not be null or undefined."
    );
  
    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)) {
      return current.concat(next);
    }
  
    if (Array.isArray(next)) {
      return [current].concat(next);
    }
  
    return [current, next];
  }
  
  /**
   * Instance of element that should respond to touch/move types of interactions,
   * as indicated explicitly by relevant callbacks.
   */
  var responderInst = null;
  
  /**
   * Count of current touches. A textInput should become responder iff the
   * selection changes while there is a touch on the screen.
   */
  var trackedTouchCount = 0;
  
  /**
   * Last reported number of active touches.
   */
  var previousActiveTouches = 0;
  
  var changeResponder = function(nextResponderInst, blockHostResponder) {
    var oldResponderInst = responderInst;
    responderInst = nextResponderInst;
    if (ResponderEventPlugin.GlobalResponderHandler !== null) {
      ResponderEventPlugin.GlobalResponderHandler.onChange(
        oldResponderInst,
        nextResponderInst,
        blockHostResponder
      );
    }
  };
  
  var eventTypes = {
    /**
     * On a `touchStart`/`mouseDown`, is it desired that this element become the
     * responder?
     */
    startShouldSetResponder: {
      phasedRegistrationNames: {
        bubbled: "onStartShouldSetResponder",
        captured: "onStartShouldSetResponderCapture"
      }
    },
  
    /**
     * On a `scroll`, is it desired that this element become the responder? This
     * is usually not needed, but should be used to retroactively infer that a
     * `touchStart` had occurred during momentum scroll. During a momentum scroll,
     * a touch start will be immediately followed by a scroll event if the view is
     * currently scrolling.
     *
     * TODO: This shouldn't bubble.
     */
    scrollShouldSetResponder: {
      phasedRegistrationNames: {
        bubbled: "onScrollShouldSetResponder",
        captured: "onScrollShouldSetResponderCapture"
      }
    },
  
    /**
     * On text selection change, should this element become the responder? This
     * is needed for text inputs or other views with native selection, so the
     * JS view can claim the responder.
     *
     * TODO: This shouldn't bubble.
     */
    selectionChangeShouldSetResponder: {
      phasedRegistrationNames: {
        bubbled: "onSelectionChangeShouldSetResponder",
        captured: "onSelectionChangeShouldSetResponderCapture"
      }
    },
  
    /**
     * On a `touchMove`/`mouseMove`, is it desired that this element become the
     * responder?
     */
    moveShouldSetResponder: {
      phasedRegistrationNames: {
        bubbled: "onMoveShouldSetResponder",
        captured: "onMoveShouldSetResponderCapture"
      }
    },
  
    /**
     * Direct responder events dispatched directly to responder. Do not bubble.
     */
    responderStart: { registrationName: "onResponderStart" },
    responderMove: { registrationName: "onResponderMove" },
    responderEnd: { registrationName: "onResponderEnd" },
    responderRelease: { registrationName: "onResponderRelease" },
    responderTerminationRequest: {
      registrationName: "onResponderTerminationRequest"
    },
    responderGrant: { registrationName: "onResponderGrant" },
    responderReject: { registrationName: "onResponderReject" },
    responderTerminate: { registrationName: "onResponderTerminate" }
  };
  
  /**
   *
   * Responder System:
   * ----------------
   *
   * - A global, solitary "interaction lock" on a view.
   * - If a node becomes the responder, it should convey visual feedback
   *   immediately to indicate so, either by highlighting or moving accordingly.
   * - To be the responder means, that touches are exclusively important to that
   *   responder view, and no other view.
   * - While touches are still occurring, the responder lock can be transferred to
   *   a new view, but only to increasingly "higher" views (meaning ancestors of
   *   the current responder).
   *
   * Responder being granted:
   * ------------------------
   *
   * - Touch starts, moves, and scrolls can cause an ID to become the responder.
   * - We capture/bubble `startShouldSetResponder`/`moveShouldSetResponder` to
   *   the "appropriate place".
   * - If nothing is currently the responder, the "appropriate place" is the
   *   initiating event's `targetID`.
   * - If something *is* already the responder, the "appropriate place" is the
   *   first common ancestor of the event target and the current `responderInst`.
   * - Some negotiation happens: See the timing diagram below.
   * - Scrolled views automatically become responder. The reasoning is that a
   *   platform scroll view that isn't built on top of the responder system has
   *   began scrolling, and the active responder must now be notified that the
   *   interaction is no longer locked to it - the system has taken over.
   *
   * - Responder being released:
   *   As soon as no more touches that *started* inside of descendants of the
   *   *current* responderInst, an `onResponderRelease` event is dispatched to the
   *   current responder, and the responder lock is released.
   *
   * TODO:
   * - on "end", a callback hook for `onResponderEndShouldRemainResponder` that
   *   determines if the responder lock should remain.
   * - If a view shouldn't "remain" the responder, any active touches should by
   *   default be considered "dead" and do not influence future negotiations or
   *   bubble paths. It should be as if those touches do not exist.
   * -- For multitouch: Usually a translate-z will choose to "remain" responder
   *  after one out of many touches ended. For translate-y, usually the view
   *  doesn't wish to "remain" responder after one of many touches end.
   * - Consider building this on top of a `stopPropagation` model similar to
   *   `W3C` events.
   * - Ensure that `onResponderTerminate` is called on touch cancels, whether or
   *   not `onResponderTerminationRequest` returns `true` or `false`.
   *
   */
  
  /*                                             Negotiation Performed
                                               +-----------------------+
                                              /                         \
  Process low level events to    +     Current Responder      +   wantsResponderID
  determine who to perform negot-|   (if any exists at all)   |
  iation/transition              | Otherwise just pass through|
  -------------------------------+----------------------------+------------------+
  Bubble to find first ID        |                            |
  to return true:wantsResponderID|                            |
                                 |                            |
       +-------------+           |                            |
       | onTouchStart|           |                            |
       +------+------+     none  |                            |
              |            return|                            |
  +-----------v-------------+true| +------------------------+ |
  |onStartShouldSetResponder|----->|onResponderStart (cur)  |<-----------+
  +-----------+-------------+    | +------------------------+ |          |
              |                  |                            | +--------+-------+
              | returned true for|       false:REJECT +-------->|onResponderReject
              | wantsResponderID |                    |       | +----------------+
              | (now attempt     | +------------------+-----+ |
              |  handoff)        | |   onResponder          | |
              +------------------->|      TerminationRequest| |
                                 | +------------------+-----+ |
                                 |                    |       | +----------------+
                                 |         true:GRANT +-------->|onResponderGrant|
                                 |                            | +--------+-------+
                                 | +------------------------+ |          |
                                 | |   onResponderTerminate |<-----------+
                                 | +------------------+-----+ |
                                 |                    |       | +----------------+
                                 |                    +-------->|onResponderStart|
                                 |                            | +----------------+
  Bubble to find first ID        |                            |
  to return true:wantsResponderID|                            |
                                 |                            |
       +-------------+           |                            |
       | onTouchMove |           |                            |
       +------+------+     none  |                            |
              |            return|                            |
  +-----------v-------------+true| +------------------------+ |
  |onMoveShouldSetResponder |----->|onResponderMove (cur)   |<-----------+
  +-----------+-------------+    | +------------------------+ |          |
              |                  |                            | +--------+-------+
              | returned true for|       false:REJECT +-------->|onResponderRejec|
              | wantsResponderID |                    |       | +----------------+
              | (now attempt     | +------------------+-----+ |
              |  handoff)        | |   onResponder          | |
              +------------------->|      TerminationRequest| |
                                 | +------------------+-----+ |
                                 |                    |       | +----------------+
                                 |         true:GRANT +-------->|onResponderGrant|
                                 |                            | +--------+-------+
                                 | +------------------------+ |          |
                                 | |   onResponderTerminate |<-----------+
                                 | +------------------+-----+ |
                                 |                    |       | +----------------+
                                 |                    +-------->|onResponderMove |
                                 |                            | +----------------+
                                 |                            |
                                 |                            |
        Some active touch started|                            |
        inside current responder | +------------------------+ |
        +------------------------->|      onResponderEnd    | |
        |                        | +------------------------+ |
    +---+---------+              |                            |
    | onTouchEnd  |              |                            |
    +---+---------+              |                            |
        |                        | +------------------------+ |
        +------------------------->|     onResponderEnd     | |
        No active touches started| +-----------+------------+ |
        inside current responder |             |              |
                                 |             v              |
                                 | +------------------------+ |
                                 | |    onResponderRelease  | |
                                 | +------------------------+ |
                                 |                            |
                                 +                            + */
  
  /**
   * A note about event ordering in the `EventPluginHub`.
   *
   * Suppose plugins are injected in the following order:
   *
   * `[R, S, C]`
   *
   * To help illustrate the example, assume `S` is `SimpleEventPlugin` (for
   * `onClick` etc) and `R` is `ResponderEventPlugin`.
   *
   * "Deferred-Dispatched Events":
   *
   * - The current event plugin system will traverse the list of injected plugins,
   *   in order, and extract events by collecting the plugin's return value of
   *   `extractEvents()`.
   * - These events that are returned from `extractEvents` are "deferred
   *   dispatched events".
   * - When returned from `extractEvents`, deferred-dispatched events contain an
   *   "accumulation" of deferred dispatches.
   * - These deferred dispatches are accumulated/collected before they are
   *   returned, but processed at a later time by the `EventPluginHub` (hence the
   *   name deferred).
   *
   * In the process of returning their deferred-dispatched events, event plugins
   * themselves can dispatch events on-demand without returning them from
   * `extractEvents`. Plugins might want to do this, so that they can use event
   * dispatching as a tool that helps them decide which events should be extracted
   * in the first place.
   *
   * "On-Demand-Dispatched Events":
   *
   * - On-demand-dispatched events are not returned from `extractEvents`.
   * - On-demand-dispatched events are dispatched during the process of returning
   *   the deferred-dispatched events.
   * - They should not have side effects.
   * - They should be avoided, and/or eventually be replaced with another
   *   abstraction that allows event plugins to perform multiple "rounds" of event
   *   extraction.
   *
   * Therefore, the sequence of event dispatches becomes:
   *
   * - `R`s on-demand events (if any)   (dispatched by `R` on-demand)
   * - `S`s on-demand events (if any)   (dispatched by `S` on-demand)
   * - `C`s on-demand events (if any)   (dispatched by `C` on-demand)
   * - `R`s extracted events (if any)   (dispatched by `EventPluginHub`)
   * - `S`s extracted events (if any)   (dispatched by `EventPluginHub`)
   * - `C`s extracted events (if any)   (dispatched by `EventPluginHub`)
   *
   * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`
   * on-demand dispatch returns `true` (and some other details are satisfied) the
   * `onResponderGrant` deferred dispatched event is returned from
   * `extractEvents`. The sequence of dispatch executions in this case
   * will appear as follows:
   *
   * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)
   * - `touchStartCapture`       (`EventPluginHub` dispatches as usual)
   * - `touchStart`              (`EventPluginHub` dispatches as usual)
   * - `responderGrant/Reject`   (`EventPluginHub` dispatches as usual)
   */
  
  function setResponderAndExtractTransfer(
    topLevelType,
    targetInst,
    nativeEvent,
    nativeEventTarget
  ) {
    var shouldSetEventType = isStartish(topLevelType)
      ? eventTypes.startShouldSetResponder
      : isMoveish(topLevelType)
        ? eventTypes.moveShouldSetResponder
        : topLevelType === "topSelectionChange"
          ? eventTypes.selectionChangeShouldSetResponder
          : eventTypes.scrollShouldSetResponder;
  
    // TODO: stop one short of the current responder.
    var bubbleShouldSetFrom = !responderInst
      ? targetInst
      : getLowestCommonAncestor(responderInst, targetInst);
  
    // When capturing/bubbling the "shouldSet" event, we want to skip the target
    // (deepest ID) if it happens to be the current responder. The reasoning:
    // It's strange to get an `onMoveShouldSetResponder` when you're *already*
    // the responder.
    var skipOverBubbleShouldSetFrom = bubbleShouldSetFrom === responderInst;
    var shouldSetEvent = ResponderSyntheticEvent.getPooled(
      shouldSetEventType,
      bubbleShouldSetFrom,
      nativeEvent,
      nativeEventTarget
    );
    shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
    if (skipOverBubbleShouldSetFrom) {
      accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);
    } else {
      accumulateTwoPhaseDispatches(shouldSetEvent);
    }
    var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent);
    if (!shouldSetEvent.isPersistent()) {
      shouldSetEvent.constructor.release(shouldSetEvent);
    }
  
    if (!wantsResponderInst || wantsResponderInst === responderInst) {
      return null;
    }
    var extracted = void 0;
    var grantEvent = ResponderSyntheticEvent.getPooled(
      eventTypes.responderGrant,
      wantsResponderInst,
      nativeEvent,
      nativeEventTarget
    );
    grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
  
    accumulateDirectDispatches(grantEvent);
    var blockHostResponder = executeDirectDispatch(grantEvent) === true;
    if (responderInst) {
      var terminationRequestEvent = ResponderSyntheticEvent.getPooled(
        eventTypes.responderTerminationRequest,
        responderInst,
        nativeEvent,
        nativeEventTarget
      );
      terminationRequestEvent.touchHistory =
        ResponderTouchHistoryStore.touchHistory;
      accumulateDirectDispatches(terminationRequestEvent);
      var shouldSwitch =
        !hasDispatches(terminationRequestEvent) ||
        executeDirectDispatch(terminationRequestEvent);
      if (!terminationRequestEvent.isPersistent()) {
        terminationRequestEvent.constructor.release(terminationRequestEvent);
      }
  
      if (shouldSwitch) {
        var terminateEvent = ResponderSyntheticEvent.getPooled(
          eventTypes.responderTerminate,
          responderInst,
          nativeEvent,
          nativeEventTarget
        );
        terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
        accumulateDirectDispatches(terminateEvent);
        extracted = accumulate(extracted, [grantEvent, terminateEvent]);
        changeResponder(wantsResponderInst, blockHostResponder);
      } else {
        var rejectEvent = ResponderSyntheticEvent.getPooled(
          eventTypes.responderReject,
          wantsResponderInst,
          nativeEvent,
          nativeEventTarget
        );
        rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
        accumulateDirectDispatches(rejectEvent);
        extracted = accumulate(extracted, rejectEvent);
      }
    } else {
      extracted = accumulate(extracted, grantEvent);
      changeResponder(wantsResponderInst, blockHostResponder);
    }
    return extracted;
  }
  
  /**
   * A transfer is a negotiation between a currently set responder and the next
   * element to claim responder status. Any start event could trigger a transfer
   * of responderInst. Any move event could trigger a transfer.
   *
   * @param {string} topLevelType Record from `BrowserEventConstants`.
   * @return {boolean} True if a transfer of responder could possibly occur.
   */
  function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) {
    return (
      topLevelInst &&
      // responderIgnoreScroll: We are trying to migrate away from specifically
      // tracking native scroll events here and responderIgnoreScroll indicates we
      // will send topTouchCancel to handle canceling touch events instead
      ((topLevelType === "topScroll" && !nativeEvent.responderIgnoreScroll) ||
        (trackedTouchCount > 0 && topLevelType === "topSelectionChange") ||
        isStartish(topLevelType) ||
        isMoveish(topLevelType))
    );
  }
  
  /**
   * Returns whether or not this touch end event makes it such that there are no
   * longer any touches that started inside of the current `responderInst`.
   *
   * @param {NativeEvent} nativeEvent Native touch end event.
   * @return {boolean} Whether or not this touch end event ends the responder.
   */
  function noResponderTouches(nativeEvent) {
    var touches = nativeEvent.touches;
    if (!touches || touches.length === 0) {
      return true;
    }
    for (var i = 0; i < touches.length; i++) {
      var activeTouch = touches[i];
      var target = activeTouch.target;
      if (target !== null && target !== undefined && target !== 0) {
        // Is the original touch location inside of the current responder?
        var targetInst = getInstanceFromNode(target);
        if (isAncestor(responderInst, targetInst)) {
          return false;
        }
      }
    }
    return true;
  }
  
  var ResponderEventPlugin = {
    /* For unit testing only */
    _getResponder: function() {
      return responderInst;
    },
  
    eventTypes: eventTypes,
  
    /**
     * We must be resilient to `targetInst` being `null` on `touchMove` or
     * `touchEnd`. On certain platforms, this means that a native scroll has
     * assumed control and the original touch targets are destroyed.
     */
    extractEvents: function(
      topLevelType,
      targetInst,
      nativeEvent,
      nativeEventTarget
    ) {
      if (isStartish(topLevelType)) {
        trackedTouchCount += 1;
      } else if (isEndish(topLevelType)) {
        if (trackedTouchCount >= 0) {
          trackedTouchCount -= 1;
        } else {
          console.error(
            "Ended a touch event which was not counted in `trackedTouchCount`."
          );
          return null;
        }
      }
  
      ResponderTouchHistoryStore.recordTouchTrack(topLevelType, nativeEvent);
  
      var extracted = canTriggerTransfer(topLevelType, targetInst, nativeEvent)
        ? setResponderAndExtractTransfer(
            topLevelType,
            targetInst,
            nativeEvent,
            nativeEventTarget
          )
        : null;
      // Responder may or may not have transferred on a new touch start/move.
      // Regardless, whoever is the responder after any potential transfer, we
      // direct all touch start/move/ends to them in the form of
      // `onResponderMove/Start/End`. These will be called for *every* additional
      // finger that move/start/end, dispatched directly to whoever is the
      // current responder at that moment, until the responder is "released".
      //
      // These multiple individual change touch events are are always bookended
      // by `onResponderGrant`, and one of
      // (`onResponderRelease/onResponderTerminate`).
      var isResponderTouchStart = responderInst && isStartish(topLevelType);
      var isResponderTouchMove = responderInst && isMoveish(topLevelType);
      var isResponderTouchEnd = responderInst && isEndish(topLevelType);
      var incrementalTouch = isResponderTouchStart
        ? eventTypes.responderStart
        : isResponderTouchMove
          ? eventTypes.responderMove
          : isResponderTouchEnd ? eventTypes.responderEnd : null;
  
      if (incrementalTouch) {
        var gesture = ResponderSyntheticEvent.getPooled(
          incrementalTouch,
          responderInst,
          nativeEvent,
          nativeEventTarget
        );
        gesture.touchHistory = ResponderTouchHistoryStore.touchHistory;
        accumulateDirectDispatches(gesture);
        extracted = accumulate(extracted, gesture);
      }
  
      var isResponderTerminate =
        responderInst && topLevelType === "topTouchCancel";
      var isResponderRelease =
        responderInst &&
        !isResponderTerminate &&
        isEndish(topLevelType) &&
        noResponderTouches(nativeEvent);
      var finalTouch = isResponderTerminate
        ? eventTypes.responderTerminate
        : isResponderRelease ? eventTypes.responderRelease : null;
      if (finalTouch) {
        var finalEvent = ResponderSyntheticEvent.getPooled(
          finalTouch,
          responderInst,
          nativeEvent,
          nativeEventTarget
        );
        finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
        accumulateDirectDispatches(finalEvent);
        extracted = accumulate(extracted, finalEvent);
        changeResponder(null);
      }
  
      var numberActiveTouches =
        ResponderTouchHistoryStore.touchHistory.numberActiveTouches;
      if (
        ResponderEventPlugin.GlobalInteractionHandler &&
        numberActiveTouches !== previousActiveTouches
      ) {
        ResponderEventPlugin.GlobalInteractionHandler.onChange(
          numberActiveTouches
        );
      }
      previousActiveTouches = numberActiveTouches;
  
      return extracted;
    },
  
    GlobalResponderHandler: null,
    GlobalInteractionHandler: null,
  
    injection: {
      /**
       * @param {{onChange: (ReactID, ReactID) => void} GlobalResponderHandler
       * Object that handles any change in responder. Use this to inject
       * integration with an existing touch handling system etc.
       */
      injectGlobalResponderHandler: function(GlobalResponderHandler) {
        ResponderEventPlugin.GlobalResponderHandler = GlobalResponderHandler;
      },
  
      /**
       * @param {{onChange: (numberActiveTouches) => void} GlobalInteractionHandler
       * Object that handles any change in the number of active touches.
       */
      injectGlobalInteractionHandler: function(GlobalInteractionHandler) {
        ResponderEventPlugin.GlobalInteractionHandler = GlobalInteractionHandler;
      }
    }
  };
  
  var customBubblingEventTypes = {};
  var customDirectEventTypes = {};
  
  var ReactNativeBridgeEventPlugin = {
    eventTypes: {},
  
    /**
     * @see {EventPluginHub.extractEvents}
     */
    extractEvents: function(
      topLevelType,
      targetInst,
      nativeEvent,
      nativeEventTarget
    ) {
      var bubbleDispatchConfig = customBubblingEventTypes[topLevelType];
      var directDispatchConfig = customDirectEventTypes[topLevelType];
      invariant(
        bubbleDispatchConfig || directDispatchConfig,
        'Unsupported top level event type "%s" dispatched',
        topLevelType
      );
      var event = SyntheticEvent$1.getPooled(
        bubbleDispatchConfig || directDispatchConfig,
        targetInst,
        nativeEvent,
        nativeEventTarget
      );
      if (bubbleDispatchConfig) {
        accumulateTwoPhaseDispatches(event);
      } else if (directDispatchConfig) {
        accumulateDirectDispatches(event);
      } else {
        return null;
      }
      return event;
    },
  
    processEventTypes: function(viewConfig) {
      var bubblingEventTypes = viewConfig.bubblingEventTypes,
        directEventTypes = viewConfig.directEventTypes;
  
      {
        if (bubblingEventTypes != null && directEventTypes != null) {
          for (var topLevelType in directEventTypes) {
            invariant(
              bubblingEventTypes[topLevelType] == null,
              "Event cannot be both direct and bubbling: %s",
              topLevelType
            );
          }
        }
      }
  
      if (bubblingEventTypes != null) {
        for (var _topLevelType in bubblingEventTypes) {
          if (customBubblingEventTypes[_topLevelType] == null) {
            ReactNativeBridgeEventPlugin.eventTypes[
              _topLevelType
            ] = customBubblingEventTypes[_topLevelType] =
              bubblingEventTypes[_topLevelType];
          }
        }
      }
  
      if (directEventTypes != null) {
        for (var _topLevelType2 in directEventTypes) {
          if (customDirectEventTypes[_topLevelType2] == null) {
            ReactNativeBridgeEventPlugin.eventTypes[
              _topLevelType2
            ] = customDirectEventTypes[_topLevelType2] =
              directEventTypes[_topLevelType2];
          }
        }
      }
    }
  };
  
  var instanceCache = {};
  var instanceProps = {};
  
  function precacheFiberNode(hostInst, tag) {
    instanceCache[tag] = hostInst;
  }
  
  function uncacheFiberNode(tag) {
    delete instanceCache[tag];
    delete instanceProps[tag];
  }
  
  function getInstanceFromTag(tag) {
    if (typeof tag === "number") {
      return instanceCache[tag] || null;
    } else {
      // Fabric will invoke event emitters on a direct fiber reference
      return tag;
    }
  }
  
  function getTagFromInstance(inst) {
    var tag = inst.stateNode._nativeTag;
    if (tag === undefined) {
      tag = inst.stateNode.canonical._nativeTag;
    }
    invariant(tag, "All native instances should have a tag.");
    return tag;
  }
  
  function getFiberCurrentPropsFromNode$1(stateNode) {
    return instanceProps[stateNode._nativeTag] || null;
  }
  
  function updateFiberProps(tag, props) {
    instanceProps[tag] = props;
  }
  
  var ReactNativeComponentTree = Object.freeze({
    precacheFiberNode: precacheFiberNode,
    uncacheFiberNode: uncacheFiberNode,
    getClosestInstanceFromNode: getInstanceFromTag,
    getInstanceFromNode: getInstanceFromTag,
    getNodeFromInstance: getTagFromInstance,
    getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode$1,
    updateFiberProps: updateFiberProps
  });
  
  // Use to restore controlled state after a change event has fired.
  
  var fiberHostComponent = 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;
    }
    invariant(
      fiberHostComponent &&
        typeof fiberHostComponent.restoreControlledState === "function",
      "Fiber needs to be injected to handle a fiber target for controlled " +
        "events. This error is likely caused by a bug in React. Please file an issue."
    );
    var props = getFiberCurrentPropsFromNode(internalInstance.stateNode);
    fiberHostComponent.restoreControlledState(
      internalInstance.stateNode,
      internalInstance.type,
      props
    );
  }
  
  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 _batchedUpdates = function(fn, bookkeeping) {
    return fn(bookkeeping);
  };
  var _interactiveUpdates = function(fn, a, b) {
    return fn(a, b);
  };
  var _flushInteractiveUpdates = 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 _batchedUpdates(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.
        _flushInteractiveUpdates();
        restoreStateIfNeeded();
      }
    }
  }
  
  var injection$2 = {
    injectRenderer: function(renderer) {
      _batchedUpdates = renderer.batchedUpdates;
      _interactiveUpdates = renderer.interactiveUpdates;
      _flushInteractiveUpdates = renderer.flushInteractiveUpdates;
    }
  };
  
  /**
   * Keeps track of allocating and associating native "tags" which are numeric,
   * unique view IDs. All the native tags are negative numbers, to avoid
   * collisions, but in the JS we keep track of them as positive integers to store
   * them effectively in Arrays. So we must refer to them as "inverses" of the
   * native tags (that are * normally negative).
   *
   * It *must* be the case that every `rootNodeID` always maps to the exact same
   * `tag` forever. The easiest way to accomplish this is to never delete
   * anything from this table.
   * Why: Because `dangerouslyReplaceNodeWithMarkupByID` relies on being able to
   * unmount a component with a `rootNodeID`, then mount a new one in its place,
   */
  var INITIAL_TAG_COUNT = 1;
  var ReactNativeTagHandles = {
    tagsStartAt: INITIAL_TAG_COUNT,
    tagCount: INITIAL_TAG_COUNT,
  
    allocateTag: function() {
      // Skip over root IDs as those are reserved for native
      while (this.reactTagIsNativeTopRootID(ReactNativeTagHandles.tagCount)) {
        ReactNativeTagHandles.tagCount++;
      }
      var tag = ReactNativeTagHandles.tagCount;
      ReactNativeTagHandles.tagCount++;
      return tag;
    },
  
    assertRootTag: function(tag) {
      invariant(
        this.reactTagIsNativeTopRootID(tag),
        "Expect a native root tag, instead got %s",
        tag
      );
    },
  
    reactTagIsNativeTopRootID: function(reactTag) {
      // We reserve all tags that are 1 mod 10 for native root views
      return reactTag % 10 === 1;
    }
  };
  
  /**
   * Version of `ReactBrowserEventEmitter` that works on the receiving side of a
   * serialized worker boundary.
   */
  
  // Shared default empty native event - conserve memory.
  var EMPTY_NATIVE_EVENT = {};
  
  /**
   * Selects a subsequence of `Touch`es, without destroying `touches`.
   *
   * @param {Array<Touch>} touches Deserialized touch objects.
   * @param {Array<number>} indices Indices by which to pull subsequence.
   * @return {Array<Touch>} Subsequence of touch objects.
   */
  var touchSubsequence = function(touches, indices) {
    var ret = [];
    for (var i = 0; i < indices.length; i++) {
      ret.push(touches[indices[i]]);
    }
    return ret;
  };
  
  /**
   * TODO: Pool all of this.
   *
   * Destroys `touches` by removing touch objects at indices `indices`. This is
   * to maintain compatibility with W3C touch "end" events, where the active
   * touches don't include the set that has just been "ended".
   *
   * @param {Array<Touch>} touches Deserialized touch objects.
   * @param {Array<number>} indices Indices to remove from `touches`.
   * @return {Array<Touch>} Subsequence of removed touch objects.
   */
  var removeTouchesAtIndices = function(touches, indices) {
    var rippedOut = [];
    // use an unsafe downcast to alias to nullable elements,
    // so we can delete and then compact.
    var temp = touches;
    for (var i = 0; i < indices.length; i++) {
      var index = indices[i];
      rippedOut.push(touches[index]);
      temp[index] = null;
    }
    var fillAt = 0;
    for (var j = 0; j < temp.length; j++) {
      var cur = temp[j];
      if (cur !== null) {
        temp[fillAt++] = cur;
      }
    }
    temp.length = fillAt;
    return rippedOut;
  };
  
  /**
   * Internal version of `receiveEvent` in terms of normalized (non-tag)
   * `rootNodeID`.
   *
   * @see receiveEvent.
   *
   * @param {rootNodeID} rootNodeID React root node ID that event occurred on.
   * @param {TopLevelType} topLevelType Top level type of event.
   * @param {?object} nativeEventParam Object passed from native.
   */
  function _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam) {
    var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT;
    var inst = getInstanceFromTag(rootNodeID);
    batchedUpdates(function() {
      runExtractedEventsInBatch(
        topLevelType,
        inst,
        nativeEvent,
        nativeEvent.target
      );
    });
    // React Native doesn't use ReactControlledComponent but if it did, here's
    // where it would do it.
  }
  
  /**
   * Publicly exposed method on module for native objc to invoke when a top
   * level event is extracted.
   * @param {rootNodeID} rootNodeID React root node ID that event occurred on.
   * @param {TopLevelType} topLevelType Top level type of event.
   * @param {object} nativeEventParam Object passed from native.
   */
  function receiveEvent(rootNodeID, topLevelType, nativeEventParam) {
    _receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam);
  }
  
  /**
   * Simple multi-wrapper around `receiveEvent` that is intended to receive an
   * efficient representation of `Touch` objects, and other information that
   * can be used to construct W3C compliant `Event` and `Touch` lists.
   *
   * This may create dispatch behavior that differs than web touch handling. We
   * loop through each of the changed touches and receive it as a single event.
   * So two `touchStart`/`touchMove`s that occur simultaneously are received as
   * two separate touch event dispatches - when they arguably should be one.
   *
   * This implementation reuses the `Touch` objects themselves as the `Event`s
   * since we dispatch an event for each touch (though that might not be spec
   * compliant). The main purpose of reusing them is to save allocations.
   *
   * TODO: Dispatch multiple changed touches in one event. The bubble path
   * could be the first common ancestor of all the `changedTouches`.
   *
   * One difference between this behavior and W3C spec: cancelled touches will
   * not appear in `.touches`, or in any future `.touches`, though they may
   * still be "actively touching the surface".
   *
   * Web desktop polyfills only need to construct a fake touch event with
   * identifier 0, also abandoning traditional click handlers.
   */
  function receiveTouches(eventTopLevelType, touches, changedIndices) {
    var changedTouches =
      eventTopLevelType === "topTouchEnd" ||
      eventTopLevelType === "topTouchCancel"
        ? removeTouchesAtIndices(touches, changedIndices)
        : touchSubsequence(touches, changedIndices);
  
    for (var jj = 0; jj < changedTouches.length; jj++) {
      var touch = changedTouches[jj];
      // Touch objects can fulfill the role of `DOM` `Event` objects if we set
      // the `changedTouches`/`touches`. This saves allocations.
      touch.changedTouches = changedTouches;
      touch.touches = touches;
      var nativeEvent = touch;
      var rootNodeID = null;
      var target = nativeEvent.target;
      if (target !== null && target !== undefined) {
        if (target < ReactNativeTagHandles.tagsStartAt) {
          {
            warning(
              false,
              "A view is reporting that a touch occurred on tag zero."
            );
          }
        } else {
          rootNodeID = target;
        }
      }
      // $FlowFixMe Shouldn't we *not* call it if rootNodeID is null?
      _receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent);
    }
  }
  
  var ReactNativeEventEmitter = Object.freeze({
    getListener: getListener,
    registrationNames: registrationNameModules,
    _receiveRootNodeIDEvent: _receiveRootNodeIDEvent,
    receiveEvent: receiveEvent,
    receiveTouches: receiveTouches
  });
  
  var ReactNativeEventPluginOrder = [
    "ResponderEventPlugin",
    "ReactNativeBridgeEventPlugin"
  ];
  
  // Module provided by RN:
  var ReactNativeGlobalResponderHandler = {
    onChange: function(from, to, blockNativeResponder) {
      if (to !== null) {
        var tag = to.stateNode._nativeTag;
        UIManager.setJSResponder(tag, blockNativeResponder);
      } else {
        UIManager.clearJSResponder();
      }
    }
  };
  
  /**
   * Make sure essential globals are available and are patched correctly. Please don't remove this
   * line. Bundles created by react-packager `require` it before executing any application code. This
   * ensures it exists in the dependency graph and can be `require`d.
   * TODO: require this in packager, not in React #10932517
   */
  // Module provided by RN:
  // Module provided by RN:
  /**
   * Register the event emitter with the native bridge
   */
  RCTEventEmitter.register(ReactNativeEventEmitter);
  
  /**
   * Inject module for resolving DOM hierarchy and plugin ordering.
   */
  injection.injectEventPluginOrder(ReactNativeEventPluginOrder);
  injection$1.injectComponentTree(ReactNativeComponentTree);
  
  ResponderEventPlugin.injection.injectGlobalResponderHandler(
    ReactNativeGlobalResponderHandler
  );
  
  /**
   * Some important event plugins included by default (without having to require
   * them).
   */
  injection.injectEventPluginsByName({
    ResponderEventPlugin: ResponderEventPlugin,
    ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin
  });
  
  // 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_CALL_TYPE = hasSymbol ? Symbol["for"]("react.call") : 0xeac8;
  var REACT_RETURN_TYPE = hasSymbol ? Symbol["for"]("react.return") : 0xeac9;
  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_PROVIDER_TYPE = hasSymbol ? Symbol["for"]("react.provider") : 0xeacd;
  var REACT_CONTEXT_TYPE = hasSymbol ? Symbol["for"]("react.context") : 0xeace;
  var REACT_ASYNC_MODE_TYPE = hasSymbol
    ? Symbol["for"]("react.async_mode")
    : 0xeacf;
  
  var MAYBE_ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator;
  var FAUX_ITERATOR_SYMBOL = "@@iterator";
  
  function getIteratorFn(maybeIterable) {
    if (maybeIterable === null || typeof maybeIterable === "undefined") {
      return null;
    }
    var maybeIterator =
      (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) ||
      maybeIterable[FAUX_ITERATOR_SYMBOL];
    if (typeof maybeIterator === "function") {
      return maybeIterator;
    }
    return null;
  }
  
  function createPortal(
    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
    };
  }
  
  var TouchHistoryMath = {
    /**
     * This code is optimized and not intended to look beautiful. This allows
     * computing of touch centroids that have moved after `touchesChangedAfter`
     * timeStamp. You can compute the current centroid involving all touches
     * moves after `touchesChangedAfter`, or you can compute the previous
     * centroid of all touches that were moved after `touchesChangedAfter`.
     *
     * @param {TouchHistoryMath} touchHistory Standard Responder touch track
     * data.
     * @param {number} touchesChangedAfter timeStamp after which moved touches
     * are considered "actively moving" - not just "active".
     * @param {boolean} isXAxis Consider `x` dimension vs. `y` dimension.
     * @param {boolean} ofCurrent Compute current centroid for actively moving
     * touches vs. previous centroid of now actively moving touches.
     * @return {number} value of centroid in specified dimension.
     */
    centroidDimension: function(
      touchHistory,
      touchesChangedAfter,
      isXAxis,
      ofCurrent
    ) {
      var touchBank = touchHistory.touchBank;
      var total = 0;
      var count = 0;
  
      var oneTouchData =
        touchHistory.numberActiveTouches === 1
          ? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch]
          : null;
  
      if (oneTouchData !== null) {
        if (
          oneTouchData.touchActive &&
          oneTouchData.currentTimeStamp > touchesChangedAfter
        ) {
          total +=
            ofCurrent && isXAxis
              ? oneTouchData.currentPageX
              : ofCurrent && !isXAxis
                ? oneTouchData.currentPageY
                : !ofCurrent && isXAxis
                  ? oneTouchData.previousPageX
                  : oneTouchData.previousPageY;
          count = 1;
        }
      } else {
        for (var i = 0; i < touchBank.length; i++) {
          var touchTrack = touchBank[i];
          if (
            touchTrack !== null &&
            touchTrack !== undefined &&
            touchTrack.touchActive &&
            touchTrack.currentTimeStamp >= touchesChangedAfter
          ) {
            var toAdd = void 0; // Yuck, program temporarily in invalid state.
            if (ofCurrent && isXAxis) {
              toAdd = touchTrack.currentPageX;
            } else if (ofCurrent && !isXAxis) {
              toAdd = touchTrack.currentPageY;
            } else if (!ofCurrent && isXAxis) {
              toAdd = touchTrack.previousPageX;
            } else {
              toAdd = touchTrack.previousPageY;
            }
            total += toAdd;
            count++;
          }
        }
      }
      return count > 0 ? total / count : TouchHistoryMath.noCentroid;
    },
  
    currentCentroidXOfTouchesChangedAfter: function(
      touchHistory,
      touchesChangedAfter
    ) {
      return TouchHistoryMath.centroidDimension(
        touchHistory,
        touchesChangedAfter,
        true, // isXAxis
        true
      );
    },
  
    currentCentroidYOfTouchesChangedAfter: function(
      touchHistory,
      touchesChangedAfter
    ) {
      return TouchHistoryMath.centroidDimension(
        touchHistory,
        touchesChangedAfter,
        false, // isXAxis
        true
      );
    },
  
    previousCentroidXOfTouchesChangedAfter: function(
      touchHistory,
      touchesChangedAfter
    ) {
      return TouchHistoryMath.centroidDimension(
        touchHistory,
        touchesChangedAfter,
        true, // isXAxis
        false
      );
    },
  
    previousCentroidYOfTouchesChangedAfter: function(
      touchHistory,
      touchesChangedAfter
    ) {
      return TouchHistoryMath.centroidDimension(
        touchHistory,
        touchesChangedAfter,
        false, // isXAxis
        false
      );
    },
  
    currentCentroidX: function(touchHistory) {
      return TouchHistoryMath.centroidDimension(
        touchHistory,
        0, // touchesChangedAfter
        true, // isXAxis
        true
      );
    },
  
    currentCentroidY: function(touchHistory) {
      return TouchHistoryMath.centroidDimension(
        touchHistory,
        0, // touchesChangedAfter
        false, // isXAxis
        true
      );
    },
  
    noCentroid: -1
  };
  
  var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
  
  var ReactCurrentOwner = ReactInternals.ReactCurrentOwner;
  var ReactDebugCurrentFrame = ReactInternals.ReactDebugCurrentFrame;
  
  var ReactGlobalSharedState = Object.freeze({
    ReactCurrentOwner: ReactCurrentOwner,
    ReactDebugCurrentFrame: ReactDebugCurrentFrame
  });
  
  // TODO: this is special because it gets imported during build.
  
  var ReactVersion = "16.2.0";
  
  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }
  
  var objects = {};
  var uniqueID = 1;
  var emptyObject$2 = {};
  
  var ReactNativePropRegistry = (function() {
    function ReactNativePropRegistry() {
      _classCallCheck(this, ReactNativePropRegistry);
    }
  
    ReactNativePropRegistry.register = function register(object) {
      var id = ++uniqueID;
      {
        Object.freeze(object);
      }
      objects[id] = object;
      return id;
    };
  
    ReactNativePropRegistry.getByID = function getByID(id) {
      if (!id) {
        // Used in the style={[condition && id]} pattern,
        // we want it to be a no-op when the value is false or null
        return emptyObject$2;
      }
  
      var object = objects[id];
      if (!object) {
        console.warn("Invalid style with id `" + id + "`. Skipping ...");
        return emptyObject$2;
      }
      return object;
    };
  
    return ReactNativePropRegistry;
  })();
  
  // Modules provided by RN:
  var emptyObject$1 = {};
  
  /**
   * Create a payload that contains all the updates between two sets of props.
   *
   * These helpers are all encapsulated into a single module, because they use
   * mutation as a performance optimization which leads to subtle shared
   * dependencies between the code paths. To avoid this mutable state leaking
   * across modules, I've kept them isolated to this module.
   */
  
  // Tracks removed keys
  var removedKeys = null;
  var removedKeyCount = 0;
  
  function defaultDiffer(prevProp, nextProp) {
    if (typeof nextProp !== "object" || nextProp === null) {
      // Scalars have already been checked for equality
      return true;
    } else {
      // For objects and arrays, the default diffing algorithm is a deep compare
      return deepDiffer(prevProp, nextProp);
    }
  }
  
  function resolveObject(idOrObject) {
    if (typeof idOrObject === "number") {
      return ReactNativePropRegistry.getByID(idOrObject);
    }
    return idOrObject;
  }
  
  function restoreDeletedValuesInNestedArray(
    updatePayload,
    node,
    validAttributes
  ) {
    if (Array.isArray(node)) {
      var i = node.length;
      while (i-- && removedKeyCount > 0) {
        restoreDeletedValuesInNestedArray(
          updatePayload,
          node[i],
          validAttributes
        );
      }
    } else if (node && removedKeyCount > 0) {
      var obj = resolveObject(node);
      for (var propKey in removedKeys) {
        if (!removedKeys[propKey]) {
          continue;
        }
        var _nextProp = obj[propKey];
        if (_nextProp === undefined) {
          continue;
        }
  
        var attributeConfig = validAttributes[propKey];
        if (!attributeConfig) {
          continue; // not a valid native prop
        }
  
        if (typeof _nextProp === "function") {
          _nextProp = true;
        }
        if (typeof _nextProp === "undefined") {
          _nextProp = null;
        }
  
        if (typeof attributeConfig !== "object") {
          // case: !Object is the default case
          updatePayload[propKey] = _nextProp;
        } else if (
          typeof attributeConfig.diff === "function" ||
          typeof attributeConfig.process === "function"
        ) {
          // case: CustomAttributeConfiguration
          var nextValue =
            typeof attributeConfig.process === "function"
              ? attributeConfig.process(_nextProp)
              : _nextProp;
          updatePayload[propKey] = nextValue;
        }
        removedKeys[propKey] = false;
        removedKeyCount--;
      }
    }
  }
  
  function diffNestedArrayProperty(
    updatePayload,
    prevArray,
    nextArray,
    validAttributes
  ) {
    var minLength =
      prevArray.length < nextArray.length ? prevArray.length : nextArray.length;
    var i = void 0;
    for (i = 0; i < minLength; i++) {
      // Diff any items in the array in the forward direction. Repeated keys
      // will be overwritten by later values.
      updatePayload = diffNestedProperty(
        updatePayload,
        prevArray[i],
        nextArray[i],
        validAttributes
      );
    }
    for (; i < prevArray.length; i++) {
      // Clear out all remaining properties.
      updatePayload = clearNestedProperty(
        updatePayload,
        prevArray[i],
        validAttributes
      );
    }
    for (; i < nextArray.length; i++) {
      // Add all remaining properties.
      updatePayload = addNestedProperty(
        updatePayload,
        nextArray[i],
        validAttributes
      );
    }
    return updatePayload;
  }
  
  function diffNestedProperty(
    updatePayload,
    prevProp,
    nextProp,
    validAttributes
  ) {
    if (!updatePayload && prevProp === nextProp) {
      // If no properties have been added, then we can bail out quickly on object
      // equality.
      return updatePayload;
    }
  
    if (!prevProp || !nextProp) {
      if (nextProp) {
        return addNestedProperty(updatePayload, nextProp, validAttributes);
      }
      if (prevProp) {
        return clearNestedProperty(updatePayload, prevProp, validAttributes);
      }
      return updatePayload;
    }
  
    if (!Array.isArray(prevProp) && !Array.isArray(nextProp)) {
      // Both are leaves, we can diff the leaves.
      return diffProperties(
        updatePayload,
        resolveObject(prevProp),
        resolveObject(nextProp),
        validAttributes
      );
    }
  
    if (Array.isArray(prevProp) && Array.isArray(nextProp)) {
      // Both are arrays, we can diff the arrays.
      return diffNestedArrayProperty(
        updatePayload,
        prevProp,
        nextProp,
        validAttributes
      );
    }
  
    if (Array.isArray(prevProp)) {
      return diffProperties(
        updatePayload,
        // $FlowFixMe - We know that this is always an object when the input is.
        flattenStyle(prevProp),
        // $FlowFixMe - We know that this isn't an array because of above flow.
        resolveObject(nextProp),
        validAttributes
      );
    }
  
    return diffProperties(
      updatePayload,
      resolveObject(prevProp),
      // $FlowFixMe - We know that this is always an object when the input is.
      flattenStyle(nextProp),
      validAttributes
    );
  }
  
  /**
   * addNestedProperty takes a single set of props and valid attribute
   * attribute configurations. It processes each prop and adds it to the
   * updatePayload.
   */
  function addNestedProperty(updatePayload, nextProp, validAttributes) {
    if (!nextProp) {
      return updatePayload;
    }
  
    if (!Array.isArray(nextProp)) {
      // Add each property of the leaf.
      return addProperties(
        updatePayload,
        resolveObject(nextProp),
        validAttributes
      );
    }
  
    for (var i = 0; i < nextProp.length; i++) {
      // Add all the properties of the array.
      updatePayload = addNestedProperty(
        updatePayload,
        nextProp[i],
        validAttributes
      );
    }
  
    return updatePayload;
  }
  
  /**
   * clearNestedProperty takes a single set of props and valid attributes. It
   * adds a null sentinel to the updatePayload, for each prop key.
   */
  function clearNestedProperty(updatePayload, prevProp, validAttributes) {
    if (!prevProp) {
      return updatePayload;
    }
  
    if (!Array.isArray(prevProp)) {
      // Add each property of the leaf.
      return clearProperties(
        updatePayload,
        resolveObject(prevProp),
        validAttributes
      );
    }
  
    for (var i = 0; i < prevProp.length; i++) {
      // Add all the properties of the array.
      updatePayload = clearNestedProperty(
        updatePayload,
        prevProp[i],
        validAttributes
      );
    }
    return updatePayload;
  }
  
  /**
   * diffProperties takes two sets of props and a set of valid attributes
   * and write to updatePayload the values that changed or were deleted.
   * If no updatePayload is provided, a new one is created and returned if
   * anything changed.
   */
  function diffProperties(updatePayload, prevProps, nextProps, validAttributes) {
    var attributeConfig = void 0;
    var nextProp = void 0;
    var prevProp = void 0;
  
    for (var propKey in nextProps) {
      attributeConfig = validAttributes[propKey];
      if (!attributeConfig) {
        continue; // not a valid native prop
      }
  
      prevProp = prevProps[propKey];
      nextProp = nextProps[propKey];
  
      // functions are converted to booleans as markers that the associated
      // events should be sent from native.
      if (typeof nextProp === "function") {
        nextProp = true;
        // If nextProp is not a function, then don't bother changing prevProp
        // since nextProp will win and go into the updatePayload regardless.
        if (typeof prevProp === "function") {
          prevProp = true;
        }
      }
  
      // An explicit value of undefined is treated as a null because it overrides
      // any other preceding value.
      if (typeof nextProp === "undefined") {
        nextProp = null;
        if (typeof prevProp === "undefined") {
          prevProp = null;
        }
      }
  
      if (removedKeys) {
        removedKeys[propKey] = false;
      }
  
      if (updatePayload && updatePayload[propKey] !== undefined) {
        // Something else already triggered an update to this key because another
        // value diffed. Since we're now later in the nested arrays our value is
        // more important so we need to calculate it and override the existing
        // value. It doesn't matter if nothing changed, we'll set it anyway.
  
        // Pattern match on: attributeConfig
        if (typeof attributeConfig !== "object") {
          // case: !Object is the default case
          updatePayload[propKey] = nextProp;
        } else if (
          typeof attributeConfig.diff === "function" ||
          typeof attributeConfig.process === "function"
        ) {
          // case: CustomAttributeConfiguration
          var nextValue =
            typeof attributeConfig.process === "function"
              ? attributeConfig.process(nextProp)
              : nextProp;
          updatePayload[propKey] = nextValue;
        }
        continue;
      }
  
      if (prevProp === nextProp) {
        continue; // nothing changed
      }
  
      // Pattern match on: attributeConfig
      if (typeof attributeConfig !== "object") {
        // case: !Object is the default case
        if (defaultDiffer(prevProp, nextProp)) {
          // a normal leaf has changed
          (updatePayload || (updatePayload = {}))[propKey] = nextProp;
        }
      } else if (
        typeof attributeConfig.diff === "function" ||
        typeof attributeConfig.process === "function"
      ) {
        // case: CustomAttributeConfiguration
        var shouldUpdate =
          prevProp === undefined ||
          (typeof attributeConfig.diff === "function"
            ? attributeConfig.diff(prevProp, nextProp)
            : defaultDiffer(prevProp, nextProp));
        if (shouldUpdate) {
          var _nextValue =
            typeof attributeConfig.process === "function"
              ? attributeConfig.process(nextProp)
              : nextProp;
          (updatePayload || (updatePayload = {}))[propKey] = _nextValue;
        }
      } else {
        // default: fallthrough case when nested properties are defined
        removedKeys = null;
        removedKeyCount = 0;
        // We think that attributeConfig is not CustomAttributeConfiguration at
        // this point so we assume it must be AttributeConfiguration.
        updatePayload = diffNestedProperty(
          updatePayload,
          prevProp,
          nextProp,
          attributeConfig
        );
        if (removedKeyCount > 0 && updatePayload) {
          restoreDeletedValuesInNestedArray(
            updatePayload,
            nextProp,
            attributeConfig
          );
          removedKeys = null;
        }
      }
    }
  
    // Also iterate through all the previous props to catch any that have been
    // removed and make sure native gets the signal so it can reset them to the
    // default.
    for (var _propKey in prevProps) {
      if (nextProps[_propKey] !== undefined) {
        continue; // we've already covered this key in the previous pass
      }
      attributeConfig = validAttributes[_propKey];
      if (!attributeConfig) {
        continue; // not a valid native prop
      }
  
      if (updatePayload && updatePayload[_propKey] !== undefined) {
        // This was already updated to a diff result earlier.
        continue;
      }
  
      prevProp = prevProps[_propKey];
      if (prevProp === undefined) {
        continue; // was already empty anyway
      }
      // Pattern match on: attributeConfig
      if (
        typeof attributeConfig !== "object" ||
        typeof attributeConfig.diff === "function" ||
        typeof attributeConfig.process === "function"
      ) {
        // case: CustomAttributeConfiguration | !Object
        // Flag the leaf property for removal by sending a sentinel.
        (updatePayload || (updatePayload = {}))[_propKey] = null;
        if (!removedKeys) {
          removedKeys = {};
        }
        if (!removedKeys[_propKey]) {
          removedKeys[_propKey] = true;
          removedKeyCount++;
        }
      } else {
        // default:
        // This is a nested attribute configuration where all the properties
        // were removed so we need to go through and clear out all of them.
        updatePayload = clearNestedProperty(
          updatePayload,
          prevProp,
          attributeConfig
        );
      }
    }
    return updatePayload;
  }
  
  /**
   * addProperties adds all the valid props to the payload after being processed.
   */
  function addProperties(updatePayload, props, validAttributes) {
    // TODO: Fast path
    return diffProperties(updatePayload, emptyObject$1, props, validAttributes);
  }
  
  /**
   * clearProperties clears all the previous props by adding a null sentinel
   * to the payload for each valid key.
   */
  function clearProperties(updatePayload, prevProps, validAttributes) {
    // TODO: Fast path
    return diffProperties(
      updatePayload,
      prevProps,
      emptyObject$1,
      validAttributes
    );
  }
  
  function create(props, validAttributes) {
    return addProperties(
      null, // updatePayload
      props,
      validAttributes
    );
  }
  
  function diff(prevProps, nextProps, validAttributes) {
    return diffProperties(
      null, // updatePayload
      prevProps,
      nextProps,
      validAttributes
    );
  }
  
  /**
   * In the future, we should cleanup callbacks by cancelling them instead of
   * using this.
   */
  function mountSafeCallback(context, callback) {
    return function() {
      if (!callback) {
        return undefined;
      }
      if (typeof context.__isMounted === "boolean") {
        // TODO(gaearon): this is gross and should be removed.
        // It is currently necessary because View uses createClass,
        // and so any measure() calls on View (which are done by React
        // DevTools) trigger the isMounted() deprecation warning.
        if (!context.__isMounted) {
          return undefined;
        }
        // The else branch is important so that we don't
        // trigger the deprecation warning by calling isMounted.
      } else if (typeof context.isMounted === "function") {
        if (!context.isMounted()) {
          return undefined;
        }
      }
      return callback.apply(context, arguments);
    };
  }
  
  function throwOnStylesProp(component, props) {
    if (props.styles !== undefined) {
      var owner = component._owner || null;
      var name = component.constructor.displayName;
      var msg =
        "`styles` is not a supported property of `" +
        name +
        "`, did " +
        "you mean `style` (singular)?";
      if (owner && owner.constructor && owner.constructor.displayName) {
        msg +=
          "\n\nCheck the `" +
          owner.constructor.displayName +
          "` parent " +
          " component.";
      }
      throw new Error(msg);
    }
  }
  
  function warnForStyleProps(props, validAttributes) {
    for (var key in validAttributes.style) {
      if (!(validAttributes[key] || props[key] === undefined)) {
        console.error(
          "You are setting the style `{ " +
            key +
            ": ... }` as a prop. You " +
            "should nest it in a style object. " +
            "E.g. `{ style: { " +
            key +
            ": ... } }`"
        );
      }
    }
  }
  
  /**
   * `ReactInstanceMap` maintains a mapping from a public facing stateful
   * instance (key) and the internal representation (value). This allows public
   * methods to accept the user facing instance as an argument and map them back
   * to internal methods.
   *
   * Note that this module is currently shared and assumed to be stateless.
   * If this becomes an actual Map, that will break.
   */
  
  /**
   * This API should be called `delete` but we'd have to make sure to always
   * transform these to strings for IE support. When this transform is fully
   * supported we can rename it.
   */
  
  function get(key) {
    return key._reactInternalFiber;
  }
  
  function set(key, value) {
    key._reactInternalFiber = value;
  }
  
  function getComponentName(fiber) {
    var type = fiber.type;
  
    if (typeof type === "function") {
      return type.displayName || type.name;
    }
    if (typeof type === "string") {
      return type;
    }
    switch (type) {
      case REACT_FRAGMENT_TYPE:
        return "ReactFragment";
      case REACT_PORTAL_TYPE:
        return "ReactPortal";
      case REACT_CALL_TYPE:
        return "ReactCall";
      case REACT_RETURN_TYPE:
        return "ReactReturn";
    }
    return null;
  }
  
  // TODO: Share this module between Fabric and React Native renderers
  // so that both can be used in the same tree.
  
  var findHostInstance = function(fiber) {
    return null;
  };
  
  var findHostInstanceFabric = function(fiber) {
    return null;
  };
  
  function injectFindHostInstanceFabric(impl) {
    findHostInstanceFabric = impl;
  }
  
  /**
   * ReactNative vs ReactWeb
   * -----------------------
   * React treats some pieces of data opaquely. This means that the information
   * is first class (it can be passed around), but cannot be inspected. This
   * allows us to build infrastructure that reasons about resources, without
   * making assumptions about the nature of those resources, and this allows that
   * infra to be shared across multiple platforms, where the resources are very
   * different. General infra (such as `ReactMultiChild`) reasons opaquely about
   * the data, but platform specific code (such as `ReactNativeBaseComponent`) can
   * make assumptions about the data.
   *
   *
   * `rootNodeID`, uniquely identifies a position in the generated native view
   * tree. Many layers of composite components (created with `React.createClass`)
   * can all share the same `rootNodeID`.
   *
   * `nodeHandle`: A sufficiently unambiguous way to refer to a lower level
   * resource (dom node, native view etc). The `rootNodeID` is sufficient for web
   * `nodeHandle`s, because the position in a tree is always enough to uniquely
   * identify a DOM node (we never have nodes in some bank outside of the
   * document). The same would be true for `ReactNative`, but we must maintain a
   * mapping that we can send efficiently serializable
   * strings across native boundaries.
   *
   * Opaque name      TodaysWebReact   FutureWebWorkerReact   ReactNative
   * ----------------------------------------------------------------------------
   * nodeHandle       N/A              rootNodeID             tag
   */
  
  // TODO (bvaughn) Rename the findNodeHandle module to something more descriptive
  // eg findInternalHostInstance. This will reduce the likelihood of someone
  // accidentally deep-requiring this version.
  function findNodeHandle(componentOrHandle) {
    {
      var owner = ReactCurrentOwner.current;
      if (owner !== null && owner.stateNode !== null) {
        warning(
          owner.stateNode._warnedAboutRefsInRender,
          "%s is accessing findNodeHandle inside its render(). " +
            "render() should be a pure function of props and state. It should " +
            "never access something that requires stale data from the previous " +
            "render, such as refs. Move this logic to componentDidMount and " +
            "componentDidUpdate instead.",
          getComponentName(owner) || "A component"
        );
  
        owner.stateNode._warnedAboutRefsInRender = true;
      }
    }
    if (componentOrHandle == null) {
      return null;
    }
    if (typeof componentOrHandle === "number") {
      // Already a node handle
      return componentOrHandle;
    }
  
    var component = componentOrHandle;
  
    // TODO (balpert): Wrap iOS native components in a composite wrapper, then
    // ReactInstanceMap.get here will always succeed for mounted components
    var internalInstance = get(component);
    if (internalInstance) {
      return (
        findHostInstance(internalInstance) ||
        findHostInstanceFabric(internalInstance)
      );
    } else {
      if (component) {
        return component;
      } else {
        invariant(
          // Native
          (typeof component === "object" && "_nativeTag" in component) ||
            // Composite
            (component.render != null && typeof component.render === "function"),
          "findNodeHandle(...): Argument is not a component " +
            "(type: %s, keys: %s)",
          typeof component,
          Object.keys(component)
        );
        invariant(
          false,
          "findNodeHandle(...): Unable to find node handle for unmounted " +
            "component."
        );
      }
    }
  }
  
  /**
   * External users of findNodeHandle() expect the host tag number return type.
   * The injected findNodeHandle() strategy returns the instance wrapper though.
   * See NativeMethodsMixin#setNativeProps for more info on why this is done.
   */
  function findNumericNodeHandleFiber(componentOrHandle) {
    var instance = findNodeHandle(componentOrHandle);
    if (instance == null || typeof instance === "number") {
      return instance;
    }
    return instance._nativeTag;
  }
  
  // Modules provided by RN:
  /**
   * `NativeMethodsMixin` provides methods to access the underlying native
   * component directly. This can be useful in cases when you want to focus
   * a view or measure its on-screen dimensions, for example.
   *
   * The methods described here are available on most of the default components
   * provided by React Native. Note, however, that they are *not* available on
   * composite components that aren't directly backed by a native view. This will
   * generally include most components that you define in your own app. For more
   * information, see [Direct
   * Manipulation](docs/direct-manipulation.html).
   *
   * Note the Flow $Exact<> syntax is required to support mixins.
   * React createClass mixins can only be used with exact types.
   */
  var NativeMethodsMixin = {
    /**
     * Determines the location on screen, width, and height of the given view and
     * returns the values via an async callback. If successful, the callback will
     * be called with the following arguments:
     *
     *  - x
     *  - y
     *  - width
     *  - height
     *  - pageX
     *  - pageY
     *
     * Note that these measurements are not available until after the rendering
     * has been completed in native. If you need the measurements as soon as
     * possible, consider using the [`onLayout`
     * prop](docs/view.html#onlayout) instead.
     */
    measure: function(callback) {
      UIManager.measure(
        findNumericNodeHandleFiber(this),
        mountSafeCallback(this, callback)
      );
    },
  
    /**
     * Determines the location of the given view in the window and returns the
     * values via an async callback. If the React root view is embedded in
     * another native view, this will give you the absolute coordinates. If
     * successful, the callback will be called with the following
     * arguments:
     *
     *  - x
     *  - y
     *  - width
     *  - height
     *
     * Note that these measurements are not available until after the rendering
     * has been completed in native.
     */
    measureInWindow: function(callback) {
      UIManager.measureInWindow(
        findNumericNodeHandleFiber(this),
        mountSafeCallback(this, callback)
      );
    },
  
    /**
     * Like [`measure()`](#measure), but measures the view relative an ancestor,
     * specified as `relativeToNativeNode`. This means that the returned x, y
     * are relative to the origin x, y of the ancestor view.
     *
     * As always, to obtain a native node handle for a component, you can use
     * `findNumericNodeHandle(component)`.
     */
    measureLayout: function(
      relativeToNativeNode,
      onSuccess,
      onFail /* currently unused */
    ) {
      UIManager.measureLayout(
        findNumericNodeHandleFiber(this),
        relativeToNativeNode,
        mountSafeCallback(this, onFail),
        mountSafeCallback(this, onSuccess)
      );
    },
  
    /**
     * This function sends props straight to native. They will not participate in
     * future diff process - this means that if you do not include them in the
     * next render, they will remain active (see [Direct
     * Manipulation](docs/direct-manipulation.html)).
     */
    setNativeProps: function(nativeProps) {
      // Class components don't have viewConfig -> validateAttributes.
      // Nor does it make sense to set native props on a non-native component.
      // Instead, find the nearest host component and set props on it.
      // Use findNodeHandle() rather than findNumericNodeHandle() because
      // We want the instance/wrapper (not the native tag).
      var maybeInstance = void 0;
  
      // Fiber errors if findNodeHandle is called for an umounted component.
      // Tests using ReactTestRenderer will trigger this case indirectly.
      // Mimicking stack behavior, we should silently ignore this case.
      // TODO Fix ReactTestRenderer so we can remove this try/catch.
      try {
        maybeInstance = findNodeHandle(this);
      } catch (error) {}
  
      // If there is no host component beneath this we should fail silently.
      // This is not an error; it could mean a class component rendered null.
      if (maybeInstance == null) {
        return;
      }
  
      var viewConfig = maybeInstance.viewConfig;
  
      {
        warnForStyleProps(nativeProps, viewConfig.validAttributes);
      }
  
      var updatePayload = create(nativeProps, viewConfig.validAttributes);
  
      // Avoid the overhead of bridge calls if there's no update.
      // This is an expensive no-op for Android, and causes an unnecessary
      // view invalidation for certain components (eg RCTTextInput) on iOS.
      if (updatePayload != null) {
        UIManager.updateView(
          maybeInstance._nativeTag,
          viewConfig.uiViewClassName,
          updatePayload
        );
      }
    },
  
    /**
     * Requests focus for the given input or view. The exact behavior triggered
     * will depend on the platform and type of view.
     */
    focus: function() {
      TextInputState.focusTextInput(findNumericNodeHandleFiber(this));
    },
  
    /**
     * Removes focus from an input or view. This is the opposite of `focus()`.
     */
    blur: function() {
      TextInputState.blurTextInput(findNumericNodeHandleFiber(this));
    }
  };
  
  {
    // hide this from Flow since we can't define these properties outside of
    // true without actually implementing them (setting them to undefined
    // isn't allowed by ReactClass)
    var NativeMethodsMixin_DEV = NativeMethodsMixin;
    invariant(
      !NativeMethodsMixin_DEV.componentWillMount &&
        !NativeMethodsMixin_DEV.componentWillReceiveProps &&
        !NativeMethodsMixin_DEV.UNSAFE_componentWillMount &&
        !NativeMethodsMixin_DEV.UNSAFE_componentWillReceiveProps,
      "Do not override existing functions."
    );
    NativeMethodsMixin_DEV.componentWillMount = function() {
      throwOnStylesProp(this, this.props);
    };
    NativeMethodsMixin_DEV.componentWillReceiveProps = function(newProps) {
      throwOnStylesProp(this, newProps);
    };
    NativeMethodsMixin_DEV.UNSAFE_componentWillMount = function() {
      throwOnStylesProp(this, this.props);
    };
    NativeMethodsMixin_DEV.UNSAFE_componentWillReceiveProps = function(newProps) {
      throwOnStylesProp(this, newProps);
    };
  }
  
  function _classCallCheck$1(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }
  
  function _possibleConstructorReturn(self, call) {
    if (!self) {
      throw new ReferenceError(
        "this hasn't been initialised - super() hasn't been called"
      );
    }
    return call && (typeof call === "object" || typeof call === "function")
      ? call
      : self;
  }
  
  function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError(
        "Super expression must either be null or a function, not " +
          typeof superClass
      );
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (superClass)
      Object.setPrototypeOf
        ? Object.setPrototypeOf(subClass, superClass)
        : (subClass.__proto__ = superClass);
  }
  
  // Modules provided by RN:
  /**
   * Superclass that provides methods to access the underlying native component.
   * This can be useful when you want to focus a view or measure its dimensions.
   *
   * Methods implemented by this class are available on most default components
   * provided by React Native. However, they are *not* available on composite
   * components that are not directly backed by a native view. For more
   * information, see [Direct Manipulation](docs/direct-manipulation.html).
   *
   * @abstract
   */
  
  var ReactNativeComponent = (function(_React$Component) {
    _inherits(ReactNativeComponent, _React$Component);
  
    function ReactNativeComponent() {
      _classCallCheck$1(this, ReactNativeComponent);
  
      return _possibleConstructorReturn(
        this,
        _React$Component.apply(this, arguments)
      );
    }
  
    /**
     * Removes focus. This is the opposite of `focus()`.
     */
    ReactNativeComponent.prototype.blur = function blur() {
      TextInputState.blurTextInput(findNumericNodeHandleFiber(this));
    };
  
    /**
     * Requests focus. The exact behavior depends on the platform and view.
     */
  
    ReactNativeComponent.prototype.focus = function focus() {
      TextInputState.focusTextInput(findNumericNodeHandleFiber(this));
    };
  
    /**
     * Measures the on-screen location and dimensions. If successful, the callback
     * will be called asynchronously with the following arguments:
     *
     *  - x
     *  - y
     *  - width
     *  - height
     *  - pageX
     *  - pageY
     *
     * These values are not available until after natives rendering completes. If
     * you need the measurements as soon as possible, consider using the
     * [`onLayout` prop](docs/view.html#onlayout) instead.
     */
  
    ReactNativeComponent.prototype.measure = function measure(callback) {
      UIManager.measure(
        findNumericNodeHandleFiber(this),
        mountSafeCallback(this, callback)
      );
    };
  
    /**
     * Measures the on-screen location and dimensions. Even if the React Native
     * root view is embedded within another native view, this method will give you
     * the absolute coordinates measured from the window. If successful, the
     * callback will be called asynchronously with the following arguments:
     *
     *  - x
     *  - y
     *  - width
     *  - height
     *
     * These values are not available until after natives rendering completes.
     */
  
    ReactNativeComponent.prototype.measureInWindow = function measureInWindow(
      callback
    ) {
      UIManager.measureInWindow(
        findNumericNodeHandleFiber(this),
        mountSafeCallback(this, callback)
      );
    };
  
    /**
     * Similar to [`measure()`](#measure), but the resulting location will be
     * relative to the supplied ancestor's location.
     *
     * Obtain a native node handle with `ReactNative.findNodeHandle(component)`.
     */
  
    ReactNativeComponent.prototype.measureLayout = function measureLayout(
      relativeToNativeNode,
      onSuccess,
      onFail /* currently unused */
    ) {
      UIManager.measureLayout(
        findNumericNodeHandleFiber(this),
        relativeToNativeNode,
        mountSafeCallback(this, onFail),
        mountSafeCallback(this, onSuccess)
      );
    };
  
    /**
     * This function sends props straight to native. They will not participate in
     * future diff process - this means that if you do not include them in the
     * next render, they will remain active (see [Direct
     * Manipulation](docs/direct-manipulation.html)).
     */
  
    ReactNativeComponent.prototype.setNativeProps = function setNativeProps(
      nativeProps
    ) {
      // Class components don't have viewConfig -> validateAttributes.
      // Nor does it make sense to set native props on a non-native component.
      // Instead, find the nearest host component and set props on it.
      // Use findNodeHandle() rather than ReactNative.findNodeHandle() because
      // We want the instance/wrapper (not the native tag).
      var maybeInstance = void 0;
  
      // Fiber errors if findNodeHandle is called for an umounted component.
      // Tests using ReactTestRenderer will trigger this case indirectly.
      // Mimicking stack behavior, we should silently ignore this case.
      // TODO Fix ReactTestRenderer so we can remove this try/catch.
      try {
        maybeInstance = findNodeHandle(this);
      } catch (error) {}
  
      // If there is no host component beneath this we should fail silently.
      // This is not an error; it could mean a class component rendered null.
      if (maybeInstance == null) {
        return;
      }
  
      var viewConfig =
        maybeInstance.viewConfig || maybeInstance.canonical.viewConfig;
  
      var updatePayload = create(nativeProps, viewConfig.validAttributes);
  
      // Avoid the overhead of bridge calls if there's no update.
      // This is an expensive no-op for Android, and causes an unnecessary
      // view invalidation for certain components (eg RCTTextInput) on iOS.
      if (updatePayload != null) {
        UIManager.updateView(
          maybeInstance._nativeTag,
          viewConfig.uiViewClassName,
          updatePayload
        );
      }
    };
  
    return ReactNativeComponent;
  })(React.Component);
  
  var hasNativePerformanceNow =
    typeof performance === "object" && typeof performance.now === "function";
  
  var now = hasNativePerformanceNow
    ? function() {
        return performance.now();
      }
    : function() {
        return Date.now();
      };
  
  var scheduledCallback = null;
  var frameDeadline = 0;
  
  var frameDeadlineObject = {
    timeRemaining: function() {
      return frameDeadline - now();
    }
  };
  
  function setTimeoutCallback() {
    // TODO (bvaughn) Hard-coded 5ms unblocks initial async testing.
    // React API probably changing to boolean rather than time remaining.
    // Longer-term plan is to rewrite this using shared memory,
    // And just return the value of the bit as the boolean.
    frameDeadline = now() + 5;
  
    var callback = scheduledCallback;
    scheduledCallback = null;
    if (callback !== null) {
      callback(frameDeadlineObject);
    }
  }
  
  // RN has a poor polyfill for requestIdleCallback so we aren't using it.
  // This implementation is only intended for short-term use anyway.
  // We also don't implement cancel functionality b'c Fiber doesn't currently need it.
  function scheduleDeferredCallback(callback) {
    // We assume only one callback is scheduled at a time b'c that's how Fiber works.
    scheduledCallback = callback;
    return setTimeout(setTimeoutCallback, 1);
  }
  
  function cancelDeferredCallback(callbackID) {
    scheduledCallback = null;
    clearTimeout(callbackID);
  }
  
  var viewConfigCallbacks = new Map();
  var viewConfigs = new Map();
  
  /**
   * Registers a native view/component by name.
   * A callback is provided to load the view config from UIManager.
   * The callback is deferred until the view is actually rendered.
   * This is done to avoid causing Prepack deopts.
   */
  function register(name, callback) {
    invariant(
      !viewConfigCallbacks.has(name),
      "Tried to register two views with the same name %s",
      name
    );
    viewConfigCallbacks.set(name, callback);
    return name;
  }
  
  /**
   * Retrieves a config for the specified view.
   * If this is the first time the view has been used,
   * This configuration will be lazy-loaded from UIManager.
   */
  function get$1(name) {
    var viewConfig = void 0;
    if (!viewConfigs.has(name)) {
      var callback = viewConfigCallbacks.get(name);
      invariant(
        typeof callback === "function",
        "View config not found for name %s",
        name
      );
      viewConfigCallbacks.set(name, null);
      viewConfig = callback();
      viewConfigs.set(name, viewConfig);
    } else {
      viewConfig = viewConfigs.get(name);
    }
    invariant(viewConfig, "View config not found for name %s", name);
    return viewConfig;
  }
  
  // Don't change these two values:
  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 Err = 64;
  var Ref = 128;
  
  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 owner = ReactCurrentOwner.current;
      if (owner !== null && owner.tag === ClassComponent) {
        var ownerFiber = owner;
        var instance = ownerFiber.stateNode;
        warning(
          instance._warnedAboutRefsInRender,
          "%s is accessing isMounted inside its render() function. " +
            "render() should be a pure function of props and state. It should " +
            "never access something that requires stale data from the previous " +
            "render, such as refs. Move this logic to componentDidMount and " +
            "componentDidUpdate instead.",
          getComponentName(ownerFiber) || "A component"
        );
        instance._warnedAboutRefsInRender = true;
      }
    }
  
    var fiber = get(component);
    if (!fiber) {
      return false;
    }
    return isFiberMountedImpl(fiber) === MOUNTED;
  }
  
  function assertIsMounted(fiber) {
    invariant(
      isFiberMountedImpl(fiber) === MOUNTED,
      "Unable to find node on an unmounted component."
    );
  }
  
  function findCurrentFiberUsingSlowPath(fiber) {
    var alternate = fiber.alternate;
    if (!alternate) {
      // If there is no alternate, then we only need to check if it is mounted.
      var state = isFiberMountedImpl(fiber);
      invariant(
        state !== UNMOUNTED,
        "Unable to find node on an unmounted component."
      );
      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.
        invariant(false, "Unable to find node on an unmounted component.");
      }
  
      if (a["return"] !== b["return"]) {
        // The return pointer of A and the return pointer of B point to different
        // fibers. We assume that return pointers never criss-cross, so A must
        // belong to the child set of A.return, and B must belong to the child
        // set of B.return.
        a = parentA;
        b = parentB;
      } else {
        // The return pointers point to the same fiber. We'll have to use the
        // default, slow path: scan the child sets of each parent alternate to see
        // which child belongs to which set.
        //
        // Search parent A's child set
        var didFindChild = false;
        var _child = parentA.child;
        while (_child) {
          if (_child === a) {
            didFindChild = true;
            a = parentA;
            b = parentB;
            break;
          }
          if (_child === b) {
            didFindChild = true;
            b = parentA;
            a = parentB;
            break;
          }
          _child = _child.sibling;
        }
        if (!didFindChild) {
          // Search parent B's child set
          _child = parentB.child;
          while (_child) {
            if (_child === a) {
              didFindChild = true;
              a = parentB;
              b = parentA;
              break;
            }
            if (_child === b) {
              didFindChild = true;
              b = parentB;
              a = parentA;
              break;
            }
            _child = _child.sibling;
          }
          invariant(
            didFindChild,
            "Child was not found in either parent set. This indicates a bug " +
              "in React related to the return pointer. Please file an issue."
          );
        }
      }
  
      invariant(
        a.alternate === b,
        "Return fibers should always be each others' alternates. " +
          "This error is likely caused by a bug in React. Please file an issue."
      );
    }
    // If the root is not a host container, we're in a disconnected tree. I.e.
    // unmounted.
    invariant(
      a.tag === HostRoot,
      "Unable to find node on an unmounted component."
    );
    if (a.stateNode.current === a) {
      // We've determined that A is the current branch.
      return fiber;
    }
    // Otherwise B has to be current branch.
    return alternate;
  }
  
  function findCurrentHostFiber(parent) {
    var currentParent = findCurrentFiberUsingSlowPath(parent);
    if (!currentParent) {
      return null;
    }
  
    // Next we'll drill down this component to find the first HostComponent/Text.
    var node = currentParent;
    while (true) {
      if (node.tag === HostComponent || node.tag === HostText) {
        return node;
      } else if (node.child) {
        node.child["return"] = node;
        node = node.child;
        continue;
      }
      if (node === currentParent) {
        return null;
      }
      while (!node.sibling) {
        if (!node["return"] || node["return"] === currentParent) {
          return null;
        }
        node = node["return"];
      }
      node.sibling["return"] = node["return"];
      node = node.sibling;
    }
    // Flow needs the return null here, but ESLint complains about it.
    // eslint-disable-next-line no-unreachable
    return null;
  }
  
  function findCurrentHostFiberWithNoPortals(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.tag !== HostPortal) {
        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;
  }
  
  var valueStack = [];
  
  var fiberStack = void 0;
  
  {
    fiberStack = [];
  }
  
  var index = -1;
  
  function createCursor(defaultValue) {
    return {
      current: defaultValue
    };
  }
  
  function pop(cursor, fiber) {
    if (index < 0) {
      {
        warning(false, "Unexpected pop.");
      }
      return;
    }
  
    {
      if (fiber !== fiberStack[index]) {
        warning(false, "Unexpected Fiber popped.");
      }
    }
  
    cursor.current = valueStack[index];
  
    valueStack[index] = null;
  
    {
      fiberStack[index] = null;
    }
  
    index--;
  }
  
  function push(cursor, value, fiber) {
    index++;
  
    valueStack[index] = cursor.current;
  
    {
      fiberStack[index] = fiber;
    }
  
    cursor.current = value;
  }
  
  function reset() {
    while (index > -1) {
      valueStack[index] = null;
  
      {
        fiberStack[index] = null;
      }
  
      index--;
    }
  }
  
  var describeComponentFrame = function(name, source, ownerName) {
    return (
      "\n    in " +
      (name || "Unknown") +
      (source
        ? " (at " +
          source.fileName.replace(/^.*[\\\/]/, "") +
          ":" +
          source.lineNumber +
          ")"
        : ownerName ? " (created by " + ownerName + ")" : "")
    );
  };
  
  function describeFiber(fiber) {
    switch (fiber.tag) {
      case IndeterminateComponent:
      case FunctionalComponent:
      case ClassComponent:
      case HostComponent:
        var owner = fiber._debugOwner;
        var source = fiber._debugSource;
        var name = getComponentName(fiber);
        var ownerName = null;
        if (owner) {
          ownerName = getComponentName(owner);
        }
        return describeComponentFrame(name, source, ownerName);
      default:
        return "";
    }
  }
  
  // This function can only be called with a work-in-progress fiber and
  // only during begin or complete phase. Do not call it under any other
  // circumstances.
  function getStackAddendumByWorkInProgressFiber(workInProgress) {
    var info = "";
    var node = workInProgress;
    do {
      info += describeFiber(node);
      // Otherwise this return pointer might point to the wrong tree:
      node = node["return"];
    } while (node);
    return info;
  }
  
  function getCurrentFiberOwnerName() {
    {
      var fiber = ReactDebugCurrentFiber.current;
      if (fiber === null) {
        return null;
      }
      var owner = fiber._debugOwner;
      if (owner !== null && typeof owner !== "undefined") {
        return getComponentName(owner);
      }
    }
    return null;
  }
  
  function getCurrentFiberStackAddendum() {
    {
      var fiber = ReactDebugCurrentFiber.current;
      if (fiber === null) {
        return null;
      }
      // Safe because if current fiber exists, we are reconciling,
      // and it is guaranteed to be the work-in-progress version.
      return getStackAddendumByWorkInProgressFiber(fiber);
    }
    return null;
  }
  
  function resetCurrentFiber() {
    ReactDebugCurrentFrame.getCurrentStack = null;
    ReactDebugCurrentFiber.current = null;
    ReactDebugCurrentFiber.phase = null;
  }
  
  function setCurrentFiber(fiber) {
    ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum;
    ReactDebugCurrentFiber.current = fiber;
    ReactDebugCurrentFiber.phase = null;
  }
  
  function setCurrentPhase(phase) {
    ReactDebugCurrentFiber.phase = phase;
  }
  
  var ReactDebugCurrentFiber = {
    current: null,
    phase: null,
    resetCurrentFiber: resetCurrentFiber,
    setCurrentFiber: setCurrentFiber,
    setCurrentPhase: setCurrentPhase,
    getCurrentFiberOwnerName: getCurrentFiberOwnerName,
    getCurrentFiberStackAddendum: getCurrentFiberStackAddendum
  };
  
  // Exports ReactDOM.createRoot
  
  var enableUserTimingAPI = true;
  
  // Mutating mode (React DOM, React ART, React Native):
  var enableMutatingReconciler = true;
  // Experimental noop mode (currently unused):
  var enableNoopReconciler = false;
  // Experimental persistent mode (Fabric):
  var enablePersistentReconciler = false;
  // Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
  var debugRenderPhaseSideEffects = false;
  
  // 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:
  var debugRenderPhaseSideEffectsForStrictMode = true;
  
  // Warn about deprecated, async-unsafe lifecycles; relates to RFC #6:
  var warnAboutDeprecatedLifecycles = false;
  
  // Only used in www builds.
  
  // Prefix measurements so that it's possible to filter them.
  // Longer prefixes are hard to read in DevTools.
  var reactEmoji = "\u269B";
  var warningEmoji = "\u26D4";
  var supportsUserTiming =
    typeof performance !== "undefined" &&
    typeof performance.mark === "function" &&
    typeof performance.clearMarks === "function" &&
    typeof performance.measure === "function" &&
    typeof performance.clearMeasures === "function";
  
  // Keep track of current fiber so that we know the path to unwind on pause.
  // TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them?
  var currentFiber = null;
  // If we're in the middle of user code, which fiber and method is it?
  // Reusing `currentFiber` would be confusing for this because user code fiber
  // can change during commit phase too, but we don't need to unwind it (since
  // lifecycles in the commit phase don't resemble a tree).
  var currentPhase = null;
  var currentPhaseFiber = null;
  // Did lifecycle hook schedule an update? This is often a performance problem,
  // so we will keep track of it, and include it in the report.
  // Track commits caused by cascading updates.
  var isCommitting = false;
  var hasScheduledUpdateInCurrentCommit = false;
  var hasScheduledUpdateInCurrentPhase = false;
  var commitCountInCurrentWorkLoop = 0;
  var effectCountInCurrentCommit = 0;
  var isWaitingForCallback = false;
  // During commits, we only show a measurement once per method name
  // to avoid stretch the commit phase with measurement overhead.
  var labelsInCurrentCommit = new Set();
  
  var formatMarkName = function(markName) {
    return reactEmoji + " " + markName;
  };
  
  var formatLabel = function(label, warning$$1) {
    var prefix = warning$$1 ? warningEmoji + " " : reactEmoji + " ";
    var suffix = warning$$1 ? " Warning: " + warning$$1 : "";
    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$$1) {
    var formattedMarkName = formatMarkName(markName);
    var formattedLabel = formatLabel(label, warning$$1);
    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) || "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) || "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$$1) {
    var componentName = getComponentName(fiber) || "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$$1);
  };
  
  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 CallComponent:
      case ReturnComponent:
      case Fragment:
        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) {
    if (enableUserTimingAPI) {
      if (supportsUserTiming) {
        isWaitingForCallback = false;
        var warning$$1 = didExpire ? "React was blocked by main thread" : null;
        endMark(
          "(Waiting for async callback...)",
          "(Waiting for async callback...)",
          warning$$1
        );
      }
    }
  }
  
  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$$1 = "An error was thrown inside this error boundary";
      endFiberMark(fiber, null, warning$$1);
    }
  }
  
  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$$1 = hasScheduledUpdateInCurrentPhase
          ? "Scheduled a cascading update"
          : null;
        endFiberMark(currentPhaseFiber, currentPhase, warning$$1);
      }
      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) {
    if (enableUserTimingAPI) {
      if (!supportsUserTiming) {
        return;
      }
      var warning$$1 = null;
      if (interruptedBy !== null) {
        if (interruptedBy.tag === HostRoot) {
          warning$$1 = "A top-level update interrupted the previous render";
        } else {
          var componentName = getComponentName(interruptedBy) || "Unknown";
          warning$$1 =
            "An update to " + componentName + " interrupted the previous render";
        }
      } else if (commitCountInCurrentWorkLoop > 1) {
        warning$$1 = "There were cascading updates";
      }
      commitCountInCurrentWorkLoop = 0;
      // Pause any measurements until the next loop.
      pauseTimers();
      endMark(
        "(React Tree Reconciliation)",
        "(React Tree Reconciliation)",
        warning$$1
      );
    }
  }
  
  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$$1 = null;
      if (hasScheduledUpdateInCurrentCommit) {
        warning$$1 = "Lifecycle hook scheduled a cascading update";
      } else if (commitCountInCurrentWorkLoop > 0) {
        warning$$1 = "Caused by a cascading update in earlier commit";
      }
      hasScheduledUpdateInCurrentCommit = false;
      commitCountInCurrentWorkLoop++;
      isCommitting = false;
      labelsInCurrentCommit.clear();
  
      endMark("(Committing Changes)", "(Committing Changes)", warning$$1);
    }
  }
  
  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 warnedAboutMissingGetChildContext = void 0;
  
  {
    warnedAboutMissingGetChildContext = {};
  }
  
  // A cursor to the current merged context object on the stack.
  var contextStackCursor = createCursor(emptyObject);
  // 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 = emptyObject;
  
  function getUnmaskedContext(workInProgress) {
    var hasOwnContext = isContextProvider(workInProgress);
    if (hasOwnContext) {
      // If the fiber is a context provider itself, when we read its context
      // we 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 emptyObject;
    }
  
    // Avoid recreating masked context unless unmasked context has changed.
    // Failing to do this will result in unnecessary calls to componentWillReceiveProps.
    // This may trigger infinite loops if componentWillReceiveProps calls setState.
    var instance = workInProgress.stateNode;
    if (
      instance &&
      instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext
    ) {
      return instance.__reactInternalMemoizedMaskedChildContext;
    }
  
    var context = {};
    for (var key in contextTypes) {
      context[key] = unmaskedContext[key];
    }
  
    {
      var name = getComponentName(workInProgress) || "Unknown";
      checkPropTypes(
        contextTypes,
        context,
        "context",
        name,
        ReactDebugCurrentFiber.getCurrentFiberStackAddendum
      );
    }
  
    // Cache unmasked context so we can avoid recreating masked context unless necessary.
    // Context is created before the class component is instantiated so check for instance.
    if (instance) {
      cacheContext(workInProgress, unmaskedContext, context);
    }
  
    return context;
  }
  
  function hasContextChanged() {
    return didPerformWorkStackCursor.current;
  }
  
  function isContextConsumer(fiber) {
    return fiber.tag === ClassComponent && fiber.type.contextTypes != null;
  }
  
  function isContextProvider(fiber) {
    return fiber.tag === ClassComponent && fiber.type.childContextTypes != null;
  }
  
  function popContextProvider(fiber) {
    if (!isContextProvider(fiber)) {
      return;
    }
  
    pop(didPerformWorkStackCursor, fiber);
    pop(contextStackCursor, fiber);
  }
  
  function popTopLevelContextObject(fiber) {
    pop(didPerformWorkStackCursor, fiber);
    pop(contextStackCursor, fiber);
  }
  
  function pushTopLevelContextObject(fiber, context, didChange) {
    invariant(
      contextStackCursor.cursor == null,
      "Unexpected context found on stack. " +
        "This error is likely caused by a bug in React. Please file an issue."
    );
  
    push(contextStackCursor, context, fiber);
    push(didPerformWorkStackCursor, didChange, fiber);
  }
  
  function processChildContext(fiber, parentContext) {
    var instance = fiber.stateNode;
    var childContextTypes = fiber.type.childContextTypes;
  
    // TODO (bvaughn) Replace this behavior with an invariant() in the future.
    // It has only been added in Fiber to match the (unintentional) behavior in Stack.
    if (typeof instance.getChildContext !== "function") {
      {
        var componentName = getComponentName(fiber) || "Unknown";
  
        if (!warnedAboutMissingGetChildContext[componentName]) {
          warnedAboutMissingGetChildContext[componentName] = true;
          warning(
            false,
            "%s.childContextTypes is specified but there is no getChildContext() method " +
              "on the instance. You can either define getChildContext() on %s or remove " +
              "childContextTypes from it.",
            componentName,
            componentName
          );
        }
      }
      return parentContext;
    }
  
    var childContext = void 0;
    {
      ReactDebugCurrentFiber.setCurrentPhase("getChildContext");
    }
    startPhaseTimer(fiber, "getChildContext");
    childContext = instance.getChildContext();
    stopPhaseTimer();
    {
      ReactDebugCurrentFiber.setCurrentPhase(null);
    }
    for (var contextKey in childContext) {
      invariant(
        contextKey in childContextTypes,
        '%s.getChildContext(): key "%s" is not defined in childContextTypes.',
        getComponentName(fiber) || "Unknown",
        contextKey
      );
    }
    {
      var name = getComponentName(fiber) || "Unknown";
      checkPropTypes(
        childContextTypes,
        childContext,
        "child context",
        name,
        // In practice, there is one case in which we won't get a stack. It's when
        // somebody calls unstable_renderSubtreeIntoContainer() and we process
        // context from the parent component instance. The stack will be missing
        // because it's outside of the reconciliation, and so the pointer has not
        // been set. This is rare and doesn't matter. We'll also remove that API.
        ReactDebugCurrentFiber.getCurrentFiberStackAddendum
      );
    }
  
    return Object.assign({}, parentContext, childContext);
  }
  
  function pushContextProvider(workInProgress) {
    if (!isContextProvider(workInProgress)) {
      return false;
    }
  
    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) ||
      emptyObject;
  
    // 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, didChange) {
    var instance = workInProgress.stateNode;
    invariant(
      instance,
      "Expected to have an instance by this point. " +
        "This error is likely caused by a bug in React. Please file an issue."
    );
  
    if (didChange) {
      // Merge parent and own context.
      // Skip this if we're not updating due to sCU.
      // This avoids unnecessarily recomputing memoized values.
      var mergedContext = processChildContext(workInProgress, 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 resetContext() {
    previousContext = emptyObject;
    contextStackCursor.current = emptyObject;
    didPerformWorkStackCursor.current = false;
  }
  
  function findCurrentUnmaskedContext(fiber) {
    // Currently this is only used with renderSubtreeIntoContainer; not sure if it
    // makes sense elsewhere
    invariant(
      isFiberMounted(fiber) && fiber.tag === ClassComponent,
      "Expected subtree parent to be a mounted class component. " +
        "This error is likely caused by a bug in React. Please file an issue."
    );
  
    var node = fiber;
    while (node.tag !== HostRoot) {
      if (isContextProvider(node)) {
        return node.stateNode.__reactInternalMemoizedMergedChildContext;
      }
      var parent = node["return"];
      invariant(
        parent,
        "Found unexpected detached subtree parent. " +
          "This error is likely caused by a bug in React. Please file an issue."
      );
      node = parent;
    }
    return node.stateNode.context;
  }
  
  // Max 31 bit integer. The max integer size in V8 for 32-bit systems.
  // Math.pow(2, 30) - 1
  // 0b111111111111111111111111111111
  var MAX_SIGNED_31_BIT_INT = 1073741823;
  
  // TODO: Use an opaque type once ESLint et al support the syntax
  
  var NoWork = 0;
  var Sync = 1;
  var Never = MAX_SIGNED_31_BIT_INT;
  
  var UNIT_SIZE = 10;
  var MAGIC_NUMBER_OFFSET = 2;
  
  // 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 ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET;
  }
  
  function expirationTimeToMs(expirationTime) {
    return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
  }
  
  function ceiling(num, precision) {
    return (((num / precision) | 0) + 1) * precision;
  }
  
  function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) {
    return ceiling(
      currentTime + expirationInMs / UNIT_SIZE,
      bucketSizeMs / UNIT_SIZE
    );
  }
  
  var NoContext = 0;
  var AsyncMode = 1;
  var StrictMode = 2;
  
  var hasBadMapPolyfill = void 0;
  
  {
    hasBadMapPolyfill = false;
    try {
      var nonExtensibleObject = Object.preventExtensions({});
      var testMap = new Map([[nonExtensibleObject, null]]);
      var testSet = new Set([nonExtensibleObject]);
      // This is necessary for Rollup to not consider these unused.
      // https://github.com/rollup/rollup/issues/1771
      // TODO: we can remove these if Rollup fixes the bug.
      testMap.set(0, 0);
      testSet.add(0);
    } catch (e) {
      // TODO: Consider warning about bad polyfills
      hasBadMapPolyfill = true;
    }
  }
  
  // A Fiber is work on a Component that needs to be done or was done. There can
  // be more than one per component.
  
  var debugCounter = void 0;
  
  {
    debugCounter = 1;
  }
  
  function FiberNode(tag, pendingProps, key, mode) {
    // Instance
    this.tag = tag;
    this.key = key;
    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.mode = mode;
  
    // Effects
    this.effectTag = NoEffect;
    this.nextEffect = null;
  
    this.firstEffect = null;
    this.lastEffect = null;
  
    this.expirationTime = NoWork;
  
    this.alternate = null;
  
    {
      this._debugID = debugCounter++;
      this._debugSource = null;
      this._debugOwner = null;
      this._debugIsCurrentlyTiming = false;
      if (!hasBadMapPolyfill && typeof Object.preventExtensions === "function") {
        Object.preventExtensions(this);
      }
    }
  }
  
  // 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) {
    return !!(Component.prototype && Component.prototype.isReactComponent);
  }
  
  // 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.type = current.type;
      workInProgress.stateNode = current.stateNode;
  
      {
        // DEV-only fields
        workInProgress._debugID = current._debugID;
        workInProgress._debugSource = current._debugSource;
        workInProgress._debugOwner = current._debugOwner;
      }
  
      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;
    }
  
    workInProgress.expirationTime = expirationTime;
  
    workInProgress.child = current.child;
    workInProgress.memoizedProps = current.memoizedProps;
    workInProgress.memoizedState = current.memoizedState;
    workInProgress.updateQueue = current.updateQueue;
  
    // These will be overridden during the parent's reconciliation
    workInProgress.sibling = current.sibling;
    workInProgress.index = current.index;
    workInProgress.ref = current.ref;
  
    return workInProgress;
  }
  
  function createHostRootFiber(isAsync) {
    var mode = isAsync ? AsyncMode | StrictMode : NoContext;
    return createFiber(HostRoot, null, null, mode);
  }
  
  function createFiberFromElement(element, mode, expirationTime) {
    var owner = null;
    {
      owner = element._owner;
    }
  
    var fiber = void 0;
    var type = element.type;
    var key = element.key;
    var pendingProps = element.props;
  
    var fiberTag = void 0;
    if (typeof type === "function") {
      fiberTag = shouldConstruct(type) ? ClassComponent : IndeterminateComponent;
    } else if (typeof type === "string") {
      fiberTag = HostComponent;
    } else {
      switch (type) {
        case REACT_FRAGMENT_TYPE:
          return createFiberFromFragment(
            pendingProps.children,
            mode,
            expirationTime,
            key
          );
        case REACT_ASYNC_MODE_TYPE:
          fiberTag = Mode;
          mode |= AsyncMode | StrictMode;
          break;
        case REACT_STRICT_MODE_TYPE:
          fiberTag = Mode;
          mode |= StrictMode;
          break;
        case REACT_CALL_TYPE:
          fiberTag = CallComponent;
          break;
        case REACT_RETURN_TYPE:
          fiberTag = ReturnComponent;
          break;
        default: {
          if (typeof type === "object" && type !== null) {
            switch (type.$$typeof) {
              case REACT_PROVIDER_TYPE:
                fiberTag = ContextProvider;
                break;
              case REACT_CONTEXT_TYPE:
                // This is a consumer
                fiberTag = ContextConsumer;
                break;
              default:
                if (typeof type.tag === "number") {
                  // Currently assumed to be a continuation and therefore is a
                  // fiber already.
                  // TODO: The yield system is currently broken for updates in
                  // some cases. The reified yield stores a fiber, but we don't
                  // know which fiber that is; the current or a workInProgress?
                  // When the continuation gets rendered here we don't know if we
                  // can reuse that fiber or if we need to clone it. There is
                  // probably a clever way to restructure this.
                  fiber = type;
                  fiber.pendingProps = pendingProps;
                  fiber.expirationTime = expirationTime;
                  return fiber;
                } else {
                  throwOnInvalidElementType(type, owner);
                }
                break;
            }
          } else {
            throwOnInvalidElementType(type, owner);
          }
        }
      }
    }
  
    fiber = createFiber(fiberTag, pendingProps, key, mode);
    fiber.type = type;
    fiber.expirationTime = expirationTime;
  
    {
      fiber._debugSource = element._source;
      fiber._debugOwner = element._owner;
    }
  
    return fiber;
  }
  
  function throwOnInvalidElementType(type, owner) {
    var info = "";
    {
      if (
        type === undefined ||
        (typeof type === "object" &&
          type !== null &&
          Object.keys(type).length === 0)
      ) {
        info +=
          " You likely forgot to export your component from the file " +
          "it's defined in, or you might have mixed up default and " +
          "named imports.";
      }
      var ownerName = owner ? getComponentName(owner) : null;
      if (ownerName) {
        info += "\n\nCheck the render method of `" + ownerName + "`.";
      }
    }
    invariant(
      false,
      "Element type is invalid: expected a string (for built-in " +
        "components) or a class/function (for composite components) " +
        "but got: %s.%s",
      type == null ? type : typeof type,
      info
    );
  }
  
  function createFiberFromFragment(elements, mode, expirationTime, key) {
    var fiber = createFiber(Fragment, elements, key, mode);
    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);
    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;
  }
  
  // TODO: This should be lifted into the renderer.
  
  function createFiberRoot(containerInfo, isAsync, hydrate) {
    // Cyclic construction. This cheats the type system right now because
    // stateNode is any.
    var uninitializedFiber = createHostRootFiber(isAsync);
    var root = {
      current: uninitializedFiber,
      containerInfo: containerInfo,
      pendingChildren: null,
      remainingExpirationTime: NoWork,
      isReadyForCommit: false,
      finishedWork: null,
      context: null,
      pendingContext: null,
      hydrate: hydrate,
      firstBatch: null,
      nextScheduledRoot: null
    };
    uninitializedFiber.stateNode = root;
    return root;
  }
  
  var onCommitFiberRoot = null;
  var onCommitFiberUnmount = null;
  var hasLoggedError = false;
  
  function catchErrors(fn) {
    return function(arg) {
      try {
        return fn(arg);
      } catch (err) {
        if (true && !hasLoggedError) {
          hasLoggedError = true;
          warning(false, "React DevTools encountered an error: %s", err);
        }
      }
    };
  }
  
  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) {
      {
        warning(
          false,
          "The installed version of React DevTools is too old and will not work " +
            "with the current version of React. Please update React DevTools. " +
            "https://fb.me/react-devtools"
        );
      }
      // DevTools exists, even though it doesn't support Fiber.
      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.
      {
        warning(false, "React DevTools encountered an error: %s.", err);
      }
    }
    // DevTools exists
    return true;
  }
  
  function onCommitRoot(root) {
    if (typeof onCommitFiberRoot === "function") {
      onCommitFiberRoot(root);
    }
  }
  
  function onCommitUnmount(fiber) {
    if (typeof onCommitFiberUnmount === "function") {
      onCommitFiberUnmount(fiber);
    }
  }
  
  var ReactStrictModeWarnings = {
    discardPendingWarnings: function() {},
    flushPendingDeprecationWarnings: function() {},
    flushPendingUnsafeLifecycleWarnings: function() {},
    recordDeprecationWarnings: function(fiber, instance) {},
    recordUnsafeLifecycleWarnings: function(fiber, instance) {}
  };
  
  {
    var LIFECYCLE_SUGGESTIONS = {
      UNSAFE_componentWillMount: "componentDidMount",
      UNSAFE_componentWillReceiveProps: "static getDerivedStateFromProps",
      UNSAFE_componentWillUpdate: "componentDidUpdate"
    };
  
    var pendingComponentWillMountWarnings = [];
    var pendingComponentWillReceivePropsWarnings = [];
    var pendingComponentWillUpdateWarnings = [];
    var pendingUnsafeLifecycleWarnings = new Map();
  
    // Tracks components we have already warned about.
    var didWarnAboutDeprecatedLifecycles = new Set();
    var didWarnAboutUnsafeLifecycles = new Set();
  
    ReactStrictModeWarnings.discardPendingWarnings = function() {
      pendingComponentWillMountWarnings = [];
      pendingComponentWillReceivePropsWarnings = [];
      pendingComponentWillUpdateWarnings = [];
      pendingUnsafeLifecycleWarnings = new Map();
    };
  
    ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function() {
      pendingUnsafeLifecycleWarnings.forEach(function(
        lifecycleWarningsMap,
        strictRoot
      ) {
        var lifecyclesWarningMesages = [];
  
        Object.keys(lifecycleWarningsMap).forEach(function(lifecycle) {
          var lifecycleWarnings = lifecycleWarningsMap[lifecycle];
          if (lifecycleWarnings.length > 0) {
            var componentNames = new Set();
            lifecycleWarnings.forEach(function(fiber) {
              componentNames.add(getComponentName(fiber) || "Component");
              didWarnAboutUnsafeLifecycles.add(fiber.type);
            });
  
            var formatted = lifecycle.replace("UNSAFE_", "");
            var suggestion = LIFECYCLE_SUGGESTIONS[lifecycle];
            var sortedComponentNames = Array.from(componentNames)
              .sort()
              .join(", ");
  
            lifecyclesWarningMesages.push(
              formatted +
                ": Please update the following components to use " +
                (suggestion + " instead: " + sortedComponentNames)
            );
          }
        });
  
        if (lifecyclesWarningMesages.length > 0) {
          var strictRootComponentStack = getStackAddendumByWorkInProgressFiber(
            strictRoot
          );
  
          warning(
            false,
            "Unsafe lifecycle methods were found within a strict-mode tree:%s" +
              "\n\n%s" +
              "\n\nLearn more about this warning here:" +
              "\nhttps://fb.me/react-strict-mode-warnings",
            strictRootComponentStack,
            lifecyclesWarningMesages.join("\n\n")
          );
        }
      });
  
      pendingUnsafeLifecycleWarnings = new Map();
    };
  
    var getStrictRoot = function(fiber) {
      var maybeStrictRoot = null;
  
      while (fiber !== null) {
        if (fiber.mode & StrictMode) {
          maybeStrictRoot = fiber;
        }
  
        fiber = fiber["return"];
      }
  
      return maybeStrictRoot;
    };
  
    ReactStrictModeWarnings.flushPendingDeprecationWarnings = function() {
      if (pendingComponentWillMountWarnings.length > 0) {
        var uniqueNames = new Set();
        pendingComponentWillMountWarnings.forEach(function(fiber) {
          uniqueNames.add(getComponentName(fiber) || "Component");
          didWarnAboutDeprecatedLifecycles.add(fiber.type);
        });
  
        var sortedNames = Array.from(uniqueNames)
          .sort()
          .join(", ");
  
        warning(
          false,
          "componentWillMount is deprecated and will be removed in the next major version. " +
            "Use componentDidMount instead. As a temporary workaround, " +
            "you can rename to UNSAFE_componentWillMount." +
            "\n\nPlease update the following components: %s" +
            "\n\nLearn more about this warning here:" +
            "\nhttps://fb.me/react-async-component-lifecycle-hooks",
          sortedNames
        );
  
        pendingComponentWillMountWarnings = [];
      }
  
      if (pendingComponentWillReceivePropsWarnings.length > 0) {
        var _uniqueNames = new Set();
        pendingComponentWillReceivePropsWarnings.forEach(function(fiber) {
          _uniqueNames.add(getComponentName(fiber) || "Component");
          didWarnAboutDeprecatedLifecycles.add(fiber.type);
        });
  
        var _sortedNames = Array.from(_uniqueNames)
          .sort()
          .join(", ");
  
        warning(
          false,
          "componentWillReceiveProps is deprecated and will be removed in the next major version. " +
            "Use static getDerivedStateFromProps instead." +
            "\n\nPlease update the following components: %s" +
            "\n\nLearn more about this warning here:" +
            "\nhttps://fb.me/react-async-component-lifecycle-hooks",
          _sortedNames
        );
  
        pendingComponentWillReceivePropsWarnings = [];
      }
  
      if (pendingComponentWillUpdateWarnings.length > 0) {
        var _uniqueNames2 = new Set();
        pendingComponentWillUpdateWarnings.forEach(function(fiber) {
          _uniqueNames2.add(getComponentName(fiber) || "Component");
          didWarnAboutDeprecatedLifecycles.add(fiber.type);
        });
  
        var _sortedNames2 = Array.from(_uniqueNames2)
          .sort()
          .join(", ");
  
        warning(
          false,
          "componentWillUpdate is deprecated and will be removed in the next major version. " +
            "Use componentDidUpdate instead. As a temporary workaround, " +
            "you can rename to UNSAFE_componentWillUpdate." +
            "\n\nPlease update the following components: %s" +
            "\n\nLearn more about this warning here:" +
            "\nhttps://fb.me/react-async-component-lifecycle-hooks",
          _sortedNames2
        );
  
        pendingComponentWillUpdateWarnings = [];
      }
    };
  
    ReactStrictModeWarnings.recordDeprecationWarnings = function(
      fiber,
      instance
    ) {
      // Dedup strategy: Warn once per component.
      if (didWarnAboutDeprecatedLifecycles.has(fiber.type)) {
        return;
      }
  
      // Don't warn about react-lifecycles-compat polyfilled components.
      // Note that it is sufficient to check for the presence of a
      // single lifecycle, componentWillMount, with the polyfill flag.
      if (
        typeof instance.componentWillMount === "function" &&
        instance.componentWillMount.__suppressDeprecationWarning === true
      ) {
        return;
      }
  
      if (typeof instance.componentWillMount === "function") {
        pendingComponentWillMountWarnings.push(fiber);
      }
      if (typeof instance.componentWillReceiveProps === "function") {
        pendingComponentWillReceivePropsWarnings.push(fiber);
      }
      if (typeof instance.componentWillUpdate === "function") {
        pendingComponentWillUpdateWarnings.push(fiber);
      }
    };
  
    ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function(
      fiber,
      instance
    ) {
      var strictRoot = getStrictRoot(fiber);
  
      // Dedup strategy: Warn once per component.
      // This is difficult to track any other way since component names
      // are often vague and are likely to collide between 3rd party libraries.
      // An expand property is probably okay to use here since it's DEV-only,
      // and will only be set in the event of serious warnings.
      if (didWarnAboutUnsafeLifecycles.has(fiber.type)) {
        return;
      }
  
      // Don't warn about react-lifecycles-compat polyfilled components.
      // Note that it is sufficient to check for the presence of a
      // single lifecycle, componentWillMount, with the polyfill flag.
      if (
        typeof instance.componentWillMount === "function" &&
        instance.componentWillMount.__suppressDeprecationWarning === true
      ) {
        return;
      }
  
      var warningsForRoot = void 0;
      if (!pendingUnsafeLifecycleWarnings.has(strictRoot)) {
        warningsForRoot = {
          UNSAFE_componentWillMount: [],
          UNSAFE_componentWillReceiveProps: [],
          UNSAFE_componentWillUpdate: []
        };
  
        pendingUnsafeLifecycleWarnings.set(strictRoot, warningsForRoot);
      } else {
        warningsForRoot = pendingUnsafeLifecycleWarnings.get(strictRoot);
      }
  
      var unsafeLifecycles = [];
      if (
        typeof instance.componentWillMount === "function" ||
        typeof instance.UNSAFE_componentWillMount === "function"
      ) {
        unsafeLifecycles.push("UNSAFE_componentWillMount");
      }
      if (
        typeof instance.componentWillReceiveProps === "function" ||
        typeof instance.UNSAFE_componentWillReceiveProps === "function"
      ) {
        unsafeLifecycles.push("UNSAFE_componentWillReceiveProps");
      }
      if (
        typeof instance.componentWillUpdate === "function" ||
        typeof instance.UNSAFE_componentWillUpdate === "function"
      ) {
        unsafeLifecycles.push("UNSAFE_componentWillUpdate");
      }
  
      if (unsafeLifecycles.length > 0) {
        unsafeLifecycles.forEach(function(lifecycle) {
          warningsForRoot[lifecycle].push(fiber);
        });
      }
    };
  }
  
  var didWarnUpdateInsideUpdate = void 0;
  
  {
    didWarnUpdateInsideUpdate = false;
  }
  
  // Callbacks are not validated until invocation
  
  // Singly linked-list of updates. When an update is scheduled, it is added to
  // the queue of the current fiber and the work-in-progress fiber. The two queues
  // are separate but they share a persistent structure.
  //
  // During reconciliation, updates are removed from the work-in-progress fiber,
  // but they remain on the current fiber. That ensures that if a work-in-progress
  // is aborted, the aborted updates are recovered by cloning from current.
  //
  // The work-in-progress queue is always a subset of the current queue.
  //
  // When the tree is committed, the work-in-progress becomes the current.
  
  function createUpdateQueue(baseState) {
    var queue = {
      baseState: baseState,
      expirationTime: NoWork,
      first: null,
      last: null,
      callbackList: null,
      hasForceUpdate: false,
      isInitialized: false
    };
    {
      queue.isProcessing = false;
    }
    return queue;
  }
  
  function insertUpdateIntoQueue(queue, update) {
    // Append the update to the end of the list.
    if (queue.last === null) {
      // Queue is empty
      queue.first = queue.last = update;
    } else {
      queue.last.next = update;
      queue.last = update;
    }
    if (
      queue.expirationTime === NoWork ||
      queue.expirationTime > update.expirationTime
    ) {
      queue.expirationTime = update.expirationTime;
    }
  }
  
  function insertUpdateIntoFiber(fiber, update) {
    // We'll have at least one and at most two distinct update queues.
    var alternateFiber = fiber.alternate;
    var queue1 = fiber.updateQueue;
    if (queue1 === null) {
      // TODO: We don't know what the base state will be until we begin work.
      // It depends on which fiber is the next current. Initialize with an empty
      // base state, then set to the memoizedState when rendering. Not super
      // happy with this approach.
      queue1 = fiber.updateQueue = createUpdateQueue(null);
    }
  
    var queue2 = void 0;
    if (alternateFiber !== null) {
      queue2 = alternateFiber.updateQueue;
      if (queue2 === null) {
        queue2 = alternateFiber.updateQueue = createUpdateQueue(null);
      }
    } else {
      queue2 = null;
    }
    queue2 = queue2 !== queue1 ? queue2 : null;
  
    // Warn if an update is scheduled from inside an updater function.
    {
      if (
        (queue1.isProcessing || (queue2 !== null && queue2.isProcessing)) &&
        !didWarnUpdateInsideUpdate
      ) {
        warning(
          false,
          "An update (setState, replaceState, or forceUpdate) was scheduled " +
            "from inside an update function. Update functions should be pure, " +
            "with zero side-effects. Consider using componentDidUpdate or a " +
            "callback."
        );
        didWarnUpdateInsideUpdate = true;
      }
    }
  
    // If there's only one queue, add the update to that queue and exit.
    if (queue2 === null) {
      insertUpdateIntoQueue(queue1, update);
      return;
    }
  
    // If either queue is empty, we need to add to both queues.
    if (queue1.last === null || queue2.last === null) {
      insertUpdateIntoQueue(queue1, update);
      insertUpdateIntoQueue(queue2, update);
      return;
    }
  
    // If both lists are not empty, the last update is the same for both lists
    // because of structural sharing. So, we should only append to one of
    // the lists.
    insertUpdateIntoQueue(queue1, update);
    // But we still need to update the `last` pointer of queue2.
    queue2.last = update;
  }
  
  function getUpdateExpirationTime(fiber) {
    if (fiber.tag !== ClassComponent && fiber.tag !== HostRoot) {
      return NoWork;
    }
    var updateQueue = fiber.updateQueue;
    if (updateQueue === null) {
      return NoWork;
    }
    return updateQueue.expirationTime;
  }
  
  function getStateFromUpdate(update, instance, prevState, props) {
    var partialState = update.partialState;
    if (typeof partialState === "function") {
      return partialState.call(instance, prevState, props);
    } else {
      return partialState;
    }
  }
  
  function processUpdateQueue(
    current,
    workInProgress,
    queue,
    instance,
    props,
    renderExpirationTime
  ) {
    if (current !== null && current.updateQueue === queue) {
      // We need to create a work-in-progress queue, by cloning the current queue.
      var currentQueue = queue;
      queue = workInProgress.updateQueue = {
        baseState: currentQueue.baseState,
        expirationTime: currentQueue.expirationTime,
        first: currentQueue.first,
        last: currentQueue.last,
        isInitialized: currentQueue.isInitialized,
        // These fields are no longer valid because they were already committed.
        // Reset them.
        callbackList: null,
        hasForceUpdate: false
      };
    }
  
    {
      // Set this flag so we can warn if setState is called inside the update
      // function of another setState.
      queue.isProcessing = true;
    }
  
    // Reset the remaining expiration time. If we skip over any updates, we'll
    // increase this accordingly.
    queue.expirationTime = NoWork;
  
    // TODO: We don't know what the base state will be until we begin work.
    // It depends on which fiber is the next current. Initialize with an empty
    // base state, then set to the memoizedState when rendering. Not super
    // happy with this approach.
    var state = void 0;
    if (queue.isInitialized) {
      state = queue.baseState;
    } else {
      state = queue.baseState = workInProgress.memoizedState;
      queue.isInitialized = true;
    }
    var dontMutatePrevState = true;
    var update = queue.first;
    var didSkip = false;
    while (update !== null) {
      var updateExpirationTime = update.expirationTime;
      if (updateExpirationTime > renderExpirationTime) {
        // This update does not have sufficient priority. Skip it.
        var remainingExpirationTime = queue.expirationTime;
        if (
          remainingExpirationTime === NoWork ||
          remainingExpirationTime > updateExpirationTime
        ) {
          // Update the remaining expiration time.
          queue.expirationTime = updateExpirationTime;
        }
        if (!didSkip) {
          didSkip = true;
          queue.baseState = state;
        }
        // Continue to the next update.
        update = update.next;
        continue;
      }
  
      // This update does have sufficient priority.
  
      // If no previous updates were skipped, drop this update from the queue by
      // advancing the head of the list.
      if (!didSkip) {
        queue.first = update.next;
        if (queue.first === null) {
          queue.last = null;
        }
      }
  
      // Invoke setState callback an extra time to help detect side-effects.
      // Ignore the return value in this case.
      if (
        debugRenderPhaseSideEffects ||
        (debugRenderPhaseSideEffectsForStrictMode &&
          workInProgress.mode & StrictMode)
      ) {
        getStateFromUpdate(update, instance, state, props);
      }
  
      // Process the update
      var _partialState = void 0;
      if (update.isReplace) {
        state = getStateFromUpdate(update, instance, state, props);
        dontMutatePrevState = true;
      } else {
        _partialState = getStateFromUpdate(update, instance, state, props);
        if (_partialState) {
          if (dontMutatePrevState) {
            // $FlowFixMe: Idk how to type this properly.
            state = Object.assign({}, state, _partialState);
          } else {
            state = Object.assign(state, _partialState);
          }
          dontMutatePrevState = false;
        }
      }
      if (update.isForced) {
        queue.hasForceUpdate = true;
      }
      if (update.callback !== null) {
        // Append to list of callbacks.
        var _callbackList = queue.callbackList;
        if (_callbackList === null) {
          _callbackList = queue.callbackList = [];
        }
        _callbackList.push(update);
      }
      update = update.next;
    }
  
    if (queue.callbackList !== null) {
      workInProgress.effectTag |= Callback;
    } else if (queue.first === null && !queue.hasForceUpdate) {
      // The queue is empty. We can reset it.
      workInProgress.updateQueue = null;
    }
  
    if (!didSkip) {
      didSkip = true;
      queue.baseState = state;
    }
  
    {
      // No longer processing.
      queue.isProcessing = false;
    }
  
    return state;
  }
  
  function commitCallbacks(queue, context) {
    var callbackList = queue.callbackList;
    if (callbackList === null) {
      return;
    }
    // Set the list to null to make sure they don't get called more than once.
    queue.callbackList = null;
    for (var i = 0; i < callbackList.length; i++) {
      var update = callbackList[i];
      var _callback = update.callback;
      // This update might be processed again. Clear the callback so it's only
      // called once.
      update.callback = null;
      invariant(
        typeof _callback === "function",
        "Invalid argument passed as callback. Expected a function. Instead " +
          "received: %s",
        _callback
      );
      _callback.call(context);
    }
  }
  
  var fakeInternalInstance = {};
  var isArray = Array.isArray;
  
  var didWarnAboutStateAssignmentForComponent = void 0;
  var didWarnAboutUndefinedDerivedState = void 0;
  var didWarnAboutUninitializedState = void 0;
  var didWarnAboutWillReceivePropsAndDerivedState = void 0;
  var warnOnInvalidCallback = void 0;
  
  {
    didWarnAboutStateAssignmentForComponent = {};
    didWarnAboutUndefinedDerivedState = {};
    didWarnAboutUninitializedState = {};
    didWarnAboutWillReceivePropsAndDerivedState = {};
  
    var didWarnOnInvalidCallback = {};
  
    warnOnInvalidCallback = function(callback, callerName) {
      if (callback === null || typeof callback === "function") {
        return;
      }
      var key = callerName + "_" + callback;
      if (!didWarnOnInvalidCallback[key]) {
        warning(
          false,
          "%s(...): Expected the last optional `callback` argument to be a " +
            "function. Instead received: %s.",
          callerName,
          callback
        );
        didWarnOnInvalidCallback[key] = true;
      }
    };
  
    // This is so gross but it's at least non-critical and can be removed if
    // it causes problems. This is meant to give a nicer error message for
    // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component,
    // ...)) which otherwise throws a "_processChildContext is not a function"
    // exception.
    Object.defineProperty(fakeInternalInstance, "_processChildContext", {
      enumerable: false,
      value: function() {
        invariant(
          false,
          "_processChildContext is not available in React 16+. This likely " +
            "means you have multiple copies of React and are attempting to nest " +
            "a React 15 tree inside a React 16 tree using " +
            "unstable_renderSubtreeIntoContainer, which isn't supported. Try " +
            "to make sure you have only one copy of React (and ideally, switch " +
            "to ReactDOM.createPortal)."
        );
      }
    });
    Object.freeze(fakeInternalInstance);
  }
  
  var ReactFiberClassComponent = function(
    scheduleWork,
    computeExpirationForFiber,
    memoizeProps,
    memoizeState
  ) {
    // Class component state updater
    var updater = {
      isMounted: isMounted,
      enqueueSetState: function(instance, partialState, callback) {
        var fiber = get(instance);
        callback = callback === undefined ? null : callback;
        {
          warnOnInvalidCallback(callback, "setState");
        }
        var expirationTime = computeExpirationForFiber(fiber);
        var update = {
          expirationTime: expirationTime,
          partialState: partialState,
          callback: callback,
          isReplace: false,
          isForced: false,
          nextCallback: null,
          next: null
        };
        insertUpdateIntoFiber(fiber, update);
        scheduleWork(fiber, expirationTime);
      },
      enqueueReplaceState: function(instance, state, callback) {
        var fiber = get(instance);
        callback = callback === undefined ? null : callback;
        {
          warnOnInvalidCallback(callback, "replaceState");
        }
        var expirationTime = computeExpirationForFiber(fiber);
        var update = {
          expirationTime: expirationTime,
          partialState: state,
          callback: callback,
          isReplace: true,
          isForced: false,
          nextCallback: null,
          next: null
        };
        insertUpdateIntoFiber(fiber, update);
        scheduleWork(fiber, expirationTime);
      },
      enqueueForceUpdate: function(instance, callback) {
        var fiber = get(instance);
        callback = callback === undefined ? null : callback;
        {
          warnOnInvalidCallback(callback, "forceUpdate");
        }
        var expirationTime = computeExpirationForFiber(fiber);
        var update = {
          expirationTime: expirationTime,
          partialState: null,
          callback: callback,
          isReplace: false,
          isForced: true,
          nextCallback: null,
          next: null
        };
        insertUpdateIntoFiber(fiber, update);
        scheduleWork(fiber, expirationTime);
      }
    };
  
    function checkShouldComponentUpdate(
      workInProgress,
      oldProps,
      newProps,
      oldState,
      newState,
      newContext
    ) {
      if (
        oldProps === null ||
        (workInProgress.updateQueue !== null &&
          workInProgress.updateQueue.hasForceUpdate)
      ) {
        // If the workInProgress already has an Update effect, return true
        return true;
      }
  
      var instance = workInProgress.stateNode;
      var type = workInProgress.type;
      if (typeof instance.shouldComponentUpdate === "function") {
        startPhaseTimer(workInProgress, "shouldComponentUpdate");
        var shouldUpdate = instance.shouldComponentUpdate(
          newProps,
          newState,
          newContext
        );
        stopPhaseTimer();
  
        {
          warning(
            shouldUpdate !== undefined,
            "%s.shouldComponentUpdate(): Returned undefined instead of a " +
              "boolean value. Make sure to return true or false.",
            getComponentName(workInProgress) || "Unknown"
          );
        }
  
        return shouldUpdate;
      }
  
      if (type.prototype && type.prototype.isPureReactComponent) {
        return (
          !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
        );
      }
  
      return true;
    }
  
    function checkClassInstance(workInProgress) {
      var instance = workInProgress.stateNode;
      var type = workInProgress.type;
      {
        var name = getComponentName(workInProgress);
        var renderPresent = instance.render;
  
        if (!renderPresent) {
          if (type.prototype && typeof type.prototype.render === "function") {
            warning(
              false,
              "%s(...): No `render` method found on the returned component " +
                "instance: did you accidentally return an object from the constructor?",
              name
            );
          } else {
            warning(
              false,
              "%s(...): No `render` method found on the returned component " +
                "instance: you may have forgotten to define `render`.",
              name
            );
          }
        }
  
        var noGetInitialStateOnES6 =
          !instance.getInitialState ||
          instance.getInitialState.isReactClassApproved ||
          instance.state;
        warning(
          noGetInitialStateOnES6,
          "getInitialState was defined on %s, a plain JavaScript class. " +
            "This is only supported for classes created using React.createClass. " +
            "Did you mean to define a state property instead?",
          name
        );
        var noGetDefaultPropsOnES6 =
          !instance.getDefaultProps ||
          instance.getDefaultProps.isReactClassApproved;
        warning(
          noGetDefaultPropsOnES6,
          "getDefaultProps was defined on %s, a plain JavaScript class. " +
            "This is only supported for classes created using React.createClass. " +
            "Use a static property to define defaultProps instead.",
          name
        );
        var noInstancePropTypes = !instance.propTypes;
        warning(
          noInstancePropTypes,
          "propTypes was defined as an instance property on %s. Use a static " +
            "property to define propTypes instead.",
          name
        );
        var noInstanceContextTypes = !instance.contextTypes;
        warning(
          noInstanceContextTypes,
          "contextTypes was defined as an instance property on %s. Use a static " +
            "property to define contextTypes instead.",
          name
        );
        var noComponentShouldUpdate =
          typeof instance.componentShouldUpdate !== "function";
        warning(
          noComponentShouldUpdate,
          "%s has a method called " +
            "componentShouldUpdate(). Did you mean shouldComponentUpdate()? " +
            "The name is phrased as a question because the function is " +
            "expected to return a value.",
          name
        );
        if (
          type.prototype &&
          type.prototype.isPureReactComponent &&
          typeof instance.shouldComponentUpdate !== "undefined"
        ) {
          warning(
            false,
            "%s has a method called shouldComponentUpdate(). " +
              "shouldComponentUpdate should not be used when extending React.PureComponent. " +
              "Please extend React.Component if shouldComponentUpdate is used.",
            getComponentName(workInProgress) || "A pure component"
          );
        }
        var noComponentDidUnmount =
          typeof instance.componentDidUnmount !== "function";
        warning(
          noComponentDidUnmount,
          "%s has a method called " +
            "componentDidUnmount(). But there is no such lifecycle method. " +
            "Did you mean componentWillUnmount()?",
          name
        );
        var noComponentDidReceiveProps =
          typeof instance.componentDidReceiveProps !== "function";
        warning(
          noComponentDidReceiveProps,
          "%s has a method called " +
            "componentDidReceiveProps(). But there is no such lifecycle method. " +
            "If you meant to update the state in response to changing props, " +
            "use componentWillReceiveProps(). If you meant to fetch data or " +
            "run side-effects or mutations after React has updated the UI, use componentDidUpdate().",
          name
        );
        var noComponentWillRecieveProps =
          typeof instance.componentWillRecieveProps !== "function";
        warning(
          noComponentWillRecieveProps,
          "%s has a method called " +
            "componentWillRecieveProps(). Did you mean componentWillReceiveProps()?",
          name
        );
        var noUnsafeComponentWillRecieveProps =
          typeof instance.UNSAFE_componentWillRecieveProps !== "function";
        warning(
          noUnsafeComponentWillRecieveProps,
          "%s has a method called " +
            "UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?",
          name
        );
        var hasMutatedProps = instance.props !== workInProgress.pendingProps;
        warning(
          instance.props === undefined || !hasMutatedProps,
          "%s(...): When calling super() in `%s`, make sure to pass " +
            "up the same props that your component's constructor was passed.",
          name,
          name
        );
        var noInstanceDefaultProps = !instance.defaultProps;
        warning(
          noInstanceDefaultProps,
          "Setting defaultProps as an instance property on %s is not supported and will be ignored." +
            " Instead, define defaultProps as a static property on %s.",
          name,
          name
        );
      }
  
      var state = instance.state;
      if (state && (typeof state !== "object" || isArray(state))) {
        warning(
          false,
          "%s.state: must be set to an object or null",
          getComponentName(workInProgress)
        );
      }
      if (typeof instance.getChildContext === "function") {
        warning(
          typeof workInProgress.type.childContextTypes === "object",
          "%s.getChildContext(): childContextTypes must be defined in order to " +
            "use getChildContext().",
          getComponentName(workInProgress)
        );
      }
    }
  
    function resetInputPointers(workInProgress, instance) {
      instance.props = workInProgress.memoizedProps;
      instance.state = workInProgress.memoizedState;
    }
  
    function adoptClassInstance(workInProgress, instance) {
      instance.updater = updater;
      workInProgress.stateNode = instance;
      // The instance needs access to the fiber so that it can schedule updates
      set(instance, workInProgress);
      {
        instance._reactInternalInstance = fakeInternalInstance;
      }
    }
  
    function constructClassInstance(workInProgress, props) {
      var ctor = workInProgress.type;
      var unmaskedContext = getUnmaskedContext(workInProgress);
      var needsContext = isContextConsumer(workInProgress);
      var context = needsContext
        ? getMaskedContext(workInProgress, unmaskedContext)
        : emptyObject;
  
      // Instantiate twice to help detect side-effects.
      if (
        debugRenderPhaseSideEffects ||
        (debugRenderPhaseSideEffectsForStrictMode &&
          workInProgress.mode & StrictMode)
      ) {
        new ctor(props, context); // eslint-disable-line no-new
      }
  
      var instance = new ctor(props, context);
      var state =
        instance.state !== null && instance.state !== undefined
          ? instance.state
          : null;
      adoptClassInstance(workInProgress, instance);
  
      {
        if (
          typeof ctor.getDerivedStateFromProps === "function" &&
          state === null
        ) {
          var componentName = getComponentName(workInProgress) || "Unknown";
          if (!didWarnAboutUninitializedState[componentName]) {
            warning(
              false,
              "%s: Did not properly initialize state during construction. " +
                "Expected state to be an object, but it was %s.",
              componentName,
              instance.state === null ? "null" : "undefined"
            );
            didWarnAboutUninitializedState[componentName] = true;
          }
        }
      }
  
      workInProgress.memoizedState = state;
  
      var partialState = callGetDerivedStateFromProps(
        workInProgress,
        instance,
        props
      );
  
      if (partialState !== null && partialState !== undefined) {
        // Render-phase updates (like this) should not be added to the update queue,
        // So that multiple render passes do not enqueue multiple updates.
        // Instead, just synchronously merge the returned state into the instance.
        workInProgress.memoizedState = Object.assign(
          {},
          workInProgress.memoizedState,
          partialState
        );
      }
  
      // Cache unmasked context so we can avoid recreating masked context unless necessary.
      // ReactFiberContext usually updates this cache but can't for newly-created instances.
      if (needsContext) {
        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) {
        {
          warning(
            false,
            "%s.componentWillMount(): Assigning directly to this.state is " +
              "deprecated (except inside a component's " +
              "constructor). Use setState instead.",
            getComponentName(workInProgress)
          );
        }
        updater.enqueueReplaceState(instance, instance.state, null);
      }
    }
  
    function callComponentWillReceiveProps(
      workInProgress,
      instance,
      newProps,
      newContext
    ) {
      var oldState = instance.state;
      startPhaseTimer(workInProgress, "componentWillReceiveProps");
      if (typeof instance.componentWillReceiveProps === "function") {
        instance.componentWillReceiveProps(newProps, newContext);
      }
      if (typeof instance.UNSAFE_componentWillReceiveProps === "function") {
        instance.UNSAFE_componentWillReceiveProps(newProps, newContext);
      }
      stopPhaseTimer();
  
      if (instance.state !== oldState) {
        {
          var componentName = getComponentName(workInProgress) || "Component";
          if (!didWarnAboutStateAssignmentForComponent[componentName]) {
            warning(
              false,
              "%s.componentWillReceiveProps(): Assigning directly to " +
                "this.state is deprecated (except inside a component's " +
                "constructor). Use setState instead.",
              componentName
            );
            didWarnAboutStateAssignmentForComponent[componentName] = true;
          }
        }
        updater.enqueueReplaceState(instance, instance.state, null);
      }
    }
  
    function callGetDerivedStateFromProps(workInProgress, instance, props) {
      var type = workInProgress.type;
  
      if (typeof type.getDerivedStateFromProps === "function") {
        {
          // Don't warn about react-lifecycles-compat polyfilled components
          if (
            (typeof instance.componentWillReceiveProps === "function" &&
              instance.componentWillReceiveProps.__suppressDeprecationWarning !==
                true) ||
            typeof instance.UNSAFE_componentWillReceiveProps === "function"
          ) {
            var componentName = getComponentName(workInProgress) || "Unknown";
            if (!didWarnAboutWillReceivePropsAndDerivedState[componentName]) {
              warning(
                false,
                "%s: Defines both componentWillReceiveProps() and static " +
                  "getDerivedStateFromProps() methods. We recommend using " +
                  "only getDerivedStateFromProps().",
                componentName
              );
              didWarnAboutWillReceivePropsAndDerivedState[componentName] = true;
            }
          }
        }
  
        if (
          debugRenderPhaseSideEffects ||
          (debugRenderPhaseSideEffectsForStrictMode &&
            workInProgress.mode & StrictMode)
        ) {
          // Invoke method an extra time to help detect side-effects.
          type.getDerivedStateFromProps.call(
            null,
            props,
            workInProgress.memoizedState
          );
        }
  
        var partialState = type.getDerivedStateFromProps.call(
          null,
          props,
          workInProgress.memoizedState
        );
  
        {
          if (partialState === undefined) {
            var _componentName = getComponentName(workInProgress) || "Unknown";
            if (!didWarnAboutUndefinedDerivedState[_componentName]) {
              warning(
                false,
                "%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. " +
                  "You have returned undefined.",
                _componentName
              );
              didWarnAboutUndefinedDerivedState[_componentName] = _componentName;
            }
          }
        }
  
        return partialState;
      }
    }
  
    // Invokes the mount life-cycles on a previously never rendered instance.
    function mountClassInstance(workInProgress, renderExpirationTime) {
      var current = workInProgress.alternate;
  
      {
        checkClassInstance(workInProgress);
      }
  
      var instance = workInProgress.stateNode;
      var props = workInProgress.pendingProps;
      var unmaskedContext = getUnmaskedContext(workInProgress);
  
      instance.props = props;
      instance.state = workInProgress.memoizedState;
      instance.refs = emptyObject;
      instance.context = getMaskedContext(workInProgress, unmaskedContext);
  
      {
        if (workInProgress.mode & StrictMode) {
          ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(
            workInProgress,
            instance
          );
        }
  
        if (warnAboutDeprecatedLifecycles) {
          ReactStrictModeWarnings.recordDeprecationWarnings(
            workInProgress,
            instance
          );
        }
      }
  
      // In order to support react-lifecycles-compat polyfilled components,
      // Unsafe lifecycles should not be invoked for any component with the new gDSFP.
      if (
        (typeof instance.UNSAFE_componentWillMount === "function" ||
          typeof instance.componentWillMount === "function") &&
        typeof workInProgress.type.getDerivedStateFromProps !== "function"
      ) {
        callComponentWillMount(workInProgress, instance);
        // If we had additional state updates during this life-cycle, let's
        // process them now.
        var updateQueue = workInProgress.updateQueue;
        if (updateQueue !== null) {
          instance.state = processUpdateQueue(
            current,
            workInProgress,
            updateQueue,
            instance,
            props,
            renderExpirationTime
          );
        }
      }
      if (typeof instance.componentDidMount === "function") {
        workInProgress.effectTag |= Update;
      }
    }
  
    // Called on a preexisting class instance. Returns false if a resumed render
    // could be reused.
    // function resumeMountClassInstance(
    //   workInProgress: Fiber,
    //   priorityLevel: PriorityLevel,
    // ): boolean {
    //   const instance = workInProgress.stateNode;
    //   resetInputPointers(workInProgress, instance);
  
    //   let newState = workInProgress.memoizedState;
    //   let newProps = workInProgress.pendingProps;
    //   if (!newProps) {
    //     // If there isn't any new props, then we'll reuse the memoized props.
    //     // This could be from already completed work.
    //     newProps = workInProgress.memoizedProps;
    //     invariant(
    //       newProps != null,
    //       'There should always be pending or memoized props. This error is ' +
    //         'likely caused by a bug in React. Please file an issue.',
    //     );
    //   }
    //   const newUnmaskedContext = getUnmaskedContext(workInProgress);
    //   const newContext = getMaskedContext(workInProgress, newUnmaskedContext);
  
    //   const oldContext = instance.context;
    //   const oldProps = workInProgress.memoizedProps;
  
    //   if (
    //     typeof instance.componentWillReceiveProps === 'function' &&
    //     (oldProps !== newProps || oldContext !== newContext)
    //   ) {
    //     callComponentWillReceiveProps(
    //       workInProgress,
    //       instance,
    //       newProps,
    //       newContext,
    //     );
    //   }
  
    //   // Process the update queue before calling shouldComponentUpdate
    //   const updateQueue = workInProgress.updateQueue;
    //   if (updateQueue !== null) {
    //     newState = processUpdateQueue(
    //       workInProgress,
    //       updateQueue,
    //       instance,
    //       newState,
    //       newProps,
    //       priorityLevel,
    //     );
    //   }
  
    //   // TODO: Should we deal with a setState that happened after the last
    //   // componentWillMount and before this componentWillMount? Probably
    //   // unsupported anyway.
  
    //   if (
    //     !checkShouldComponentUpdate(
    //       workInProgress,
    //       workInProgress.memoizedProps,
    //       newProps,
    //       workInProgress.memoizedState,
    //       newState,
    //       newContext,
    //     )
    //   ) {
    //     // Update the existing instance's state, props, and context pointers even
    //     // though we're bailing out.
    //     instance.props = newProps;
    //     instance.state = newState;
    //     instance.context = newContext;
    //     return false;
    //   }
  
    //   // Update the input pointers now so that they are correct when we call
    //   // componentWillMount
    //   instance.props = newProps;
    //   instance.state = newState;
    //   instance.context = newContext;
  
    //   if (typeof instance.componentWillMount === 'function') {
    //     callComponentWillMount(workInProgress, instance);
    //     // componentWillMount may have called setState. Process the update queue.
    //     const newUpdateQueue = workInProgress.updateQueue;
    //     if (newUpdateQueue !== null) {
    //       newState = processUpdateQueue(
    //         workInProgress,
    //         newUpdateQueue,
    //         instance,
    //         newState,
    //         newProps,
    //         priorityLevel,
    //       );
    //     }
    //   }
  
    //   if (typeof instance.componentDidMount === 'function') {
    //     workInProgress.effectTag |= Update;
    //   }
  
    //   instance.state = newState;
  
    //   return true;
    // }
  
    // Invokes the update life-cycles and returns false if it shouldn't rerender.
    function updateClassInstance(current, workInProgress, renderExpirationTime) {
      var instance = workInProgress.stateNode;
      resetInputPointers(workInProgress, instance);
  
      var oldProps = workInProgress.memoizedProps;
      var newProps = workInProgress.pendingProps;
      var oldContext = instance.context;
      var newUnmaskedContext = getUnmaskedContext(workInProgress);
      var newContext = getMaskedContext(workInProgress, newUnmaskedContext);
  
      // 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 any component with the new gDSFP.
      if (
        (typeof instance.UNSAFE_componentWillReceiveProps === "function" ||
          typeof instance.componentWillReceiveProps === "function") &&
        typeof workInProgress.type.getDerivedStateFromProps !== "function"
      ) {
        if (oldProps !== newProps || oldContext !== newContext) {
          callComponentWillReceiveProps(
            workInProgress,
            instance,
            newProps,
            newContext
          );
        }
      }
  
      var partialState = void 0;
      if (oldProps !== newProps) {
        partialState = callGetDerivedStateFromProps(
          workInProgress,
          instance,
          newProps
        );
      }
  
      // Compute the next state using the memoized state and the update queue.
      var oldState = workInProgress.memoizedState;
      // TODO: Previous state can be null.
      var newState = void 0;
      if (workInProgress.updateQueue !== null) {
        newState = processUpdateQueue(
          current,
          workInProgress,
          workInProgress.updateQueue,
          instance,
          newProps,
          renderExpirationTime
        );
      } else {
        newState = oldState;
      }
  
      if (partialState !== null && partialState !== undefined) {
        // Render-phase updates (like this) should not be added to the update queue,
        // So that multiple render passes do not enqueue multiple updates.
        // Instead, just synchronously merge the returned state into the instance.
        newState =
          newState === null || newState === undefined
            ? partialState
            : Object.assign({}, newState, partialState);
      }
  
      if (
        oldProps === newProps &&
        oldState === newState &&
        !hasContextChanged() &&
        !(
          workInProgress.updateQueue !== null &&
          workInProgress.updateQueue.hasForceUpdate
        )
      ) {
        // 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;
          }
        }
        return false;
      }
  
      var shouldUpdate = checkShouldComponentUpdate(
        workInProgress,
        oldProps,
        newProps,
        oldState,
        newState,
        newContext
      );
  
      if (shouldUpdate) {
        // In order to support react-lifecycles-compat polyfilled components,
        // Unsafe lifecycles should not be invoked for any component with the new gDSFP.
        if (
          (typeof instance.UNSAFE_componentWillUpdate === "function" ||
            typeof instance.componentWillUpdate === "function") &&
          typeof workInProgress.type.getDerivedStateFromProps !== "function"
        ) {
          startPhaseTimer(workInProgress, "componentWillUpdate");
          if (typeof instance.componentWillUpdate === "function") {
            instance.componentWillUpdate(newProps, newState, newContext);
          }
          if (typeof instance.UNSAFE_componentWillUpdate === "function") {
            instance.UNSAFE_componentWillUpdate(newProps, newState, newContext);
          }
          stopPhaseTimer();
        }
        if (typeof instance.componentDidUpdate === "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.componentDidUpdate === "function") {
          if (
            oldProps !== current.memoizedProps ||
            oldState !== current.memoizedState
          ) {
            workInProgress.effectTag |= Update;
          }
        }
  
        // If shouldComponentUpdate returned false, we should still update the
        // memoized props/state to indicate that this work can be reused.
        memoizeProps(workInProgress, newProps);
        memoizeState(workInProgress, newState);
      }
  
      // Update the existing instance's state, props, and context pointers even
      // if shouldComponentUpdate returns false.
      instance.props = newProps;
      instance.state = newState;
      instance.context = newContext;
  
      return shouldUpdate;
    }
  
    return {
      adoptClassInstance: adoptClassInstance,
      callGetDerivedStateFromProps: callGetDerivedStateFromProps,
      constructClassInstance: constructClassInstance,
      mountClassInstance: mountClassInstance,
      // resumeMountClassInstance,
      updateClassInstance: updateClassInstance
    };
  };
  
  var getCurrentFiberStackAddendum$1 =
    ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
  
  var didWarnAboutMaps = void 0;
  var ownerHasKeyUseWarning = void 0;
  var ownerHasFunctionTypeWarning = void 0;
  var warnForMissingKey = function(child) {};
  
  {
    didWarnAboutMaps = false;
    /**
     * Warn if there's no key explicitly set on dynamic arrays of children or
     * object keys are not valid. This allows us to keep track of children between
     * updates.
     */
    ownerHasKeyUseWarning = {};
    ownerHasFunctionTypeWarning = {};
  
    warnForMissingKey = function(child) {
      if (child === null || typeof child !== "object") {
        return;
      }
      if (!child._store || child._store.validated || child.key != null) {
        return;
      }
      invariant(
        typeof child._store === "object",
        "React Component in warnForMissingKey should have a _store. " +
          "This error is likely caused by a bug in React. Please file an issue."
      );
      child._store.validated = true;
  
      var currentComponentErrorInfo =
        "Each child in an array or iterator should have a unique " +
        '"key" prop. See https://fb.me/react-warning-keys for ' +
        "more information." +
        (getCurrentFiberStackAddendum$1() || "");
      if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
        return;
      }
      ownerHasKeyUseWarning[currentComponentErrorInfo] = true;
  
      warning(
        false,
        "Each child in an array or iterator should have a unique " +
          '"key" prop. See https://fb.me/react-warning-keys for ' +
          "more information.%s",
        getCurrentFiberStackAddendum$1()
      );
    };
  }
  
  var isArray$1 = Array.isArray;
  
  function coerceRef(current, element) {
    var mixedRef = element.ref;
    if (mixedRef !== null && typeof mixedRef !== "function") {
      if (element._owner) {
        var owner = element._owner;
        var inst = void 0;
        if (owner) {
          var ownerFiber = owner;
          invariant(
            ownerFiber.tag === ClassComponent,
            "Stateless function components cannot have refs."
          );
          inst = ownerFiber.stateNode;
        }
        invariant(
          inst,
          "Missing owner for string ref %s. This error is likely caused by a " +
            "bug in React. Please file an issue.",
          mixedRef
        );
        var stringRef = "" + mixedRef;
        // Check if previous string ref matches new string ref
        if (
          current !== null &&
          current.ref !== null &&
          current.ref._stringRef === stringRef
        ) {
          return current.ref;
        }
        var ref = function(value) {
          var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
          if (value === null) {
            delete refs[stringRef];
          } else {
            refs[stringRef] = value;
          }
        };
        ref._stringRef = stringRef;
        return ref;
      } else {
        invariant(
          typeof mixedRef === "string",
          "Expected ref to be a function or a string."
        );
        invariant(
          element._owner,
          "Element ref was specified as a string (%s) but no owner was set. This could happen for one of" +
            " the following reasons:\n" +
            "1. You may be adding a ref to a functional component\n" +
            "2. You may be adding a ref to a component that was not created inside a component's render method\n" +
            "3. You have multiple copies of React loaded\n" +
            "See https://fb.me/react-refs-must-have-owner for more information.",
          mixedRef
        );
      }
    }
    return mixedRef;
  }
  
  function throwOnInvalidObjectType(returnFiber, newChild) {
    if (returnFiber.type !== "textarea") {
      var addendum = "";
      {
        addendum =
          " If you meant to render a collection of children, use an array " +
          "instead." +
          (getCurrentFiberStackAddendum$1() || "");
      }
      invariant(
        false,
        "Objects are not valid as a React child (found: %s).%s",
        Object.prototype.toString.call(newChild) === "[object Object]"
          ? "object with keys {" + Object.keys(newChild).join(", ") + "}"
          : newChild,
        addendum
      );
    }
  }
  
  function warnOnFunctionType() {
    var currentComponentErrorInfo =
      "Functions are not valid as a React child. This may happen if " +
      "you return a Component instead of <Component /> from render. " +
      "Or maybe you meant to call this function rather than return it." +
      (getCurrentFiberStackAddendum$1() || "");
  
    if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) {
      return;
    }
    ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true;
  
    warning(
      false,
      "Functions are not valid as a React child. This may happen if " +
        "you return a Component instead of <Component /> from render. " +
        "Or maybe you meant to call this function rather than return it.%s",
      getCurrentFiberStackAddendum$1() || ""
    );
  }
  
  // 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 = newFiber.alternate;
      if (current !== null) {
        var oldIndex = current.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, textContent, expirationTime) {
      if (current === null || current.tag !== HostText) {
        // Insert
        var created = createFiberFromText(
          textContent,
          returnFiber.mode,
          expirationTime
        );
        created["return"] = returnFiber;
        return created;
      } else {
        // Update
        var existing = useFiber(current, textContent, expirationTime);
        existing["return"] = returnFiber;
        return existing;
      }
    }
  
    function updateElement(returnFiber, current, element, expirationTime) {
      if (current !== null && current.type === element.type) {
        // Move based on index
        var existing = useFiber(current, element.props, expirationTime);
        existing.ref = coerceRef(current, element);
        existing["return"] = returnFiber;
        {
          existing._debugSource = element._source;
          existing._debugOwner = element._owner;
        }
        return existing;
      } else {
        // Insert
        var created = createFiberFromElement(
          element,
          returnFiber.mode,
          expirationTime
        );
        created.ref = coerceRef(current, element);
        created["return"] = returnFiber;
        return created;
      }
    }
  
    function updatePortal(returnFiber, current, portal, expirationTime) {
      if (
        current === null ||
        current.tag !== HostPortal ||
        current.stateNode.containerInfo !== portal.containerInfo ||
        current.stateNode.implementation !== portal.implementation
      ) {
        // Insert
        var created = createFiberFromPortal(
          portal,
          returnFiber.mode,
          expirationTime
        );
        created["return"] = returnFiber;
        return created;
      } else {
        // Update
        var existing = useFiber(current, portal.children || [], expirationTime);
        existing["return"] = returnFiber;
        return existing;
      }
    }
  
    function updateFragment(returnFiber, current, fragment, expirationTime, key) {
      if (current === null || current.tag !== Fragment) {
        // Insert
        var created = createFiberFromFragment(
          fragment,
          returnFiber.mode,
          expirationTime,
          key
        );
        created["return"] = returnFiber;
        return created;
      } else {
        // Update
        var existing = useFiber(current, 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(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$1(newChild) || getIteratorFn(newChild)) {
          var _created3 = createFiberFromFragment(
            newChild,
            returnFiber.mode,
            expirationTime,
            null
          );
          _created3["return"] = returnFiber;
          return _created3;
        }
  
        throwOnInvalidObjectType(returnFiber, newChild);
      }
  
      {
        if (typeof newChild === "function") {
          warnOnFunctionType();
        }
      }
  
      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$1(newChild) || getIteratorFn(newChild)) {
          if (key !== null) {
            return null;
          }
  
          return updateFragment(
            returnFiber,
            oldFiber,
            newChild,
            expirationTime,
            null
          );
        }
  
        throwOnInvalidObjectType(returnFiber, newChild);
      }
  
      {
        if (typeof newChild === "function") {
          warnOnFunctionType();
        }
      }
  
      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$1(newChild) || getIteratorFn(newChild)) {
          var _matchedFiber3 = existingChildren.get(newIdx) || null;
          return updateFragment(
            returnFiber,
            _matchedFiber3,
            newChild,
            expirationTime,
            null
          );
        }
  
        throwOnInvalidObjectType(returnFiber, newChild);
      }
  
      {
        if (typeof newChild === "function") {
          warnOnFunctionType();
        }
      }
  
      return null;
    }
  
    /**
     * Warns if there is a duplicate or missing key
     */
    function warnOnInvalidKey(child, knownKeys) {
      {
        if (typeof child !== "object" || child === null) {
          return knownKeys;
        }
        switch (child.$$typeof) {
          case REACT_ELEMENT_TYPE:
          case REACT_PORTAL_TYPE:
            warnForMissingKey(child);
            var key = child.key;
            if (typeof key !== "string") {
              break;
            }
            if (knownKeys === null) {
              knownKeys = new Set();
              knownKeys.add(key);
              break;
            }
            if (!knownKeys.has(key)) {
              knownKeys.add(key);
              break;
            }
            warning(
              false,
              "Encountered two children with the same key, `%s`. " +
                "Keys should be unique so that components maintain their identity " +
                "across updates. Non-unique keys may cause children to be " +
                "duplicated and/or omitted — the behavior is unsupported and " +
                "could change in a future version.%s",
              key,
              getCurrentFiberStackAddendum$1()
            );
            break;
          default:
            break;
        }
      }
      return knownKeys;
    }
  
    function reconcileChildrenArray(
      returnFiber,
      currentFirstChild,
      newChildren,
      expirationTime
    ) {
      // This algorithm can't optimize by searching from boths 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.
  
      {
        // First, validate keys.
        var knownKeys = null;
        for (var i = 0; i < newChildren.length; i++) {
          var child = newChildren[i];
          knownKeys = warnOnInvalidKey(child, knownKeys);
        }
      }
  
      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);
      invariant(
        typeof iteratorFn === "function",
        "An object is not an iterable. This error is likely caused by a bug in " +
          "React. Please file an issue."
      );
  
      {
        // Warn about using Maps as children
        if (typeof newChildrenIterable.entries === "function") {
          var possibleMap = newChildrenIterable;
          if (possibleMap.entries === iteratorFn) {
            warning(
              didWarnAboutMaps,
              "Using Maps as children is unsupported and will likely yield " +
                "unexpected results. Convert it to a sequence/iterable of keyed " +
                "ReactElements instead.%s",
              getCurrentFiberStackAddendum$1()
            );
            didWarnAboutMaps = true;
          }
        }
  
        // First, validate keys.
        // We'll get a different iterator later for the main pass.
        var _newChildren = iteratorFn.call(newChildrenIterable);
        if (_newChildren) {
          var knownKeys = null;
          var _step = _newChildren.next();
          for (; !_step.done; _step = _newChildren.next()) {
            var child = _step.value;
            knownKeys = warnOnInvalidKey(child, knownKeys);
          }
        }
      }
  
      var newChildren = iteratorFn.call(newChildrenIterable);
      invariant(newChildren != null, "An iterable object provided no iterator.");
  
      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.type === element.type
          ) {
            deleteRemainingChildren(returnFiber, child.sibling);
            var existing = useFiber(
              child,
              element.type === REACT_FRAGMENT_TYPE
                ? element.props.children
                : element.props,
              expirationTime
            );
            existing.ref = coerceRef(child, element);
            existing["return"] = returnFiber;
            {
              existing._debugSource = element._source;
              existing._debugOwner = element._owner;
            }
            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(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.
      if (
        typeof newChild === "object" &&
        newChild !== null &&
        newChild.type === REACT_FRAGMENT_TYPE &&
        newChild.key === null
      ) {
        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$1(newChild)) {
        return reconcileChildrenArray(
          returnFiber,
          currentFirstChild,
          newChild,
          expirationTime
        );
      }
  
      if (getIteratorFn(newChild)) {
        return reconcileChildrenIterator(
          returnFiber,
          currentFirstChild,
          newChild,
          expirationTime
        );
      }
  
      if (isObject) {
        throwOnInvalidObjectType(returnFiber, newChild);
      }
  
      {
        if (typeof newChild === "function") {
          warnOnFunctionType();
        }
      }
      if (typeof newChild === "undefined") {
        // 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: {
            {
              var instance = returnFiber.stateNode;
              if (instance.render._isMockFunction) {
                // We allow auto-mocks to proceed as if they're returning null.
                break;
              }
            }
          }
          // Intentionally fall through to the next case, which handles both
          // functions and classes
          // eslint-disable-next-lined no-fallthrough
          case FunctionalComponent: {
            var Component = returnFiber.type;
            invariant(
              false,
              "%s(...): Nothing was returned from render. This usually means a " +
                "return statement is missing. Or, to render nothing, " +
                "return null.",
              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, workInProgress) {
    invariant(
      current === null || workInProgress.child === current.child,
      "Resuming work not yet implemented."
    );
  
    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 stack = [];
  var index$1 = -1;
  
  var rendererSigil = void 0;
  {
    // Use this to detect multiple renderers using the same context
    rendererSigil = {};
  }
  
  function pushProvider(providerFiber) {
    index$1 += 1;
    stack[index$1] = providerFiber;
    var context = providerFiber.type.context;
    context.currentValue = providerFiber.pendingProps.value;
    context.changedBits = providerFiber.stateNode;
  
    {
      warning(
        context._currentRenderer === null ||
          context._currentRenderer === rendererSigil,
        "Detected multiple renderers concurrently rendering the " +
          "same context provider. This is currently unsupported."
      );
      context._currentRenderer = rendererSigil;
    }
  }
  
  function popProvider(providerFiber) {
    {
      warning(
        index$1 > -1 && providerFiber === stack[index$1],
        "Unexpected pop."
      );
    }
    stack[index$1] = null;
    index$1 -= 1;
    var context = providerFiber.type.context;
    if (index$1 < 0) {
      context.currentValue = context.defaultValue;
      context.changedBits = 0;
    } else {
      var previousProviderFiber = stack[index$1];
      context.currentValue = previousProviderFiber.pendingProps.value;
      context.changedBits = previousProviderFiber.stateNode;
    }
  }
  
  function resetProviderStack() {
    for (var i = index$1; i > -1; i--) {
      var providerFiber = stack[i];
      var context = providerFiber.type.context;
      context.currentValue = context.defaultValue;
      context.changedBits = 0;
      stack[i] = null;
      {
        context._currentRenderer = null;
      }
    }
    index$1 = -1;
  }
  
  var didWarnAboutBadClass = void 0;
  var didWarnAboutGetDerivedStateOnFunctionalComponent = void 0;
  var didWarnAboutStatelessRefs = void 0;
  
  {
    didWarnAboutBadClass = {};
    didWarnAboutGetDerivedStateOnFunctionalComponent = {};
    didWarnAboutStatelessRefs = {};
  }
  
  var ReactFiberBeginWork = function(
    config,
    hostContext,
    hydrationContext,
    scheduleWork,
    computeExpirationForFiber
  ) {
    var shouldSetTextContent = config.shouldSetTextContent,
      shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree;
    var pushHostContext = hostContext.pushHostContext,
      pushHostContainer = hostContext.pushHostContainer;
    var enterHydrationState = hydrationContext.enterHydrationState,
      resetHydrationState = hydrationContext.resetHydrationState,
      tryToClaimNextHydratableInstance =
        hydrationContext.tryToClaimNextHydratableInstance;
  
    var _ReactFiberClassCompo = ReactFiberClassComponent(
        scheduleWork,
        computeExpirationForFiber,
        memoizeProps,
        memoizeState
      ),
      adoptClassInstance = _ReactFiberClassCompo.adoptClassInstance,
      callGetDerivedStateFromProps =
        _ReactFiberClassCompo.callGetDerivedStateFromProps,
      constructClassInstance = _ReactFiberClassCompo.constructClassInstance,
      mountClassInstance = _ReactFiberClassCompo.mountClassInstance,
      updateClassInstance = _ReactFiberClassCompo.updateClassInstance;
  
    // TODO: Remove this and use reconcileChildrenAtExpirationTime directly.
  
    function reconcileChildren(current, workInProgress, nextChildren) {
      reconcileChildrenAtExpirationTime(
        current,
        workInProgress,
        nextChildren,
        workInProgress.expirationTime
      );
    }
  
    function reconcileChildrenAtExpirationTime(
      current,
      workInProgress,
      nextChildren,
      renderExpirationTime
    ) {
      if (current === 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.child,
          nextChildren,
          renderExpirationTime
        );
      }
    }
  
    function updateFragment(current, workInProgress) {
      var nextChildren = workInProgress.pendingProps;
      if (hasContextChanged()) {
        // Normally we can bail out on props equality but if context has changed
        // we don't do the bailout and we have to reuse existing props instead.
      } else if (workInProgress.memoizedProps === nextChildren) {
        return bailoutOnAlreadyFinishedWork(current, workInProgress);
      }
      reconcileChildren(current, workInProgress, nextChildren);
      memoizeProps(workInProgress, nextChildren);
      return workInProgress.child;
    }
  
    function updateMode(current, workInProgress) {
      var nextChildren = workInProgress.pendingProps.children;
      if (hasContextChanged()) {
        // Normally we can bail out on props equality but if context has changed
        // we don't do the bailout and we have to reuse existing props instead.
      } else if (
        nextChildren === null ||
        workInProgress.memoizedProps === nextChildren
      ) {
        return bailoutOnAlreadyFinishedWork(current, workInProgress);
      }
      reconcileChildren(current, workInProgress, nextChildren);
      memoizeProps(workInProgress, nextChildren);
      return workInProgress.child;
    }
  
    function markRef(current, workInProgress) {
      var ref = workInProgress.ref;
      if (ref !== null && (!current || current.ref !== ref)) {
        // Schedule a Ref effect
        workInProgress.effectTag |= Ref;
      }
    }
  
    function updateFunctionalComponent(current, workInProgress) {
      var fn = workInProgress.type;
      var nextProps = workInProgress.pendingProps;
  
      if (hasContextChanged()) {
        // Normally we can bail out on props equality but if context has changed
        // we don't do the bailout and we have to reuse existing props instead.
      } else {
        if (workInProgress.memoizedProps === nextProps) {
          return bailoutOnAlreadyFinishedWork(current, workInProgress);
        }
        // TODO: consider bringing fn.shouldComponentUpdate() back.
        // It used to be here.
      }
  
      var unmaskedContext = getUnmaskedContext(workInProgress);
      var context = getMaskedContext(workInProgress, unmaskedContext);
  
      var nextChildren = void 0;
  
      {
        ReactCurrentOwner.current = workInProgress;
        ReactDebugCurrentFiber.setCurrentPhase("render");
        nextChildren = fn(nextProps, context);
        ReactDebugCurrentFiber.setCurrentPhase(null);
      }
      // React DevTools reads this flag.
      workInProgress.effectTag |= PerformedWork;
      reconcileChildren(current, workInProgress, nextChildren);
      memoizeProps(workInProgress, nextProps);
      return workInProgress.child;
    }
  
    function updateClassComponent(current, workInProgress, renderExpirationTime) {
      // 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 = pushContextProvider(workInProgress);
  
      var shouldUpdate = void 0;
      if (current === null) {
        if (!workInProgress.stateNode) {
          // In the initial pass we might need to construct the instance.
          constructClassInstance(workInProgress, workInProgress.pendingProps);
          mountClassInstance(workInProgress, renderExpirationTime);
  
          shouldUpdate = true;
        } else {
          invariant(false, "Resuming work not yet implemented.");
          // In a resume, we'll already have an instance we can reuse.
          // shouldUpdate = resumeMountClassInstance(workInProgress, renderExpirationTime);
        }
      } else {
        shouldUpdate = updateClassInstance(
          current,
          workInProgress,
          renderExpirationTime
        );
      }
      return finishClassComponent(
        current,
        workInProgress,
        shouldUpdate,
        hasContext
      );
    }
  
    function finishClassComponent(
      current,
      workInProgress,
      shouldUpdate,
      hasContext
    ) {
      // Refs should update even if shouldComponentUpdate returns false
      markRef(current, workInProgress);
  
      if (!shouldUpdate) {
        // Context providers should defer to sCU for rendering
        if (hasContext) {
          invalidateContextProvider(workInProgress, false);
        }
  
        return bailoutOnAlreadyFinishedWork(current, workInProgress);
      }
  
      var instance = workInProgress.stateNode;
  
      // Rerender
      ReactCurrentOwner.current = workInProgress;
      var nextChildren = void 0;
      {
        ReactDebugCurrentFiber.setCurrentPhase("render");
        nextChildren = instance.render();
        if (
          debugRenderPhaseSideEffects ||
          (debugRenderPhaseSideEffectsForStrictMode &&
            workInProgress.mode & StrictMode)
        ) {
          instance.render();
        }
        ReactDebugCurrentFiber.setCurrentPhase(null);
      }
      // React DevTools reads this flag.
      workInProgress.effectTag |= PerformedWork;
      reconcileChildren(current, workInProgress, nextChildren);
      // Memoize props and state using the values we just used to render.
      // TODO: Restructure so we never read values from the instance.
      memoizeState(workInProgress, instance.state);
      memoizeProps(workInProgress, instance.props);
  
      // The context might have changed so we need to recalculate it.
      if (hasContext) {
        invalidateContextProvider(workInProgress, 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, workInProgress, renderExpirationTime) {
      pushHostRootContext(workInProgress);
      var updateQueue = workInProgress.updateQueue;
      if (updateQueue !== null) {
        var prevState = workInProgress.memoizedState;
        var state = processUpdateQueue(
          current,
          workInProgress,
          updateQueue,
          null,
          null,
          renderExpirationTime
        );
        if (prevState === state) {
          // 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, workInProgress);
        }
        var element = state.element;
        var root = workInProgress.stateNode;
        if (
          (current === null || current.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,
            element,
            renderExpirationTime
          );
        } else {
          // Otherwise reset hydration state in case we aborted and resumed another
          // root.
          resetHydrationState();
          reconcileChildren(current, workInProgress, element);
        }
        memoizeState(workInProgress, state);
        return workInProgress.child;
      }
      resetHydrationState();
      // If there is no update queue, that's a bailout because the root has no props.
      return bailoutOnAlreadyFinishedWork(current, workInProgress);
    }
  
    function updateHostComponent(current, workInProgress, renderExpirationTime) {
      pushHostContext(workInProgress);
  
      if (current === null) {
        tryToClaimNextHydratableInstance(workInProgress);
      }
  
      var type = workInProgress.type;
      var memoizedProps = workInProgress.memoizedProps;
      var nextProps = workInProgress.pendingProps;
      var prevProps = current !== null ? current.memoizedProps : null;
  
      if (hasContextChanged()) {
        // Normally we can bail out on props equality but if context has changed
        // we don't do the bailout and we have to reuse existing props instead.
      } else if (memoizedProps === nextProps) {
        return bailoutOnAlreadyFinishedWork(current, workInProgress);
      }
  
      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 && 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, workInProgress);
  
      // Check the host config to see if the children are offscreen/hidden.
      if (
        renderExpirationTime !== Never &&
        workInProgress.mode & AsyncMode &&
        shouldDeprioritizeSubtree(type, nextProps)
      ) {
        // Down-prioritize the children.
        workInProgress.expirationTime = Never;
        // Bailout and come back to this fiber later.
        return null;
      }
  
      reconcileChildren(current, workInProgress, nextChildren);
      memoizeProps(workInProgress, nextProps);
      return workInProgress.child;
    }
  
    function updateHostText(current, workInProgress) {
      if (current === null) {
        tryToClaimNextHydratableInstance(workInProgress);
      }
      var nextProps = workInProgress.pendingProps;
      memoizeProps(workInProgress, nextProps);
      // Nothing to do here. This is terminal. We'll do the completion step
      // immediately after.
      return null;
    }
  
    function mountIndeterminateComponent(
      current,
      workInProgress,
      renderExpirationTime
    ) {
      invariant(
        current === null,
        "An indeterminate component should never have mounted. This error is " +
          "likely caused by a bug in React. Please file an issue."
      );
      var fn = workInProgress.type;
      var props = workInProgress.pendingProps;
      var unmaskedContext = getUnmaskedContext(workInProgress);
      var context = getMaskedContext(workInProgress, unmaskedContext);
  
      var value = void 0;
  
      {
        if (fn.prototype && typeof fn.prototype.render === "function") {
          var componentName = getComponentName(workInProgress) || "Unknown";
  
          if (!didWarnAboutBadClass[componentName]) {
            warning(
              false,
              "The <%s /> component appears to have a render method, but doesn't extend React.Component. " +
                "This is likely to cause errors. Change %s to extend React.Component instead.",
              componentName,
              componentName
            );
            didWarnAboutBadClass[componentName] = true;
          }
        }
        ReactCurrentOwner.current = workInProgress;
        value = fn(props, context);
      }
      // React DevTools reads this flag.
      workInProgress.effectTag |= PerformedWork;
  
      if (
        typeof value === "object" &&
        value !== null &&
        typeof value.render === "function" &&
        value.$$typeof === undefined
      ) {
        var Component = workInProgress.type;
  
        // Proceed under the assumption that this is a class instance
        workInProgress.tag = ClassComponent;
  
        workInProgress.memoizedState =
          value.state !== null && value.state !== undefined ? value.state : null;
  
        if (typeof Component.getDerivedStateFromProps === "function") {
          var partialState = callGetDerivedStateFromProps(
            workInProgress,
            value,
            props
          );
  
          if (partialState !== null && partialState !== undefined) {
            workInProgress.memoizedState = Object.assign(
              {},
              workInProgress.memoizedState,
              partialState
            );
          }
        }
  
        // 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 = pushContextProvider(workInProgress);
        adoptClassInstance(workInProgress, value);
        mountClassInstance(workInProgress, renderExpirationTime);
        return finishClassComponent(current, workInProgress, true, hasContext);
      } else {
        // Proceed under the assumption that this is a functional component
        workInProgress.tag = FunctionalComponent;
        {
          var _Component = workInProgress.type;
  
          if (_Component) {
            warning(
              !_Component.childContextTypes,
              "%s(...): childContextTypes cannot be defined on a functional component.",
              _Component.displayName || _Component.name || "Component"
            );
          }
          if (workInProgress.ref !== null) {
            var info = "";
            var ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
            if (ownerName) {
              info += "\n\nCheck the render method of `" + ownerName + "`.";
            }
  
            var warningKey = ownerName || workInProgress._debugID || "";
            var debugSource = workInProgress._debugSource;
            if (debugSource) {
              warningKey = debugSource.fileName + ":" + debugSource.lineNumber;
            }
            if (!didWarnAboutStatelessRefs[warningKey]) {
              didWarnAboutStatelessRefs[warningKey] = true;
              warning(
                false,
                "Stateless function components cannot be given refs. " +
                  "Attempts to access this ref will fail.%s%s",
                info,
                ReactDebugCurrentFiber.getCurrentFiberStackAddendum()
              );
            }
          }
  
          if (typeof fn.getDerivedStateFromProps === "function") {
            var _componentName = getComponentName(workInProgress) || "Unknown";
  
            if (
              !didWarnAboutGetDerivedStateOnFunctionalComponent[_componentName]
            ) {
              warning(
                false,
                "%s: Stateless functional components do not support getDerivedStateFromProps.",
                _componentName
              );
              didWarnAboutGetDerivedStateOnFunctionalComponent[
                _componentName
              ] = true;
            }
          }
        }
        reconcileChildren(current, workInProgress, value);
        memoizeProps(workInProgress, props);
        return workInProgress.child;
      }
    }
  
    function updateCallComponent(current, workInProgress, renderExpirationTime) {
      var nextProps = workInProgress.pendingProps;
      if (hasContextChanged()) {
        // Normally we can bail out on props equality but if context has changed
        // we don't do the bailout and we have to reuse existing props instead.
      } else if (workInProgress.memoizedProps === nextProps) {
        nextProps = workInProgress.memoizedProps;
        // TODO: When bailing out, we might need to return the stateNode instead
        // of the child. To check it for work.
        // return bailoutOnAlreadyFinishedWork(current, workInProgress);
      }
  
      var nextChildren = nextProps.children;
  
      // The following is a fork of reconcileChildrenAtExpirationTime but using
      // stateNode to store the child.
      if (current === null) {
        workInProgress.stateNode = mountChildFibers(
          workInProgress,
          workInProgress.stateNode,
          nextChildren,
          renderExpirationTime
        );
      } else {
        workInProgress.stateNode = reconcileChildFibers(
          workInProgress,
          current.stateNode,
          nextChildren,
          renderExpirationTime
        );
      }
  
      memoizeProps(workInProgress, nextProps);
      // This doesn't take arbitrary time so we could synchronously just begin
      // eagerly do the work of workInProgress.child as an optimization.
      return workInProgress.stateNode;
    }
  
    function updatePortalComponent(
      current,
      workInProgress,
      renderExpirationTime
    ) {
      pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
      var nextChildren = workInProgress.pendingProps;
      if (hasContextChanged()) {
        // Normally we can bail out on props equality but if context has changed
        // we don't do the bailout and we have to reuse existing props instead.
      } else if (workInProgress.memoizedProps === nextChildren) {
        return bailoutOnAlreadyFinishedWork(current, workInProgress);
      }
  
      if (current === 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
        );
        memoizeProps(workInProgress, nextChildren);
      } else {
        reconcileChildren(current, workInProgress, nextChildren);
        memoizeProps(workInProgress, nextChildren);
      }
      return workInProgress.child;
    }
  
    function propagateContextChange(
      workInProgress,
      context,
      changedBits,
      renderExpirationTime
    ) {
      var fiber = workInProgress.child;
      while (fiber !== null) {
        var nextFiber = void 0;
        // Visit this fiber.
        switch (fiber.tag) {
          case ContextConsumer:
            // Check if the context matches.
            var observedBits = fiber.stateNode | 0;
            if (fiber.type === context && (observedBits & changedBits) !== 0) {
              // Update the expiration time of all the ancestors, including
              // the alternates.
              var node = fiber;
              while (node !== null) {
                var alternate = node.alternate;
                if (
                  node.expirationTime === NoWork ||
                  node.expirationTime > renderExpirationTime
                ) {
                  node.expirationTime = renderExpirationTime;
                  if (
                    alternate !== null &&
                    (alternate.expirationTime === NoWork ||
                      alternate.expirationTime > renderExpirationTime)
                  ) {
                    alternate.expirationTime = renderExpirationTime;
                  }
                } else if (
                  alternate !== null &&
                  (alternate.expirationTime === NoWork ||
                    alternate.expirationTime > renderExpirationTime)
                ) {
                  alternate.expirationTime = renderExpirationTime;
                } else {
                  // Neither alternate was updated, which means the rest of the
                  // ancestor path already has sufficient priority.
                  break;
                }
                node = node["return"];
              }
              // Don't scan deeper than a matching consumer. When we render the
              // consumer, we'll continue scanning from that point. This way the
              // scanning work is time-sliced.
              nextFiber = null;
            } else {
              // Traverse down.
              nextFiber = fiber.child;
            }
            break;
          case ContextProvider:
            // Don't scan deeper if this is a matching provider
            nextFiber = fiber.type === workInProgress.type ? null : fiber.child;
            break;
          default:
            // Traverse down.
            nextFiber = fiber.child;
            break;
        }
        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) {
              nextFiber = sibling;
              break;
            }
            // No more siblings. Traverse up.
            nextFiber = nextFiber["return"];
          }
        }
        fiber = nextFiber;
      }
    }
  
    function updateContextProvider(
      current,
      workInProgress,
      renderExpirationTime
    ) {
      var providerType = workInProgress.type;
      var context = providerType.context;
  
      var newProps = workInProgress.pendingProps;
      var oldProps = workInProgress.memoizedProps;
  
      if (hasContextChanged()) {
        // Normally we can bail out on props equality but if context has changed
        // we don't do the bailout and we have to reuse existing props instead.
      } else if (oldProps === newProps) {
        workInProgress.stateNode = 0;
        pushProvider(workInProgress);
        return bailoutOnAlreadyFinishedWork(current, workInProgress);
      }
      workInProgress.memoizedProps = newProps;
  
      var newValue = newProps.value;
  
      var changedBits = void 0;
      if (oldProps === null) {
        // Initial render
        changedBits = MAX_SIGNED_31_BIT_INT;
      } else {
        var oldValue = oldProps.value;
        // Use Object.is to compare the new context value to the old value.
        // Inlined Object.is polyfill.
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
        if (
          (oldValue === newValue &&
            (oldValue !== 0 || 1 / oldValue === 1 / newValue)) ||
          (oldValue !== oldValue && newValue !== newValue) // eslint-disable-line no-self-compare
        ) {
          // No change.
          changedBits = 0;
        } else {
          changedBits =
            typeof context.calculateChangedBits === "function"
              ? context.calculateChangedBits(oldValue, newValue)
              : MAX_SIGNED_31_BIT_INT;
          {
            warning(
              (changedBits & MAX_SIGNED_31_BIT_INT) === changedBits,
              "calculateChangedBits: Expected the return value to be a " +
                "31-bit integer. Instead received: %s",
              changedBits
            );
          }
          changedBits |= 0;
  
          if (changedBits !== 0) {
            propagateContextChange(
              workInProgress,
              context,
              changedBits,
              renderExpirationTime
            );
          }
        }
      }
  
      workInProgress.stateNode = changedBits;
      pushProvider(workInProgress);
  
      if (oldProps !== null && oldProps.children === newProps.children) {
        return bailoutOnAlreadyFinishedWork(current, workInProgress);
      }
      var newChildren = newProps.children;
      reconcileChildren(current, workInProgress, newChildren);
      return workInProgress.child;
    }
  
    function updateContextConsumer(
      current,
      workInProgress,
      renderExpirationTime
    ) {
      var context = workInProgress.type;
      var newProps = workInProgress.pendingProps;
  
      var newValue = context.currentValue;
      var changedBits = context.changedBits;
  
      if (changedBits !== 0) {
        // Context change propagation stops at matching consumers, for time-
        // slicing. Continue the propagation here.
        propagateContextChange(
          workInProgress,
          context,
          changedBits,
          renderExpirationTime
        );
      }
  
      // Store the observedBits on the fiber's stateNode for quick access.
      var observedBits = newProps.observedBits;
      if (observedBits === undefined || observedBits === null) {
        // Subscribe to all changes by default
        observedBits = MAX_SIGNED_31_BIT_INT;
      }
      workInProgress.stateNode = observedBits;
  
      var render = newProps.children;
      var newChildren = render(newValue);
      reconcileChildren(current, workInProgress, newChildren);
      return workInProgress.child;
    }
  
    /*
    function reuseChildrenEffects(returnFiber : Fiber, firstChild : Fiber) {
      let child = firstChild;
      do {
        // Ensure that the first and last effect of the parent corresponds
        // to the children's first and last effect.
        if (!returnFiber.firstEffect) {
          returnFiber.firstEffect = child.firstEffect;
        }
        if (child.lastEffect) {
          if (returnFiber.lastEffect) {
            returnFiber.lastEffect.nextEffect = child.firstEffect;
          }
          returnFiber.lastEffect = child.lastEffect;
        }
      } while (child = child.sibling);
    }
    */
  
    function bailoutOnAlreadyFinishedWork(current, workInProgress) {
      cancelWorkTimer(workInProgress);
  
      // TODO: We should ideally be able to bail out early if the children have no
      // more work to do. However, since we don't have a separation of this
      // Fiber's priority and its children yet - we don't know without doing lots
      // of the same work we do anyway. Once we have that separation we can just
      // bail out here if the children has no more work at this priority level.
      // if (workInProgress.priorityOfChildren <= priorityLevel) {
      //   // If there are side-effects in these children that have not yet been
      //   // committed we need to ensure that they get properly transferred up.
      //   if (current && current.child !== workInProgress.child) {
      //     reuseChildrenEffects(workInProgress, child);
      //   }
      //   return null;
      // }
  
      cloneChildFibers(current, workInProgress);
      return workInProgress.child;
    }
  
    function bailoutOnLowPriority(current, workInProgress) {
      cancelWorkTimer(workInProgress);
  
      // TODO: Handle HostComponent tags here as well and call pushHostContext()?
      // See PR 8590 discussion for context
      switch (workInProgress.tag) {
        case HostRoot:
          pushHostRootContext(workInProgress);
          break;
        case ClassComponent:
          pushContextProvider(workInProgress);
          break;
        case HostPortal:
          pushHostContainer(
            workInProgress,
            workInProgress.stateNode.containerInfo
          );
          break;
        case ContextProvider:
          pushProvider(workInProgress);
          break;
      }
      // TODO: What if this is currently in progress?
      // How can that happen? How is this not being cloned?
      return null;
    }
  
    // TODO: Delete memoizeProps/State and move to reconcile/bailout instead
    function memoizeProps(workInProgress, nextProps) {
      workInProgress.memoizedProps = nextProps;
    }
  
    function memoizeState(workInProgress, nextState) {
      workInProgress.memoizedState = nextState;
      // Don't reset the updateQueue, in case there are pending updates. Resetting
      // is handled by processUpdateQueue.
    }
  
    function beginWork(current, workInProgress, renderExpirationTime) {
      if (
        workInProgress.expirationTime === NoWork ||
        workInProgress.expirationTime > renderExpirationTime
      ) {
        return bailoutOnLowPriority(current, workInProgress);
      }
  
      switch (workInProgress.tag) {
        case IndeterminateComponent:
          return mountIndeterminateComponent(
            current,
            workInProgress,
            renderExpirationTime
          );
        case FunctionalComponent:
          return updateFunctionalComponent(current, workInProgress);
        case ClassComponent:
          return updateClassComponent(
            current,
            workInProgress,
            renderExpirationTime
          );
        case HostRoot:
          return updateHostRoot(current, workInProgress, renderExpirationTime);
        case HostComponent:
          return updateHostComponent(
            current,
            workInProgress,
            renderExpirationTime
          );
        case HostText:
          return updateHostText(current, workInProgress);
        case CallHandlerPhase:
          // This is a restart. Reset the tag to the initial phase.
          workInProgress.tag = CallComponent;
        // Intentionally fall through since this is now the same.
        case CallComponent:
          return updateCallComponent(
            current,
            workInProgress,
            renderExpirationTime
          );
        case ReturnComponent:
          // A return component is just a placeholder, we can just run through the
          // next one immediately.
          return null;
        case HostPortal:
          return updatePortalComponent(
            current,
            workInProgress,
            renderExpirationTime
          );
        case Fragment:
          return updateFragment(current, workInProgress);
        case Mode:
          return updateMode(current, workInProgress);
        case ContextProvider:
          return updateContextProvider(
            current,
            workInProgress,
            renderExpirationTime
          );
        case ContextConsumer:
          return updateContextConsumer(
            current,
            workInProgress,
            renderExpirationTime
          );
        default:
          invariant(
            false,
            "Unknown unit of work tag. This error is likely caused by a bug in " +
              "React. Please file an issue."
          );
      }
    }
  
    function beginFailedWork(current, workInProgress, renderExpirationTime) {
      // Push context providers here to avoid a push/pop context mismatch.
      switch (workInProgress.tag) {
        case ClassComponent:
          pushContextProvider(workInProgress);
          break;
        case HostRoot:
          pushHostRootContext(workInProgress);
          break;
        default:
          invariant(
            false,
            "Invalid type of work. This error is likely caused by a bug in React. " +
              "Please file an issue."
          );
      }
  
      // Add an error effect so we can handle the error during the commit phase
      workInProgress.effectTag |= Err;
  
      // This is a weird case where we do "resume" work — work that failed on
      // our first attempt. Because we no longer have a notion of "progressed
      // deletions," reset the child to the current child to make sure we delete
      // it again. TODO: Find a better way to handle this, perhaps during a more
      // general overhaul of error handling.
      if (current === null) {
        workInProgress.child = null;
      } else if (workInProgress.child !== current.child) {
        workInProgress.child = current.child;
      }
  
      if (
        workInProgress.expirationTime === NoWork ||
        workInProgress.expirationTime > renderExpirationTime
      ) {
        return bailoutOnLowPriority(current, workInProgress);
      }
  
      // If we don't bail out, we're going be recomputing our children so we need
      // to drop our effect list.
      workInProgress.firstEffect = null;
      workInProgress.lastEffect = null;
  
      // Unmount the current children as if the component rendered null
      var nextChildren = null;
      reconcileChildrenAtExpirationTime(
        current,
        workInProgress,
        nextChildren,
        renderExpirationTime
      );
  
      if (workInProgress.tag === ClassComponent) {
        var instance = workInProgress.stateNode;
        workInProgress.memoizedProps = instance.props;
        workInProgress.memoizedState = instance.state;
      }
  
      return workInProgress.child;
    }
  
    return {
      beginWork: beginWork,
      beginFailedWork: beginFailedWork
    };
  };
  
  var ReactFiberCompleteWork = function(config, hostContext, hydrationContext) {
    var createInstance = config.createInstance,
      createTextInstance = config.createTextInstance,
      appendInitialChild = config.appendInitialChild,
      finalizeInitialChildren = config.finalizeInitialChildren,
      prepareUpdate = config.prepareUpdate,
      mutation = config.mutation,
      persistence = config.persistence;
    var getRootHostContainer = hostContext.getRootHostContainer,
      popHostContext = hostContext.popHostContext,
      getHostContext = hostContext.getHostContext,
      popHostContainer = hostContext.popHostContainer;
    var prepareToHydrateHostInstance =
        hydrationContext.prepareToHydrateHostInstance,
      prepareToHydrateHostTextInstance =
        hydrationContext.prepareToHydrateHostTextInstance,
      popHydrationState = hydrationContext.popHydrationState;
  
    function markUpdate(workInProgress) {
      // Tag the fiber with an update effect. This turns a Placement into
      // an UpdateAndPlacement.
      workInProgress.effectTag |= Update;
    }
  
    function markRef(workInProgress) {
      workInProgress.effectTag |= Ref;
    }
  
    function appendAllReturns(returns, workInProgress) {
      var node = workInProgress.stateNode;
      if (node) {
        node["return"] = workInProgress;
      }
      while (node !== null) {
        if (
          node.tag === HostComponent ||
          node.tag === HostText ||
          node.tag === HostPortal
        ) {
          invariant(false, "A call cannot have host component children.");
        } else if (node.tag === ReturnComponent) {
          returns.push(node.pendingProps.value);
        } else if (node.child !== null) {
          node.child["return"] = node;
          node = node.child;
          continue;
        }
        while (node.sibling === null) {
          if (node["return"] === null || node["return"] === workInProgress) {
            return;
          }
          node = node["return"];
        }
        node.sibling["return"] = node["return"];
        node = node.sibling;
      }
    }
  
    function moveCallToHandlerPhase(
      current,
      workInProgress,
      renderExpirationTime
    ) {
      var props = workInProgress.memoizedProps;
      invariant(
        props,
        "Should be resolved by now. This error is likely caused by a bug in " +
          "React. Please file an issue."
      );
  
      // First step of the call has completed. Now we need to do the second.
      // TODO: It would be nice to have a multi stage call represented by a
      // single component, or at least tail call optimize nested ones. Currently
      // that requires additional fields that we don't want to add to the fiber.
      // So this requires nested handlers.
      // Note: This doesn't mutate the alternate node. I don't think it needs to
      // since this stage is reset for every pass.
      workInProgress.tag = CallHandlerPhase;
  
      // Build up the returns.
      // TODO: Compare this to a generator or opaque helpers like Children.
      var returns = [];
      appendAllReturns(returns, workInProgress);
      var fn = props.handler;
      var childProps = props.props;
      var nextChildren = fn(childProps, returns);
  
      var currentFirstChild = current !== null ? current.child : null;
      workInProgress.child = reconcileChildFibers(
        workInProgress,
        currentFirstChild,
        nextChildren,
        renderExpirationTime
      );
      return workInProgress.child;
    }
  
    function appendAllChildren(parent, workInProgress) {
      // 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;
      }
    }
  
    var updateHostContainer = void 0;
    var updateHostComponent = void 0;
    var updateHostText = void 0;
    if (mutation) {
      if (enableMutatingReconciler) {
        // Mutation mode
        updateHostContainer = function(workInProgress) {
          // Noop
        };
        updateHostComponent = function(
          current,
          workInProgress,
          updatePayload,
          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 = 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 {
        invariant(false, "Mutating reconciler is disabled.");
      }
    } else if (persistence) {
      if (enablePersistentReconciler) {
        // Persistent host tree mode
        var cloneInstance = persistence.cloneInstance,
          createContainerChildSet = persistence.createContainerChildSet,
          appendChildToContainerChildSet =
            persistence.appendChildToContainerChildSet,
          finalizeContainerChildren = persistence.finalizeContainerChildren;
  
        // An unfortunate fork of appendAllChildren because we have two different parent types.
  
        var appendAllChildrenToContainer = function(
          containerChildSet,
          workInProgress
        ) {
          // 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) {
              appendChildToContainerChildSet(containerChildSet, 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) {
          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 (finalizeContainerChildren(container, newChildSet)) {
              markUpdate(workInProgress);
            }
            portalOrRoot.pendingChildren = newChildSet;
            // If children might have changed, we have to add them all to the set.
            appendAllChildrenToContainer(newChildSet, workInProgress);
            // Schedule an update on the container to swap out the container.
            markUpdate(workInProgress);
          }
        };
        updateHostComponent = function(
          current,
          workInProgress,
          updatePayload,
          type,
          oldProps,
          newProps,
          rootContainerInstance,
          currentHostContext
        ) {
          // 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;
          var currentInstance = current.stateNode;
          if (childrenUnchanged && updatePayload === null) {
            // No changes, just reuse the existing instance.
            // Note that this might release a previous clone.
            workInProgress.stateNode = currentInstance;
          } else {
            var recyclableInstance = workInProgress.stateNode;
            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);
            }
          }
        };
        updateHostText = 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 {
        invariant(false, "Persistent reconciler is disabled.");
      }
    } else {
      if (enableNoopReconciler) {
        // No host operations
        updateHostContainer = function(workInProgress) {
          // Noop
        };
        updateHostComponent = function(
          current,
          workInProgress,
          updatePayload,
          type,
          oldProps,
          newProps,
          rootContainerInstance,
          currentHostContext
        ) {
          // Noop
        };
        updateHostText = function(current, workInProgress, oldText, newText) {
          // Noop
        };
      } else {
        invariant(false, "Noop reconciler is disabled.");
      }
    }
  
    function completeWork(current, workInProgress, renderExpirationTime) {
      var newProps = workInProgress.pendingProps;
      switch (workInProgress.tag) {
        case FunctionalComponent:
          return null;
        case ClassComponent: {
          // We are leaving this subtree, so pop context if any.
          popContextProvider(workInProgress);
          return null;
        }
        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);
          return null;
        }
        case HostComponent: {
          popHostContext(workInProgress);
          var rootContainerInstance = getRootHostContainer();
          var type = workInProgress.type;
          if (current !== null && workInProgress.stateNode != null) {
            // 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 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();
            var updatePayload = prepareUpdate(
              instance,
              type,
              oldProps,
              newProps,
              rootContainerInstance,
              currentHostContext
            );
  
            updateHostComponent(
              current,
              workInProgress,
              updatePayload,
              type,
              oldProps,
              newProps,
              rootContainerInstance,
              currentHostContext
            );
  
            if (current.ref !== workInProgress.ref) {
              markRef(workInProgress);
            }
          } else {
            if (!newProps) {
              invariant(
                workInProgress.stateNode !== null,
                "We must have new props for new mounts. This error is likely " +
                  "caused by a bug in React. Please file an issue."
              );
              // This can happen when we abort work.
              return null;
            }
  
            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);
  
              // 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(workInProgress);
            }
          }
          return null;
        }
        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(current, workInProgress, oldText, newText);
          } else {
            if (typeof newText !== "string") {
              invariant(
                workInProgress.stateNode !== null,
                "We must have new props for new mounts. This error is likely " +
                  "caused by a bug in React. Please file an issue."
              );
              // This can happen when we abort work.
              return null;
            }
            var _rootContainerInstance = getRootHostContainer();
            var _currentHostContext2 = getHostContext();
            var _wasHydrated = popHydrationState(workInProgress);
            if (_wasHydrated) {
              if (prepareToHydrateHostTextInstance(workInProgress)) {
                markUpdate(workInProgress);
              }
            } else {
              workInProgress.stateNode = createTextInstance(
                newText,
                _rootContainerInstance,
                _currentHostContext2,
                workInProgress
              );
            }
          }
          return null;
        }
        case CallComponent:
          return moveCallToHandlerPhase(
            current,
            workInProgress,
            renderExpirationTime
          );
        case CallHandlerPhase:
          // Reset the tag to now be a first phase call.
          workInProgress.tag = CallComponent;
          return null;
        case ReturnComponent:
          // Does nothing.
          return null;
        case Fragment:
          return null;
        case Mode:
          return null;
        case HostPortal:
          popHostContainer(workInProgress);
          updateHostContainer(workInProgress);
          return null;
        case ContextProvider:
          // Pop provider fiber
          popProvider(workInProgress);
          return null;
        case ContextConsumer:
          return null;
        // Error cases
        case IndeterminateComponent:
          invariant(
            false,
            "An indeterminate component should have become determinate before " +
              "completing. This error is likely caused by a bug in React. Please " +
              "file an issue."
          );
        // eslint-disable-next-line no-fallthrough
        default:
          invariant(
            false,
            "Unknown unit of work tag. This error is likely caused by a bug in " +
              "React. Please file an issue."
          );
      }
    }
  
    return {
      completeWork: completeWork
    };
  };
  
  var invokeGuardedCallback$3 = ReactErrorUtils.invokeGuardedCallback;
  var hasCaughtError$1 = ReactErrorUtils.hasCaughtError;
  var clearCaughtError$1 = ReactErrorUtils.clearCaughtError;
  
  var ReactFiberCommitWork = function(config, captureError) {
    var getPublicInstance = config.getPublicInstance,
      mutation = config.mutation,
      persistence = config.persistence;
  
    var callComponentWillUnmountWithTimer = function(current, instance) {
      startPhaseTimer(current, "componentWillUnmount");
      instance.props = current.memoizedProps;
      instance.state = current.memoizedState;
      instance.componentWillUnmount();
      stopPhaseTimer();
    };
  
    // Capture errors so they don't interrupt unmounting.
    function safelyCallComponentWillUnmount(current, instance) {
      {
        invokeGuardedCallback$3(
          null,
          callComponentWillUnmountWithTimer,
          null,
          current,
          instance
        );
        if (hasCaughtError$1()) {
          var unmountError = clearCaughtError$1();
          captureError(current, unmountError);
        }
      }
    }
  
    function safelyDetachRef(current) {
      var ref = current.ref;
      if (ref !== null) {
        {
          invokeGuardedCallback$3(null, ref, null, null);
          if (hasCaughtError$1()) {
            var refError = clearCaughtError$1();
            captureError(current, refError);
          }
        }
      }
    }
  
    function commitLifeCycles(current, finishedWork) {
      switch (finishedWork.tag) {
        case ClassComponent: {
          var instance = finishedWork.stateNode;
          if (finishedWork.effectTag & Update) {
            if (current === null) {
              startPhaseTimer(finishedWork, "componentDidMount");
              instance.props = finishedWork.memoizedProps;
              instance.state = finishedWork.memoizedState;
              instance.componentDidMount();
              stopPhaseTimer();
            } else {
              var prevProps = current.memoizedProps;
              var prevState = current.memoizedState;
              startPhaseTimer(finishedWork, "componentDidUpdate");
              instance.props = finishedWork.memoizedProps;
              instance.state = finishedWork.memoizedState;
              instance.componentDidUpdate(prevProps, prevState);
              stopPhaseTimer();
            }
          }
          var updateQueue = finishedWork.updateQueue;
          if (updateQueue !== null) {
            commitCallbacks(updateQueue, instance);
          }
          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;
              }
            }
            commitCallbacks(_updateQueue, _instance);
          }
          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 === 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;
        }
        default: {
          invariant(
            false,
            "This unit of work tag should not have side-effects. This error is " +
              "likely caused by a bug in React. Please file an issue."
          );
        }
      }
    }
  
    function commitAttachRef(finishedWork) {
      var ref = finishedWork.ref;
      if (ref !== null) {
        var instance = finishedWork.stateNode;
        switch (finishedWork.tag) {
          case HostComponent:
            ref(getPublicInstance(instance));
            break;
          default:
            ref(instance);
        }
      }
    }
  
    function commitDetachRef(current) {
      var currentRef = current.ref;
      if (currentRef !== null) {
        currentRef(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) {
      if (typeof onCommitUnmount === "function") {
        onCommitUnmount(current);
      }
  
      switch (current.tag) {
        case ClassComponent: {
          safelyDetachRef(current);
          var instance = current.stateNode;
          if (typeof instance.componentWillUnmount === "function") {
            safelyCallComponentWillUnmount(current, instance);
          }
          return;
        }
        case HostComponent: {
          safelyDetachRef(current);
          return;
        }
        case CallComponent: {
          commitNestedUnmounts(current.stateNode);
          return;
        }
        case HostPortal: {
          // TODO: this is recursive.
          // We are also not using this parent because
          // the portal will get pushed immediately.
          if (enableMutatingReconciler && mutation) {
            unmountHostComponents(current);
          } else if (enablePersistentReconciler && persistence) {
            emptyPortalContainer(current);
          }
          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.
          (!mutation || 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) {
      // 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["return"] = null;
      current.child = null;
      if (current.alternate) {
        current.alternate.child = null;
        current.alternate["return"] = null;
      }
    }
  
    var emptyPortalContainer = void 0;
  
    if (!mutation) {
      var commitContainer = void 0;
      if (persistence) {
        var replaceContainerChildren = persistence.replaceContainerChildren,
          createContainerChildSet = persistence.createContainerChildSet;
  
        emptyPortalContainer = function(current) {
          var portal = current.stateNode;
          var containerInfo = portal.containerInfo;
  
          var emptyChildSet = createContainerChildSet(containerInfo);
          replaceContainerChildren(containerInfo, emptyChildSet);
        };
        commitContainer = function(finishedWork) {
          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: {
              invariant(
                false,
                "This unit of work tag should not have side-effects. This error is " +
                  "likely caused by a bug in React. Please file an issue."
              );
            }
          }
        };
      } else {
        commitContainer = function(finishedWork) {
          // Noop
        };
      }
      if (enablePersistentReconciler || enableNoopReconciler) {
        return {
          commitResetTextContent: function(finishedWork) {},
          commitPlacement: function(finishedWork) {},
          commitDeletion: function(current) {
            // Detach refs and call componentWillUnmount() on the whole subtree.
            commitNestedUnmounts(current);
            detachFiber(current);
          },
          commitWork: function(current, finishedWork) {
            commitContainer(finishedWork);
          },
  
          commitLifeCycles: commitLifeCycles,
          commitAttachRef: commitAttachRef,
          commitDetachRef: commitDetachRef
        };
      } else if (persistence) {
        invariant(false, "Persistent reconciler is disabled.");
      } else {
        invariant(false, "Noop reconciler is disabled.");
      }
    }
    var commitMount = mutation.commitMount,
      commitUpdate = mutation.commitUpdate,
      resetTextContent = mutation.resetTextContent,
      commitTextUpdate = mutation.commitTextUpdate,
      appendChild = mutation.appendChild,
      appendChildToContainer = mutation.appendChildToContainer,
      insertBefore = mutation.insertBefore,
      insertInContainerBefore = mutation.insertInContainerBefore,
      removeChild = mutation.removeChild,
      removeChildFromContainer = mutation.removeChildFromContainer;
  
    function getHostParentFiber(fiber) {
      var parent = fiber["return"];
      while (parent !== null) {
        if (isHostParent(parent)) {
          return parent;
        }
        parent = parent["return"];
      }
      invariant(
        false,
        "Expected to find a host parent. This error is likely caused by a bug " +
          "in React. Please file an issue."
      );
    }
  
    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) {
          // 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) {
      // Recursively insert all host nodes into the parent.
      var parentFiber = getHostParentFiber(finishedWork);
      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:
          invariant(
            false,
            "Invalid host parent fiber. This error is likely caused by a bug " +
              "in React. Please file an issue."
          );
      }
      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 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) {
      // We only have the top Fiber that was inserted but we need recurse down its
      var node = current;
  
      // Each iteration, currentParent is populated with node's host parent if not
      // currentParentIsValid.
      var currentParentIsValid = false;
      var currentParent = void 0;
      var currentParentIsContainer = void 0;
  
      while (true) {
        if (!currentParentIsValid) {
          var parent = node["return"];
          findParent: while (true) {
            invariant(
              parent !== null,
              "Expected to find a host parent. This error is likely caused by " +
                "a bug in React. Please file an issue."
            );
            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 (node.tag === HostPortal) {
          // 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;
          // Visit children because portals might contain host components.
          if (node.child !== null) {
            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) {
          return;
        }
        while (node.sibling === null) {
          if (node["return"] === null || node["return"] === current) {
            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) {
      // Recursively delete all host nodes from the parent.
      // Detach refs and call componentWillUnmount() on the whole subtree.
      unmountHostComponents(current);
      detachFiber(current);
    }
  
    function commitWork(current, finishedWork) {
      switch (finishedWork.tag) {
        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 !== null ? current.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: {
          invariant(
            finishedWork.stateNode !== null,
            "This should have a text node initialized. This error is likely " +
              "caused by a bug in React. Please file an issue."
          );
          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 !== null ? current.memoizedProps : newText;
          commitTextUpdate(textInstance, oldText, newText);
          return;
        }
        case HostRoot: {
          return;
        }
        default: {
          invariant(
            false,
            "This unit of work tag should not have side-effects. This error is " +
              "likely caused by a bug in React. Please file an issue."
          );
        }
      }
    }
  
    function commitResetTextContent(current) {
      resetTextContent(current.stateNode);
    }
  
    if (enableMutatingReconciler) {
      return {
        commitResetTextContent: commitResetTextContent,
        commitPlacement: commitPlacement,
        commitDeletion: commitDeletion,
        commitWork: commitWork,
        commitLifeCycles: commitLifeCycles,
        commitAttachRef: commitAttachRef,
        commitDetachRef: commitDetachRef
      };
    } else {
      invariant(false, "Mutating reconciler is disabled.");
    }
  };
  
  var NO_CONTEXT = {};
  
  var ReactFiberHostContext = function(config) {
    var getChildHostContext = config.getChildHostContext,
      getRootHostContext = config.getRootHostContext;
  
    var contextStackCursor = createCursor(NO_CONTEXT);
    var contextFiberStackCursor = createCursor(NO_CONTEXT);
    var rootInstanceStackCursor = createCursor(NO_CONTEXT);
  
    function requiredContext(c) {
      invariant(
        c !== NO_CONTEXT,
        "Expected host context to exist. This error is likely caused by a bug " +
          "in React. Please file an issue."
      );
      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);
  
      var nextRootContext = getRootHostContext(nextRootInstance);
  
      // 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, nextRootContext, fiber);
    }
  
    function popHostContainer(fiber) {
      pop(contextStackCursor, fiber);
      pop(contextFiberStackCursor, fiber);
      pop(rootInstanceStackCursor, fiber);
    }
  
    function getHostContext() {
      var context = requiredContext(contextStackCursor.current);
      return context;
    }
  
    function pushHostContext(fiber) {
      var rootInstance = requiredContext(rootInstanceStackCursor.current);
      var context = requiredContext(contextStackCursor.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, 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, fiber);
      pop(contextFiberStackCursor, fiber);
    }
  
    function resetHostContainer() {
      contextStackCursor.current = NO_CONTEXT;
      rootInstanceStackCursor.current = NO_CONTEXT;
    }
  
    return {
      getHostContext: getHostContext,
      getRootHostContainer: getRootHostContainer,
      popHostContainer: popHostContainer,
      popHostContext: popHostContext,
      pushHostContainer: pushHostContainer,
      pushHostContext: pushHostContext,
      resetHostContainer: resetHostContainer
    };
  };
  
  var ReactFiberHydrationContext = function(config) {
    var shouldSetTextContent = config.shouldSetTextContent,
      hydration = config.hydration;
  
    // If this doesn't have hydration mode.
  
    if (!hydration) {
      return {
        enterHydrationState: function() {
          return false;
        },
        resetHydrationState: function() {},
        tryToClaimNextHydratableInstance: function() {},
        prepareToHydrateHostInstance: function() {
          invariant(
            false,
            "Expected prepareToHydrateHostInstance() to never be called. " +
              "This error is likely caused by a bug in React. Please file an issue."
          );
        },
        prepareToHydrateHostTextInstance: function() {
          invariant(
            false,
            "Expected prepareToHydrateHostTextInstance() to never be called. " +
              "This error is likely caused by a bug in React. Please file an issue."
          );
        },
        popHydrationState: function(fiber) {
          return false;
        }
      };
    }
  
    var canHydrateInstance = hydration.canHydrateInstance,
      canHydrateTextInstance = hydration.canHydrateTextInstance,
      getNextHydratableSibling = hydration.getNextHydratableSibling,
      getFirstHydratableChild = hydration.getFirstHydratableChild,
      hydrateInstance = hydration.hydrateInstance,
      hydrateTextInstance = hydration.hydrateTextInstance,
      didNotMatchHydratedContainerTextInstance =
        hydration.didNotMatchHydratedContainerTextInstance,
      didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance,
      didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance,
      didNotHydrateInstance = hydration.didNotHydrateInstance,
      didNotFindHydratableContainerInstance =
        hydration.didNotFindHydratableContainerInstance,
      didNotFindHydratableContainerTextInstance =
        hydration.didNotFindHydratableContainerTextInstance,
      didNotFindHydratableInstance = hydration.didNotFindHydratableInstance,
      didNotFindHydratableTextInstance =
        hydration.didNotFindHydratableTextInstance;
  
    // 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) {
      var parentInstance = fiber.stateNode.containerInfo;
      nextHydratableInstance = getFirstHydratableChild(parentInstance);
      hydrationParentFiber = fiber;
      isHydrating = true;
      return true;
    }
  
    function deleteHydratableInstance(returnFiber, instance) {
      {
        switch (returnFiber.tag) {
          case HostRoot:
            didNotHydrateContainerInstance(
              returnFiber.stateNode.containerInfo,
              instance
            );
            break;
          case HostComponent:
            didNotHydrateInstance(
              returnFiber.type,
              returnFiber.memoizedProps,
              returnFiber.stateNode,
              instance
            );
            break;
        }
      }
  
      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;
      {
        switch (returnFiber.tag) {
          case HostRoot: {
            var parentContainer = returnFiber.stateNode.containerInfo;
            switch (fiber.tag) {
              case HostComponent:
                var type = fiber.type;
                var props = fiber.pendingProps;
                didNotFindHydratableContainerInstance(
                  parentContainer,
                  type,
                  props
                );
                break;
              case HostText:
                var text = fiber.pendingProps;
                didNotFindHydratableContainerTextInstance(parentContainer, text);
                break;
            }
            break;
          }
          case HostComponent: {
            var parentType = returnFiber.type;
            var parentProps = returnFiber.memoizedProps;
            var parentInstance = returnFiber.stateNode;
            switch (fiber.tag) {
              case HostComponent:
                var _type = fiber.type;
                var _props = fiber.pendingProps;
                didNotFindHydratableInstance(
                  parentType,
                  parentProps,
                  parentInstance,
                  _type,
                  _props
                );
                break;
              case HostText:
                var _text = fiber.pendingProps;
                didNotFindHydratableTextInstance(
                  parentType,
                  parentProps,
                  parentInstance,
                  _text
                );
                break;
            }
            break;
          }
          default:
            return;
        }
      }
    }
  
    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;
        }
        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;
      }
      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(nextInstance);
        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, nextHydratableInstance);
      }
      hydrationParentFiber = fiber;
      nextHydratableInstance = getFirstHydratableChild(nextInstance);
    }
  
    function prepareToHydrateHostInstance(
      fiber,
      rootContainerInstance,
      hostContext
    ) {
      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) {
      var textInstance = fiber.stateNode;
      var textContent = fiber.memoizedProps;
      var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber);
      {
        if (shouldUpdate) {
          // We assume that prepareToHydrateHostTextInstance is called in a context where the
          // hydration parent is the parent host component of this host text.
          var returnFiber = hydrationParentFiber;
          if (returnFiber !== null) {
            switch (returnFiber.tag) {
              case HostRoot: {
                var parentContainer = returnFiber.stateNode.containerInfo;
                didNotMatchHydratedContainerTextInstance(
                  parentContainer,
                  textInstance,
                  textContent
                );
                break;
              }
              case HostComponent: {
                var parentType = returnFiber.type;
                var parentProps = returnFiber.memoizedProps;
                var parentInstance = returnFiber.stateNode;
                didNotMatchHydratedTextInstance(
                  parentType,
                  parentProps,
                  parentInstance,
                  textInstance,
                  textContent
                );
                break;
              }
            }
          }
        }
      }
      return shouldUpdate;
    }
  
    function popToNextHostParent(fiber) {
      var parent = fiber["return"];
      while (
        parent !== null &&
        parent.tag !== HostComponent &&
        parent.tag !== HostRoot
      ) {
        parent = parent["return"];
      }
      hydrationParentFiber = parent;
    }
  
    function popHydrationState(fiber) {
      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() {
      hydrationParentFiber = null;
      nextHydratableInstance = null;
      isHydrating = false;
    }
  
    return {
      enterHydrationState: enterHydrationState,
      resetHydrationState: resetHydrationState,
      tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance,
      prepareToHydrateHostInstance: prepareToHydrateHostInstance,
      prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance,
      popHydrationState: popHydrationState
    };
  };
  
  // 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.
  var ReactFiberInstrumentation = {
    debugTool: null
  };
  
  var ReactFiberInstrumentation_1 = ReactFiberInstrumentation;
  
  // 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;
    var suppressLogging = error && error.suppressReactErrorLogging;
    if (suppressLogging) {
      return;
    }
  
    {
      var componentName = capturedError.componentName,
        componentStack = capturedError.componentStack,
        errorBoundaryName = capturedError.errorBoundaryName,
        errorBoundaryFound = capturedError.errorBoundaryFound,
        willRetry = capturedError.willRetry;
  
      var componentNameMessage = componentName
        ? "The above error occurred in the <" + componentName + "> component:"
        : "The above error occurred in one of your React components:";
  
      var errorBoundaryMessage = void 0;
      // errorBoundaryFound check is sufficient; errorBoundaryName check is to satisfy Flow.
      if (errorBoundaryFound && errorBoundaryName) {
        if (willRetry) {
          errorBoundaryMessage =
            "React will try to recreate this component tree from scratch " +
            ("using the error boundary you provided, " + errorBoundaryName + ".");
        } else {
          errorBoundaryMessage =
            "This error was initially handled by the error boundary " +
            errorBoundaryName +
            ".\n" +
            "Recreating the tree from scratch failed so React will unmount the tree.";
        }
      } else {
        errorBoundaryMessage =
          "Consider adding an error boundary to your tree to customize error handling behavior.\n" +
          "Visit https://fb.me/react-error-boundaries to learn more about error boundaries.";
      }
      var combinedMessage =
        "" +
        componentNameMessage +
        componentStack +
        "\n\n" +
        ("" + errorBoundaryMessage);
  
      // In development, we provide our own message with just the component stack.
      // We don't include the original error message and JS stack because the browser
      // has already printed it. Even if the application swallows the error, it is still
      // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils.
      console.error(combinedMessage);
    }
  }
  
  var invokeGuardedCallback$2 = ReactErrorUtils.invokeGuardedCallback;
  var hasCaughtError = ReactErrorUtils.hasCaughtError;
  var clearCaughtError = ReactErrorUtils.clearCaughtError;
  
  var didWarnAboutStateTransition = void 0;
  var didWarnSetStateChildContext = void 0;
  var warnAboutUpdateOnUnmounted = void 0;
  var warnAboutInvalidUpdates = void 0;
  
  {
    didWarnAboutStateTransition = false;
    didWarnSetStateChildContext = false;
    var didWarnStateUpdateForUnmountedComponent = {};
  
    warnAboutUpdateOnUnmounted = function(fiber) {
      var componentName = getComponentName(fiber) || "ReactClass";
      if (didWarnStateUpdateForUnmountedComponent[componentName]) {
        return;
      }
      warning(
        false,
        "Can only update a mounted or mounting " +
          "component. This usually means you called setState, replaceState, " +
          "or forceUpdate on an unmounted component. This is a no-op.\n\nPlease " +
          "check the code for the %s component.",
        componentName
      );
      didWarnStateUpdateForUnmountedComponent[componentName] = true;
    };
  
    warnAboutInvalidUpdates = function(instance) {
      switch (ReactDebugCurrentFiber.phase) {
        case "getChildContext":
          if (didWarnSetStateChildContext) {
            return;
          }
          warning(
            false,
            "setState(...): Cannot call setState() inside getChildContext()"
          );
          didWarnSetStateChildContext = true;
          break;
        case "render":
          if (didWarnAboutStateTransition) {
            return;
          }
          warning(
            false,
            "Cannot update during an existing state transition (such as within " +
              "`render` or another component's constructor). Render methods should " +
              "be a pure function of props and state; constructor side-effects are " +
              "an anti-pattern, but can be moved to `componentWillMount`."
          );
          didWarnAboutStateTransition = true;
          break;
      }
    };
  }
  
  var ReactFiberScheduler = function(config) {
    var hostContext = ReactFiberHostContext(config);
    var hydrationContext = ReactFiberHydrationContext(config);
    var popHostContainer = hostContext.popHostContainer,
      popHostContext = hostContext.popHostContext,
      resetHostContainer = hostContext.resetHostContainer;
  
    var _ReactFiberBeginWork = ReactFiberBeginWork(
        config,
        hostContext,
        hydrationContext,
        scheduleWork,
        computeExpirationForFiber
      ),
      beginWork = _ReactFiberBeginWork.beginWork,
      beginFailedWork = _ReactFiberBeginWork.beginFailedWork;
  
    var _ReactFiberCompleteWo = ReactFiberCompleteWork(
        config,
        hostContext,
        hydrationContext
      ),
      completeWork = _ReactFiberCompleteWo.completeWork;
  
    var _ReactFiberCommitWork = ReactFiberCommitWork(config, captureError),
      commitResetTextContent = _ReactFiberCommitWork.commitResetTextContent,
      commitPlacement = _ReactFiberCommitWork.commitPlacement,
      commitDeletion = _ReactFiberCommitWork.commitDeletion,
      commitWork = _ReactFiberCommitWork.commitWork,
      commitLifeCycles = _ReactFiberCommitWork.commitLifeCycles,
      commitAttachRef = _ReactFiberCommitWork.commitAttachRef,
      commitDetachRef = _ReactFiberCommitWork.commitDetachRef;
  
    var now = config.now,
      scheduleDeferredCallback = config.scheduleDeferredCallback,
      cancelDeferredCallback = config.cancelDeferredCallback,
      prepareForCommit = config.prepareForCommit,
      resetAfterCommit = config.resetAfterCommit;
  
    // Represents the current time in ms.
  
    var startTime = now();
    var mostRecentCurrentTime = msToExpirationTime(0);
  
    // Used to ensure computeUniqueAsyncExpiration is monotonically increases.
    var lastUniqueAsyncExpiration = 0;
  
    // Represents the expiration time that incoming updates should use. (If this
    // is NoWork, use the default strategy: async updates in async mode, sync
    // updates in sync mode.)
    var expirationContext = NoWork;
  
    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;
  
    // The next fiber with an effect that we're currently committing.
    var nextEffect = null;
  
    // Keep track of which fibers have captured an error that need to be handled.
    // Work is removed from this collection after componentDidCatch is called.
    var capturedErrors = null;
    // Keep track of which fibers have failed during the current batch of work.
    // This is a different set than capturedErrors, because it is not reset until
    // the end of the batch. This is needed to propagate errors correctly if a
    // subtree fails more than once.
    var failedBoundaries = null;
    // Error boundaries that captured an error during the current commit.
    var commitPhaseBoundaries = null;
    var firstUncaughtError = null;
    var didFatal = false;
  
    var isCommitting = false;
    var isUnmounting = false;
  
    // Used for performance tracking.
    var interruptedBy = null;
  
    function resetContextStack() {
      // Reset the stack
      reset();
      // Reset the cursors
      resetContext();
      resetProviderStack();
      resetHostContainer();
    }
  
    function commitAllHostEffects() {
      while (nextEffect !== null) {
        {
          ReactDebugCurrentFiber.setCurrentFiber(nextEffect);
        }
        recordEffect();
  
        var effectTag = nextEffect.effectTag;
        if (effectTag & ContentReset) {
          commitResetTextContent(nextEffect);
        }
  
        if (effectTag & Ref) {
          var current = nextEffect.alternate;
          if (current !== null) {
            commitDetachRef(current);
          }
        }
  
        // 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 & ~(Callback | Err | ContentReset | Ref | PerformedWork);
        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: {
            isUnmounting = true;
            commitDeletion(nextEffect);
            isUnmounting = false;
            break;
          }
        }
        nextEffect = nextEffect.nextEffect;
      }
  
      {
        ReactDebugCurrentFiber.resetCurrentFiber();
      }
    }
  
    function commitAllLifeCycles() {
      {
        ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings();
  
        if (warnAboutDeprecatedLifecycles) {
          ReactStrictModeWarnings.flushPendingDeprecationWarnings();
        }
      }
  
      while (nextEffect !== null) {
        var effectTag = nextEffect.effectTag;
  
        if (effectTag & (Update | Callback)) {
          recordEffect();
          var current = nextEffect.alternate;
          commitLifeCycles(current, nextEffect);
        }
  
        if (effectTag & Ref) {
          recordEffect();
          commitAttachRef(nextEffect);
        }
  
        if (effectTag & Err) {
          recordEffect();
          commitErrorHandling(nextEffect);
        }
  
        var next = nextEffect.nextEffect;
        // Ensure that we clean these up so that we don't accidentally keep them.
        // I'm not actually sure this matters because we can't reset firstEffect
        // and lastEffect since they're on every node, not just the effectful
        // ones. So we have to clean everything as we reuse nodes anyway.
        nextEffect.nextEffect = null;
        // Ensure that we reset the effectTag here so that we can rely on effect
        // tags to reason about the current life-cycle.
        nextEffect = next;
      }
    }
  
    function commitRoot(finishedWork) {
      // We keep track of this so that captureError can collect any boundaries
      // that capture an error during the commit phase. The reason these aren't
      // local to this function is because errors that occur during cWU are
      // captured elsewhere, to prevent the unmount from being interrupted.
      isWorking = true;
      isCommitting = true;
      startCommitTimer();
  
      var root = finishedWork.stateNode;
      invariant(
        root.current !== finishedWork,
        "Cannot commit the same tree as before. This is probably a bug " +
          "related to the return field. This error is likely caused by a bug " +
          "in React. Please file an issue."
      );
      root.isReadyForCommit = false;
  
      // Reset this to null before calling lifecycles
      ReactCurrentOwner.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);
  
      // 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;
        {
          invokeGuardedCallback$2(null, commitAllHostEffects, null);
          if (hasCaughtError()) {
            didError = true;
            _error = clearCaughtError();
          }
        }
        if (didError) {
          invariant(
            nextEffect !== null,
            "Should have next effect. This error is likely caused by a bug " +
              "in React. Please file an issue."
          );
          captureError(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 _didError = false;
        var _error2 = void 0;
        {
          invokeGuardedCallback$2(null, commitAllLifeCycles, null);
          if (hasCaughtError()) {
            _didError = true;
            _error2 = clearCaughtError();
          }
        }
        if (_didError) {
          invariant(
            nextEffect !== null,
            "Should have next effect. This error is likely caused by a bug " +
              "in React. Please file an issue."
          );
          captureError(nextEffect, _error2);
          if (nextEffect !== null) {
            nextEffect = nextEffect.nextEffect;
          }
        }
      }
  
      isCommitting = false;
      isWorking = false;
      stopCommitLifeCyclesTimer();
      stopCommitTimer();
      if (typeof onCommitRoot === "function") {
        onCommitRoot(finishedWork.stateNode);
      }
      if (true && ReactFiberInstrumentation_1.debugTool) {
        ReactFiberInstrumentation_1.debugTool.onCommitWork(finishedWork);
      }
  
      // If we caught any errors during this commit, schedule their boundaries
      // to update.
      if (commitPhaseBoundaries) {
        commitPhaseBoundaries.forEach(scheduleErrorRecovery);
        commitPhaseBoundaries = null;
      }
  
      if (firstUncaughtError !== null) {
        var _error3 = firstUncaughtError;
        firstUncaughtError = null;
        onUncaughtError(_error3);
      }
  
      var remainingTime = root.current.expirationTime;
  
      if (remainingTime === NoWork) {
        capturedErrors = null;
        failedBoundaries = null;
      }
  
      return remainingTime;
    }
  
    function resetExpirationTime(workInProgress, renderTime) {
      if (renderTime !== Never && workInProgress.expirationTime === Never) {
        // The children of this component are hidden. Don't bubble their
        // expiration times.
        return;
      }
  
      // Check for pending updates.
      var newExpirationTime = getUpdateExpirationTime(workInProgress);
  
      // TODO: Calls need to visit stateNode
  
      // Bubble up the earliest expiration time.
      var child = workInProgress.child;
      while (child !== null) {
        if (
          child.expirationTime !== NoWork &&
          (newExpirationTime === NoWork ||
            newExpirationTime > child.expirationTime)
        ) {
          newExpirationTime = child.expirationTime;
        }
        child = child.sibling;
      }
      workInProgress.expirationTime = newExpirationTime;
    }
  
    function completeUnitOfWork(workInProgress) {
      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 = workInProgress.alternate;
        {
          ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
        }
        var next = completeWork(
          current,
          workInProgress,
          nextRenderExpirationTime
        );
        {
          ReactDebugCurrentFiber.resetCurrentFiber();
        }
  
        var returnFiber = workInProgress["return"];
        var siblingFiber = workInProgress.sibling;
  
        resetExpirationTime(workInProgress, nextRenderExpirationTime);
  
        if (next !== null) {
          stopWorkTimer(workInProgress);
          if (true && ReactFiberInstrumentation_1.debugTool) {
            ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress);
          }
          // If completing this work spawned new work, do that next. We'll come
          // back here again.
          return next;
        }
  
        if (returnFiber !== null) {
          // 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;
          }
        }
  
        stopWorkTimer(workInProgress);
        if (true && ReactFiberInstrumentation_1.debugTool) {
          ReactFiberInstrumentation_1.debugTool.onCompleteWork(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.
          var root = workInProgress.stateNode;
          root.isReadyForCommit = true;
          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 = workInProgress.alternate;
  
      // See if beginning this work spawns more work.
      startWorkTimer(workInProgress);
      {
        ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
      }
  
      var next = beginWork(current, workInProgress, nextRenderExpirationTime);
      {
        ReactDebugCurrentFiber.resetCurrentFiber();
      }
      if (true && ReactFiberInstrumentation_1.debugTool) {
        ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
      }
  
      if (next === null) {
        // If this doesn't spawn new work, complete the current work.
        next = completeUnitOfWork(workInProgress);
      }
  
      ReactCurrentOwner.current = null;
  
      return next;
    }
  
    function performFailedUnitOfWork(workInProgress) {
      {
        ReactStrictModeWarnings.discardPendingWarnings();
      }
  
      // 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 = workInProgress.alternate;
  
      // See if beginning this work spawns more work.
      startWorkTimer(workInProgress);
      {
        ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
      }
      var next = beginFailedWork(
        current,
        workInProgress,
        nextRenderExpirationTime
      );
      {
        ReactDebugCurrentFiber.resetCurrentFiber();
      }
      if (true && ReactFiberInstrumentation_1.debugTool) {
        ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
      }
  
      if (next === null) {
        // If this doesn't spawn new work, complete the current work.
        next = completeUnitOfWork(workInProgress);
      }
  
      ReactCurrentOwner.current = null;
  
      return next;
    }
  
    function workLoop(isAsync) {
      if (capturedErrors !== null) {
        // If there are unhandled errors, switch to the slow work loop.
        // TODO: How to avoid this check in the fast path? Maybe the renderer
        // could keep track of which roots have unhandled errors and call a
        // forked version of renderRoot.
        slowWorkLoopThatChecksForFailedWork(isAsync);
        return;
      }
      if (!isAsync) {
        // Flush all expired work.
        while (nextUnitOfWork !== null) {
          nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
        }
      } else {
        // Flush asynchronous work until the deadline runs out of time.
        while (nextUnitOfWork !== null && !shouldYield()) {
          nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
        }
      }
    }
  
    function slowWorkLoopThatChecksForFailedWork(isAsync) {
      if (!isAsync) {
        // Flush all expired work.
        while (nextUnitOfWork !== null) {
          if (hasCapturedError(nextUnitOfWork)) {
            // Use a forked version of performUnitOfWork
            nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork);
          } else {
            nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
          }
        }
      } else {
        // Flush asynchronous work until the deadline runs out of time.
        while (nextUnitOfWork !== null && !shouldYield()) {
          if (hasCapturedError(nextUnitOfWork)) {
            // Use a forked version of performUnitOfWork
            nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork);
          } else {
            nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
          }
        }
      }
    }
  
    function renderRootCatchBlock(root, failedWork, boundary, isAsync) {
      // We're going to restart the error boundary that captured the error.
      // Conceptually, we're unwinding the stack. We need to unwind the
      // context stack, too.
      unwindContexts(failedWork, boundary);
  
      // Restart the error boundary using a forked version of
      // performUnitOfWork that deletes the boundary's children. The entire
      // failed subree will be unmounted. During the commit phase, a special
      // lifecycle method is called on the error boundary, which triggers
      // a re-render.
      nextUnitOfWork = performFailedUnitOfWork(boundary);
  
      // Continue working.
      workLoop(isAsync);
    }
  
    function renderRoot(root, expirationTime, isAsync) {
      invariant(
        !isWorking,
        "renderRoot was called recursively. This error is likely caused " +
          "by a bug in React. Please file an issue."
      );
      isWorking = true;
  
      // We're about to mutate the work-in-progress tree. If the root was pending
      // commit, it no longer is: we'll need to complete it again.
      root.isReadyForCommit = false;
  
      // Check if we're starting from a fresh stack, or if we're resuming from
      // previously yielded work.
      if (
        root !== nextRoot ||
        expirationTime !== nextRenderExpirationTime ||
        nextUnitOfWork === null
      ) {
        // Reset the stack and start working from the root.
        resetContextStack();
        nextRoot = root;
        nextRenderExpirationTime = expirationTime;
        nextUnitOfWork = createWorkInProgress(
          nextRoot.current,
          null,
          expirationTime
        );
      }
  
      startWorkLoopTimer(nextUnitOfWork);
  
      var didError = false;
      var error = null;
      {
        invokeGuardedCallback$2(null, workLoop, null, isAsync);
        if (hasCaughtError()) {
          didError = true;
          error = clearCaughtError();
        }
      }
  
      // An error was thrown during the render phase.
      while (didError) {
        if (didFatal) {
          // This was a fatal error. Don't attempt to recover from it.
          firstUncaughtError = error;
          break;
        }
  
        var failedWork = nextUnitOfWork;
        if (failedWork === null) {
          // An error was thrown but there's no current unit of work. This can
          // happen during the commit phase if there's a bug in the renderer.
          didFatal = true;
          continue;
        }
  
        // "Capture" the error by finding the nearest boundary. If there is no
        // error boundary, we use the root.
        var boundary = captureError(failedWork, error);
        invariant(
          boundary !== null,
          "Should have found an error boundary. This error is likely " +
            "caused by a bug in React. Please file an issue."
        );
  
        if (didFatal) {
          // The error we just captured was a fatal error. This happens
          // when the error propagates to the root more than once.
          continue;
        }
  
        didError = false;
        error = null;
        {
          invokeGuardedCallback$2(
            null,
            renderRootCatchBlock,
            null,
            root,
            failedWork,
            boundary,
            isAsync
          );
          if (hasCaughtError()) {
            didError = true;
            error = clearCaughtError();
            continue;
          }
        }
        // We're finished working. Exit the error loop.
        break;
      }
  
      var uncaughtError = firstUncaughtError;
  
      // We're done performing work. Time to clean up.
      stopWorkLoopTimer(interruptedBy);
      interruptedBy = null;
      isWorking = false;
      didFatal = false;
      firstUncaughtError = null;
  
      if (uncaughtError !== null) {
        onUncaughtError(uncaughtError);
      }
  
      return root.isReadyForCommit ? root.current.alternate : null;
    }
  
    // Returns the boundary that captured the error, or null if the error is ignored
    function captureError(failedWork, error) {
      // It is no longer valid because we exited the user code.
      ReactCurrentOwner.current = null;
      {
        ReactDebugCurrentFiber.resetCurrentFiber();
      }
  
      // Search for the nearest error boundary.
      var boundary = null;
  
      // Passed to logCapturedError()
      var errorBoundaryFound = false;
      var willRetry = false;
      var errorBoundaryName = null;
  
      // Host containers are a special case. If the failed work itself is a host
      // container, then it acts as its own boundary. In all other cases, we
      // ignore the work itself and only search through the parents.
      if (failedWork.tag === HostRoot) {
        boundary = failedWork;
  
        if (isFailedBoundary(failedWork)) {
          // If this root already failed, there must have been an error when
          // attempting to unmount it. This is a worst-case scenario and
          // should only be possible if there's a bug in the renderer.
          didFatal = true;
        }
      } else {
        var node = failedWork["return"];
        while (node !== null && boundary === null) {
          if (node.tag === ClassComponent) {
            var instance = node.stateNode;
            if (typeof instance.componentDidCatch === "function") {
              errorBoundaryFound = true;
              errorBoundaryName = getComponentName(node);
  
              // Found an error boundary!
              boundary = node;
              willRetry = true;
            }
          } else if (node.tag === HostRoot) {
            // Treat the root like a no-op error boundary
            boundary = node;
          }
  
          if (isFailedBoundary(node)) {
            // This boundary is already in a failed state.
  
            // If we're currently unmounting, that means this error was
            // thrown while unmounting a failed subtree. We should ignore
            // the error.
            if (isUnmounting) {
              return null;
            }
  
            // If we're in the commit phase, we should check to see if
            // this boundary already captured an error during this commit.
            // This case exists because multiple errors can be thrown during
            // a single commit without interruption.
            if (
              commitPhaseBoundaries !== null &&
              (commitPhaseBoundaries.has(node) ||
                (node.alternate !== null &&
                  commitPhaseBoundaries.has(node.alternate)))
            ) {
              // If so, we should ignore this error.
              return null;
            }
  
            // The error should propagate to the next boundary -— we keep looking.
            boundary = null;
            willRetry = false;
          }
  
          node = node["return"];
        }
      }
  
      if (boundary !== null) {
        // Add to the collection of failed boundaries. This lets us know that
        // subsequent errors in this subtree should propagate to the next boundary.
        if (failedBoundaries === null) {
          failedBoundaries = new Set();
        }
        failedBoundaries.add(boundary);
  
        // This method is unsafe outside of the begin and complete phases.
        // We might be in the commit phase when an error is captured.
        // The risk is that the return path from this Fiber may not be accurate.
        // That risk is acceptable given the benefit of providing users more context.
        var _componentStack = getStackAddendumByWorkInProgressFiber(failedWork);
        var _componentName = getComponentName(failedWork);
  
        // Add to the collection of captured errors. This is stored as a global
        // map of errors and their component stack location keyed by the boundaries
        // that capture them. We mostly use this Map as a Set; it's a Map only to
        // avoid adding a field to Fiber to store the error.
        if (capturedErrors === null) {
          capturedErrors = new Map();
        }
  
        var capturedError = {
          componentName: _componentName,
          componentStack: _componentStack,
          error: error,
          errorBoundary: errorBoundaryFound ? boundary.stateNode : null,
          errorBoundaryFound: errorBoundaryFound,
          errorBoundaryName: errorBoundaryName,
          willRetry: willRetry
        };
  
        capturedErrors.set(boundary, capturedError);
  
        try {
          logCapturedError(capturedError);
        } catch (e) {
          // Prevent cycle if logCapturedError() throws.
          // A cycle may still occur if logCapturedError renders a component that throws.
          var suppressLogging = e && e.suppressReactErrorLogging;
          if (!suppressLogging) {
            console.error(e);
          }
        }
  
        // If we're in the commit phase, defer scheduling an update on the
        // boundary until after the commit is complete
        if (isCommitting) {
          if (commitPhaseBoundaries === null) {
            commitPhaseBoundaries = new Set();
          }
          commitPhaseBoundaries.add(boundary);
        } else {
          // Otherwise, schedule an update now.
          // TODO: Is this actually necessary during the render phase? Is it
          // possible to unwind and continue rendering at the same priority,
          // without corrupting internal state?
          scheduleErrorRecovery(boundary);
        }
        return boundary;
      } else if (firstUncaughtError === null) {
        // If no boundary is found, we'll need to throw the error
        firstUncaughtError = error;
      }
      return null;
    }
  
    function hasCapturedError(fiber) {
      // TODO: capturedErrors should store the boundary instance, to avoid needing
      // to check the alternate.
      return (
        capturedErrors !== null &&
        (capturedErrors.has(fiber) ||
          (fiber.alternate !== null && capturedErrors.has(fiber.alternate)))
      );
    }
  
    function isFailedBoundary(fiber) {
      // TODO: failedBoundaries should store the boundary instance, to avoid
      // needing to check the alternate.
      return (
        failedBoundaries !== null &&
        (failedBoundaries.has(fiber) ||
          (fiber.alternate !== null && failedBoundaries.has(fiber.alternate)))
      );
    }
  
    function commitErrorHandling(effectfulFiber) {
      var capturedError = void 0;
      if (capturedErrors !== null) {
        capturedError = capturedErrors.get(effectfulFiber);
        capturedErrors["delete"](effectfulFiber);
        if (capturedError == null) {
          if (effectfulFiber.alternate !== null) {
            effectfulFiber = effectfulFiber.alternate;
            capturedError = capturedErrors.get(effectfulFiber);
            capturedErrors["delete"](effectfulFiber);
          }
        }
      }
  
      invariant(
        capturedError != null,
        "No error for given unit of work. This error is likely caused by a " +
          "bug in React. Please file an issue."
      );
  
      switch (effectfulFiber.tag) {
        case ClassComponent:
          var instance = effectfulFiber.stateNode;
  
          var info = {
            componentStack: capturedError.componentStack
          };
  
          // Allow the boundary to handle the error, usually by scheduling
          // an update to itself
          instance.componentDidCatch(capturedError.error, info);
          return;
        case HostRoot:
          if (firstUncaughtError === null) {
            firstUncaughtError = capturedError.error;
          }
          return;
        default:
          invariant(
            false,
            "Invalid type of work. This error is likely caused by a bug in " +
              "React. Please file an issue."
          );
      }
    }
  
    function unwindContexts(from, to) {
      var node = from;
      while (node !== null) {
        switch (node.tag) {
          case ClassComponent:
            popContextProvider(node);
            break;
          case HostComponent:
            popHostContext(node);
            break;
          case HostRoot:
            popHostContainer(node);
            break;
          case HostPortal:
            popHostContainer(node);
            break;
          case ContextProvider:
            popProvider(node);
            break;
        }
        if (node === to || node.alternate === to) {
          stopFailedWorkTimer(node);
          break;
        } else {
          stopWorkTimer(node);
        }
        node = node["return"];
      }
    }
  
    function computeAsyncExpiration() {
      // Given the current clock time, returns an expiration time. We use rounding
      // to batch like updates together.
      // Should complete within ~1000ms. 1200ms max.
      var currentTime = recalculateCurrentTime();
      var expirationMs = 1000;
      var bucketSizeMs = 200;
      return computeExpirationBucket(currentTime, expirationMs, bucketSizeMs);
    }
  
    function computeInteractiveExpiration() {
      // Should complete within ~500ms. 600ms max.
      var currentTime = recalculateCurrentTime();
      var expirationMs = 500;
      var bucketSizeMs = 100;
      return computeExpirationBucket(currentTime, expirationMs, bucketSizeMs);
    }
  
    // Creates a unique async expiration time.
    function computeUniqueAsyncExpiration() {
      var result = computeAsyncExpiration();
      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(fiber) {
      var expirationTime = void 0;
      if (expirationContext !== NoWork) {
        // An explicit expiration context was set;
        expirationTime = expirationContext;
      } else if (isWorking) {
        if (isCommitting) {
          // Updates that occur during the commit phase should have sync priority
          // by default.
          expirationTime = Sync;
        } else {
          // Updates during the render phase should expire at the same time as
          // the work that is being rendered.
          expirationTime = nextRenderExpirationTime;
        }
      } else {
        // No explicit expiration context was set, and we're not currently
        // performing work. Calculate a new expiration time.
        if (fiber.mode & AsyncMode) {
          if (isBatchingInteractiveUpdates) {
            // This is an interactive update
            expirationTime = computeInteractiveExpiration();
          } else {
            // This is an async update
            expirationTime = computeAsyncExpiration();
          }
        } else {
          // This is a sync update
          expirationTime = Sync;
        }
      }
      if (isBatchingInteractiveUpdates) {
        // This is an interactive update. Keep track of the lowest pending
        // interactive expiration time. This allows us to synchronously flush
        // all interactive updates when needed.
        if (
          lowestPendingInteractiveExpirationTime === NoWork ||
          expirationTime > lowestPendingInteractiveExpirationTime
        ) {
          lowestPendingInteractiveExpirationTime = expirationTime;
        }
      }
      return expirationTime;
    }
  
    function scheduleWork(fiber, expirationTime) {
      return scheduleWorkImpl(fiber, expirationTime, false);
    }
  
    function checkRootNeedsClearing(root, fiber, expirationTime) {
      if (
        !isWorking &&
        root === nextRoot &&
        expirationTime < nextRenderExpirationTime
      ) {
        // Restart the root from the top.
        if (nextUnitOfWork !== null) {
          // This is an interruption. (Used for performance tracking.)
          interruptedBy = fiber;
        }
        nextRoot = null;
        nextUnitOfWork = null;
        nextRenderExpirationTime = NoWork;
      }
    }
  
    function scheduleWorkImpl(fiber, expirationTime, isErrorRecovery) {
      recordScheduleUpdate();
  
      {
        if (!isErrorRecovery && fiber.tag === ClassComponent) {
          var instance = fiber.stateNode;
          warnAboutInvalidUpdates(instance);
        }
      }
  
      var node = fiber;
      while (node !== null) {
        // Walk the parent path to the root and update each node's
        // expiration time.
        if (
          node.expirationTime === NoWork ||
          node.expirationTime > expirationTime
        ) {
          node.expirationTime = expirationTime;
        }
        if (node.alternate !== null) {
          if (
            node.alternate.expirationTime === NoWork ||
            node.alternate.expirationTime > expirationTime
          ) {
            node.alternate.expirationTime = expirationTime;
          }
        }
        if (node["return"] === null) {
          if (node.tag === HostRoot) {
            var root = node.stateNode;
  
            checkRootNeedsClearing(root, fiber, expirationTime);
            requestWork(root, expirationTime);
            checkRootNeedsClearing(root, fiber, expirationTime);
          } else {
            {
              if (!isErrorRecovery && fiber.tag === ClassComponent) {
                warnAboutUpdateOnUnmounted(fiber);
              }
            }
            return;
          }
        }
        node = node["return"];
      }
    }
  
    function scheduleErrorRecovery(fiber) {
      scheduleWorkImpl(fiber, Sync, true);
    }
  
    function recalculateCurrentTime() {
      // Subtract initial time so it fits inside 32bits
      var ms = now() - startTime;
      mostRecentCurrentTime = msToExpirationTime(ms);
      return mostRecentCurrentTime;
    }
  
    function deferredUpdates(fn) {
      var previousExpirationContext = expirationContext;
      expirationContext = computeAsyncExpiration();
      try {
        return fn();
      } finally {
        expirationContext = previousExpirationContext;
      }
    }
  
    function syncUpdates(fn, a, b, c, d) {
      var previousExpirationContext = expirationContext;
      expirationContext = Sync;
      try {
        return fn(a, b, c, d);
      } finally {
        expirationContext = previousExpirationContext;
      }
    }
  
    // 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 = -1;
    var isRendering = false;
    var nextFlushedRoot = null;
    var nextFlushedExpirationTime = NoWork;
    var lowestPendingInteractiveExpirationTime = NoWork;
    var deadlineDidExpire = false;
    var hasUnhandledError = false;
    var unhandledError = null;
    var deadline = null;
  
    var isBatchingUpdates = false;
    var isUnbatchingUpdates = false;
    var isBatchingInteractiveUpdates = false;
  
    var completedBatches = null;
  
    // Use these to prevent an infinite loop of nested updates
    var NESTED_UPDATE_LIMIT = 1000;
    var nestedUpdateCount = 0;
  
    var timeHeuristicForUnitOfWork = 1;
  
    function scheduleCallbackWithExpiration(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 {
          // Existing callback has insufficient timeout. Cancel and schedule a
          // new one.
          cancelDeferredCallback(callbackID);
        }
        // The request callback timer is already running. Don't start a new one.
      } else {
        startRequestCallbackTimer();
      }
  
      // Compute a timeout for the given expiration time.
      var currentMs = now() - startTime;
      var expirationMs = expirationTimeToMs(expirationTime);
      var timeout = expirationMs - currentMs;
  
      callbackExpirationTime = expirationTime;
      callbackID = scheduleDeferredCallback(performAsyncWork, {
        timeout: timeout
      });
    }
  
    // 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) {
      if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
        invariant(
          false,
          "Maximum update depth exceeded. This can happen when a " +
            "component repeatedly calls setState inside componentWillUpdate or " +
            "componentDidUpdate. React limits the number of nested updates to " +
            "prevent infinite loops."
        );
      }
  
      // 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.remainingExpirationTime = 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.remainingExpirationTime;
        if (
          remainingExpirationTime === NoWork ||
          expirationTime < remainingExpirationTime
        ) {
          // Update the priority.
          root.remainingExpirationTime = expirationTime;
        }
      }
  
      if (isRendering) {
        // Prevent reentrancy. Remaining work will be scheduled at the end of
        // the currently rendering batch.
        return;
      }
  
      if (isBatchingUpdates) {
        if (isUnbatchingUpdates) {
          // Flush work at the end of the batch.
          // ...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 {
        scheduleCallbackWithExpiration(expirationTime);
      }
    }
  
    function findHighestPriorityRoot() {
      var highestPriorityWork = NoWork;
      var highestPriorityRoot = null;
  
      if (lastScheduledRoot !== null) {
        var previousScheduledRoot = lastScheduledRoot;
        var root = firstScheduledRoot;
        while (root !== null) {
          var remainingExpirationTime = root.remainingExpirationTime;
          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.
            invariant(
              previousScheduledRoot !== null && lastScheduledRoot !== null,
              "Should have a previous and last root. This error is likely " +
                "caused by a bug in React. Please file an issue."
            );
            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 (
              highestPriorityWork === NoWork ||
              remainingExpirationTime < highestPriorityWork
            ) {
              // Update the priority, if it's higher
              highestPriorityWork = remainingExpirationTime;
              highestPriorityRoot = root;
            }
            if (root === lastScheduledRoot) {
              break;
            }
            previousScheduledRoot = root;
            root = root.nextScheduledRoot;
          }
        }
      }
  
      // 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.
      var previousFlushedRoot = nextFlushedRoot;
      if (
        previousFlushedRoot !== null &&
        previousFlushedRoot === highestPriorityRoot
      ) {
        nestedUpdateCount++;
      } else {
        // Reset whenever we switch roots.
        nestedUpdateCount = 0;
      }
      nextFlushedRoot = highestPriorityRoot;
      nextFlushedExpirationTime = highestPriorityWork;
    }
  
    function performAsyncWork(dl) {
      performWork(NoWork, true, dl);
    }
  
    function performSyncWork() {
      performWork(Sync, false, null);
    }
  
    function performWork(minExpirationTime, isAsync, dl) {
      deadline = dl;
  
      // Keep working on roots until there's no more work, or until the we reach
      // the deadline.
      findHighestPriorityRoot();
  
      if (enableUserTimingAPI && deadline !== null) {
        var didExpire = nextFlushedExpirationTime < recalculateCurrentTime();
        stopRequestCallbackTimer(didExpire);
      }
  
      if (isAsync) {
        while (
          nextFlushedRoot !== null &&
          nextFlushedExpirationTime !== NoWork &&
          (minExpirationTime === NoWork ||
            minExpirationTime >= nextFlushedExpirationTime) &&
          (!deadlineDidExpire ||
            recalculateCurrentTime() >= nextFlushedExpirationTime)
        ) {
          performWorkOnRoot(
            nextFlushedRoot,
            nextFlushedExpirationTime,
            !deadlineDidExpire
          );
          findHighestPriorityRoot();
        }
      } else {
        while (
          nextFlushedRoot !== null &&
          nextFlushedExpirationTime !== NoWork &&
          (minExpirationTime === 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 (deadline !== null) {
        callbackExpirationTime = NoWork;
        callbackID = -1;
      }
      // If there's work left over, schedule a new callback.
      if (nextFlushedExpirationTime !== NoWork) {
        scheduleCallbackWithExpiration(nextFlushedExpirationTime);
      }
  
      // Clean-up.
      deadline = null;
      deadlineDidExpire = false;
      nestedUpdateCount = 0;
  
      finishRendering();
    }
  
    function flushRoot(root, expirationTime) {
      invariant(
        !isRendering,
        "work.commit(): Cannot commit while already rendering. This likely " +
          "means you attempted to commit from inside a lifecycle method."
      );
      // 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.
      performWorkOnRoot(root, expirationTime, false);
      finishRendering();
    }
  
    function finishRendering() {
      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 _error4 = unhandledError;
        unhandledError = null;
        hasUnhandledError = false;
        throw _error4;
      }
    }
  
    function performWorkOnRoot(root, expirationTime, isAsync) {
      invariant(
        !isRendering,
        "performWorkOnRoot was called recursively. This error is likely caused " +
          "by a bug in React. Please file an issue."
      );
  
      isRendering = true;
  
      // Check if this is async work or sync/expired work.
      if (!isAsync) {
        // Flush sync 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;
          finishedWork = renderRoot(root, expirationTime, false);
          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;
          _finishedWork = renderRoot(root, expirationTime, true);
          if (_finishedWork !== null) {
            // We've completed the root. Check the deadline one more time
            // before committing.
            if (!shouldYield()) {
              // 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.remainingExpirationTime = NoWork;
          return;
        }
      }
  
      // Commit the root.
      root.finishedWork = null;
      root.remainingExpirationTime = commitRoot(finishedWork);
    }
  
    // When working on async work, the reconciler asks the renderer if it should
    // yield execution. For DOM, we implement this with requestIdleCallback.
    function shouldYield() {
      if (deadline === null) {
        return false;
      }
      if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
        // Disregard deadline.didTimeout. Only expired work should be flushed
        // during a timeout. This path is only hit for non-expired work.
        return false;
      }
      deadlineDidExpire = true;
      return true;
    }
  
    // TODO: Not happy about this hook. Conceptually, renderRoot should return a
    // tuple of (isReadyForCommit, didError, error)
    function onUncaughtError(error) {
      invariant(
        nextFlushedRoot !== null,
        "Should be working on a root. This error is likely caused by a bug in " +
          "React. Please file an issue."
      );
      // Unschedule this root so we don't work on it again until there's
      // another update.
      nextFlushedRoot.remainingExpirationTime = NoWork;
      if (!hasUnhandledError) {
        hasUnhandledError = true;
        unhandledError = error;
      }
    }
  
    // TODO: Batching should be implemented at the renderer level, not inside
    // the reconciler.
    function batchedUpdates(fn, a) {
      var previousIsBatchingUpdates = isBatchingUpdates;
      isBatchingUpdates = true;
      try {
        return fn(a);
      } finally {
        isBatchingUpdates = previousIsBatchingUpdates;
        if (!isBatchingUpdates && !isRendering) {
          performSyncWork();
        }
      }
    }
  
    // TODO: Batching should be implemented at the renderer level, not 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) {
      invariant(
        !isRendering,
        "flushSync was called from inside a lifecycle method. It cannot be " +
          "called when React is already rendering."
      );
      var previousIsBatchingUpdates = isBatchingUpdates;
      isBatchingUpdates = true;
      try {
        return syncUpdates(fn, a);
      } finally {
        isBatchingUpdates = previousIsBatchingUpdates;
        performSyncWork();
      }
    }
  
    function interactiveUpdates(fn, a, b) {
      if (isBatchingInteractiveUpdates) {
        return 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 &&
        lowestPendingInteractiveExpirationTime !== NoWork
      ) {
        // Synchronously flush pending interactive updates.
        performWork(lowestPendingInteractiveExpirationTime, false, null);
        lowestPendingInteractiveExpirationTime = NoWork;
      }
      var previousIsBatchingInteractiveUpdates = isBatchingInteractiveUpdates;
      var previousIsBatchingUpdates = isBatchingUpdates;
      isBatchingInteractiveUpdates = true;
      isBatchingUpdates = true;
      try {
        return fn(a, b);
      } finally {
        isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates;
        isBatchingUpdates = previousIsBatchingUpdates;
        if (!isBatchingUpdates && !isRendering) {
          performSyncWork();
        }
      }
    }
  
    function flushInteractiveUpdates() {
      if (!isRendering && lowestPendingInteractiveExpirationTime !== NoWork) {
        // Synchronously flush pending interactive updates.
        performWork(lowestPendingInteractiveExpirationTime, false, null);
        lowestPendingInteractiveExpirationTime = NoWork;
      }
    }
  
    function flushControlled(fn) {
      var previousIsBatchingUpdates = isBatchingUpdates;
      isBatchingUpdates = true;
      try {
        syncUpdates(fn);
      } finally {
        isBatchingUpdates = previousIsBatchingUpdates;
        if (!isBatchingUpdates && !isRendering) {
          performWork(Sync, false, null);
        }
      }
    }
  
    return {
      computeExpirationForFiber: computeExpirationForFiber,
      scheduleWork: scheduleWork,
      requestWork: requestWork,
      flushRoot: flushRoot,
      batchedUpdates: batchedUpdates,
      unbatchedUpdates: unbatchedUpdates,
      flushSync: flushSync,
      flushControlled: flushControlled,
      deferredUpdates: deferredUpdates,
      syncUpdates: syncUpdates,
      interactiveUpdates: interactiveUpdates,
      flushInteractiveUpdates: flushInteractiveUpdates,
      computeUniqueAsyncExpiration: computeUniqueAsyncExpiration
    };
  };
  
  var didWarnAboutNestedUpdates = void 0;
  
  {
    didWarnAboutNestedUpdates = false;
  }
  
  // 0 is PROD, 1 is DEV.
  // Might add PROFILE later.
  
  function getContextForSubtree(parentComponent) {
    if (!parentComponent) {
      return emptyObject;
    }
  
    var fiber = get(parentComponent);
    var parentContext = findCurrentUnmaskedContext(fiber);
    return isContextProvider(fiber)
      ? processChildContext(fiber, parentContext)
      : parentContext;
  }
  
  var ReactFiberReconciler$1 = function(config) {
    var getPublicInstance = config.getPublicInstance;
  
    var _ReactFiberScheduler = ReactFiberScheduler(config),
      computeUniqueAsyncExpiration =
        _ReactFiberScheduler.computeUniqueAsyncExpiration,
      computeExpirationForFiber = _ReactFiberScheduler.computeExpirationForFiber,
      scheduleWork = _ReactFiberScheduler.scheduleWork,
      requestWork = _ReactFiberScheduler.requestWork,
      flushRoot = _ReactFiberScheduler.flushRoot,
      batchedUpdates = _ReactFiberScheduler.batchedUpdates,
      unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates,
      flushSync = _ReactFiberScheduler.flushSync,
      flushControlled = _ReactFiberScheduler.flushControlled,
      deferredUpdates = _ReactFiberScheduler.deferredUpdates,
      syncUpdates = _ReactFiberScheduler.syncUpdates,
      interactiveUpdates = _ReactFiberScheduler.interactiveUpdates,
      flushInteractiveUpdates = _ReactFiberScheduler.flushInteractiveUpdates;
  
    function scheduleRootUpdate(current, element, expirationTime, callback) {
      {
        if (
          ReactDebugCurrentFiber.phase === "render" &&
          ReactDebugCurrentFiber.current !== null &&
          !didWarnAboutNestedUpdates
        ) {
          didWarnAboutNestedUpdates = true;
          warning(
            false,
            "Render methods should be a pure function of props and state; " +
              "triggering nested component updates from render is not allowed. " +
              "If necessary, trigger nested updates in componentDidUpdate.\n\n" +
              "Check the render method of %s.",
            getComponentName(ReactDebugCurrentFiber.current) || "Unknown"
          );
        }
      }
  
      callback = callback === undefined ? null : callback;
      {
        warning(
          callback === null || typeof callback === "function",
          "render(...): Expected the last optional `callback` argument to be a " +
            "function. Instead received: %s.",
          callback
        );
      }
  
      var update = {
        expirationTime: expirationTime,
        partialState: { element: element },
        callback: callback,
        isReplace: false,
        isForced: false,
        next: null
      };
      insertUpdateIntoFiber(current, update);
      scheduleWork(current, 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 = container.current;
  
      {
        if (ReactFiberInstrumentation_1.debugTool) {
          if (current.alternate === null) {
            ReactFiberInstrumentation_1.debugTool.onMountContainer(container);
          } else if (element === null) {
            ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container);
          } else {
            ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container);
          }
        }
      }
  
      var context = getContextForSubtree(parentComponent);
      if (container.context === null) {
        container.context = context;
      } else {
        container.pendingContext = context;
      }
  
      return scheduleRootUpdate(current, element, expirationTime, callback);
    }
  
    function findHostInstance(fiber) {
      var hostFiber = findCurrentHostFiber(fiber);
      if (hostFiber === null) {
        return null;
      }
      return hostFiber.stateNode;
    }
  
    return {
      createContainer: function(containerInfo, isAsync, hydrate) {
        return createFiberRoot(containerInfo, isAsync, hydrate);
      },
      updateContainer: function(element, container, parentComponent, callback) {
        var current = container.current;
        var expirationTime = computeExpirationForFiber(current);
        return updateContainerAtExpirationTime(
          element,
          container,
          parentComponent,
          expirationTime,
          callback
        );
      },
  
      updateContainerAtExpirationTime: updateContainerAtExpirationTime,
  
      flushRoot: flushRoot,
  
      requestWork: requestWork,
  
      computeUniqueAsyncExpiration: computeUniqueAsyncExpiration,
  
      batchedUpdates: batchedUpdates,
  
      unbatchedUpdates: unbatchedUpdates,
  
      deferredUpdates: deferredUpdates,
  
      syncUpdates: syncUpdates,
  
      interactiveUpdates: interactiveUpdates,
  
      flushInteractiveUpdates: flushInteractiveUpdates,
  
      flushControlled: flushControlled,
  
      flushSync: flushSync,
  
      getPublicRootInstance: function(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;
        }
      },
  
      findHostInstance: findHostInstance,
  
      findHostInstanceWithNoPortals: function(fiber) {
        var hostFiber = findCurrentHostFiberWithNoPortals(fiber);
        if (hostFiber === null) {
          return null;
        }
        return hostFiber.stateNode;
      },
      injectIntoDevTools: function(devToolsConfig) {
        var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance;
  
        return injectInternals(
          Object.assign({}, devToolsConfig, {
            findHostInstanceByFiber: function(fiber) {
              return findHostInstance(fiber);
            },
            findFiberByHostInstance: function(instance) {
              if (!findFiberByHostInstance) {
                // Might not be implemented by the renderer.
                return null;
              }
              return findFiberByHostInstance(instance);
            }
          })
        );
      }
    };
  };
  
  var ReactFiberReconciler$2 = Object.freeze({
    default: ReactFiberReconciler$1
  });
  
  var ReactFiberReconciler$3 =
    (ReactFiberReconciler$2 && ReactFiberReconciler$1) || ReactFiberReconciler$2;
  
  // TODO: bundle Flow types with the package.
  
  // TODO: decide on the top-level export form.
  // This is hacky but makes it work with both Rollup and Jest.
  var reactReconciler = ReactFiberReconciler$3["default"]
    ? ReactFiberReconciler$3["default"]
    : ReactFiberReconciler$3;
  
  function _classCallCheck$2(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }
  
  // Modules provided by RN:
  /**
   * This is used for refs on host components.
   */
  
  var ReactFabricHostComponent = (function() {
    function ReactFabricHostComponent(tag, viewConfig, props) {
      _classCallCheck$2(this, ReactFabricHostComponent);
  
      this._nativeTag = tag;
      this.viewConfig = viewConfig;
      this.currentProps = props;
    }
  
    ReactFabricHostComponent.prototype.blur = function blur() {
      TextInputState.blurTextInput(this._nativeTag);
    };
  
    ReactFabricHostComponent.prototype.focus = function focus() {
      TextInputState.focusTextInput(this._nativeTag);
    };
  
    ReactFabricHostComponent.prototype.measure = function measure(callback) {
      UIManager.measure(this._nativeTag, mountSafeCallback(this, callback));
    };
  
    ReactFabricHostComponent.prototype.measureInWindow = function measureInWindow(
      callback
    ) {
      UIManager.measureInWindow(
        this._nativeTag,
        mountSafeCallback(this, callback)
      );
    };
  
    ReactFabricHostComponent.prototype.measureLayout = function measureLayout(
      relativeToNativeNode,
      onSuccess,
      onFail /* currently unused */
    ) {
      UIManager.measureLayout(
        this._nativeTag,
        relativeToNativeNode,
        mountSafeCallback(this, onFail),
        mountSafeCallback(this, onSuccess)
      );
    };
  
    ReactFabricHostComponent.prototype.setNativeProps = function setNativeProps(
      nativeProps
    ) {
      {
        warnForStyleProps(nativeProps, this.viewConfig.validAttributes);
      }
  
      var updatePayload = create(nativeProps, this.viewConfig.validAttributes);
  
      // Avoid the overhead of bridge calls if there's no update.
      // This is an expensive no-op for Android, and causes an unnecessary
      // view invalidation for certain components (eg RCTTextInput) on iOS.
      if (updatePayload != null) {
        UIManager.updateView(
          this._nativeTag,
          this.viewConfig.uiViewClassName,
          updatePayload
        );
      }
    };
  
    return ReactFabricHostComponent;
  })();
  
  var ReactFabricRenderer = reactReconciler({
    appendInitialChild: function(parentInstance, child) {
      FabricUIManager.appendChild(parentInstance.node, child.node);
    },
    createInstance: function(
      type,
      props,
      rootContainerInstance,
      hostContext,
      internalInstanceHandle
    ) {
      var tag = ReactNativeTagHandles.allocateTag();
      var viewConfig = get$1(type);
  
      {
        for (var key in viewConfig.validAttributes) {
          if (props.hasOwnProperty(key)) {
            deepFreezeAndThrowOnMutationInDev(props[key]);
          }
        }
      }
  
      var updatePayload = create(props, viewConfig.validAttributes);
  
      var node = FabricUIManager.createNode(
        tag, // reactTag
        viewConfig.uiViewClassName, // viewName
        rootContainerInstance, // rootTag
        updatePayload, // props
        internalInstanceHandle
      );
  
      var component = new ReactFabricHostComponent(tag, viewConfig, props);
  
      return {
        node: node,
        canonical: component
      };
    },
    createTextInstance: function(
      text,
      rootContainerInstance,
      hostContext,
      internalInstanceHandle
    ) {
      var tag = ReactNativeTagHandles.allocateTag();
  
      var node = FabricUIManager.createNode(
        tag, // reactTag
        "RCTRawText", // viewName
        rootContainerInstance, // rootTag
        { text: text }, // props
        internalInstanceHandle
      );
  
      return {
        node: node
      };
    },
    finalizeInitialChildren: function(
      parentInstance,
      type,
      props,
      rootContainerInstance
    ) {
      return false;
    },
    getRootHostContext: function() {
      return emptyObject;
    },
    getChildHostContext: function() {
      return emptyObject;
    },
    getPublicInstance: function(instance) {
      return instance.canonical;
    },
  
    now: now,
  
    prepareForCommit: function() {
      // Noop
    },
    prepareUpdate: function(
      instance,
      type,
      oldProps,
      newProps,
      rootContainerInstance,
      hostContext
    ) {
      var viewConfig = instance.canonical.viewConfig;
      var updatePayload = diff(oldProps, newProps, viewConfig.validAttributes);
      // TODO: If the event handlers have changed, we need to update the current props
      // in the commit phase but there is no host config hook to do it yet.
      return updatePayload;
    },
    resetAfterCommit: function() {
      // Noop
    },
  
    scheduleDeferredCallback: scheduleDeferredCallback,
    cancelDeferredCallback: cancelDeferredCallback,
  
    shouldDeprioritizeSubtree: function(type, props) {
      return false;
    },
    shouldSetTextContent: function(type, props) {
      // TODO (bvaughn) Revisit this decision.
      // Always returning false simplifies the createInstance() implementation,
      // But creates an additional child Fiber for raw text children.
      // No additional native views are created though.
      // It's not clear to me which is better so I'm deferring for now.
      // More context @ github.com/facebook/react/pull/8560#discussion_r92111303
      return false;
    },
  
    persistence: {
      cloneInstance: function(
        instance,
        updatePayload,
        type,
        oldProps,
        newProps,
        internalInstanceHandle,
        keepChildren,
        recyclableInstance
      ) {
        var node = instance.node;
        var clone = void 0;
        if (keepChildren) {
          if (updatePayload !== null) {
            clone = FabricUIManager.cloneNodeWithNewProps(node, updatePayload);
          } else {
            clone = FabricUIManager.cloneNode(node);
          }
        } else {
          if (updatePayload !== null) {
            clone = FabricUIManager.cloneNodeWithNewChildrenAndProps(
              node,
              updatePayload
            );
          } else {
            clone = FabricUIManager.cloneNodeWithNewChildren(node);
          }
        }
        return {
          node: clone,
          canonical: instance.canonical
        };
      },
      createContainerChildSet: function(container) {
        return FabricUIManager.createChildSet(container);
      },
      appendChildToContainerChildSet: function(childSet, child) {
        FabricUIManager.appendChildToSet(childSet, child.node);
      },
      finalizeContainerChildren: function(container, newChildren) {
        FabricUIManager.completeRoot(container, newChildren);
      },
      replaceContainerChildren: function(container, newChildren) {}
    }
  });
  
  // Module provided by RN:
  var getInspectorDataForViewTag = void 0;
  
  {
    var traverseOwnerTreeUp = function(hierarchy, instance) {
      if (instance) {
        hierarchy.unshift(instance);
        traverseOwnerTreeUp(hierarchy, instance._debugOwner);
      }
    };
  
    var getOwnerHierarchy = function(instance) {
      var hierarchy = [];
      traverseOwnerTreeUp(hierarchy, instance);
      return hierarchy;
    };
  
    var lastNonHostInstance = function(hierarchy) {
      for (var i = hierarchy.length - 1; i > 1; i--) {
        var instance = hierarchy[i];
  
        if (instance.tag !== HostComponent) {
          return instance;
        }
      }
      return hierarchy[0];
    };
  
    var getHostProps = function(fiber) {
      var host = findCurrentHostFiber(fiber);
      if (host) {
        return host.memoizedProps || emptyObject;
      }
      return emptyObject;
    };
  
    var getHostNode = function(fiber, findNodeHandle) {
      var hostNode = void 0;
      // look for children first for the hostNode
      // as composite fibers do not have a hostNode
      while (fiber) {
        if (fiber.stateNode !== null && fiber.tag === HostComponent) {
          hostNode = findNodeHandle(fiber.stateNode);
        }
        if (hostNode) {
          return hostNode;
        }
        fiber = fiber.child;
      }
      return null;
    };
  
    var createHierarchy = function(fiberHierarchy) {
      return fiberHierarchy.map(function(fiber) {
        return {
          name: getComponentName(fiber),
          getInspectorData: function(findNodeHandle) {
            return {
              measure: function(callback) {
                return UIManager.measure(
                  getHostNode(fiber, findNodeHandle),
                  callback
                );
              },
              props: getHostProps(fiber),
              source: fiber._debugSource
            };
          }
        };
      });
    };
  
    getInspectorDataForViewTag = function(viewTag) {
      var closestInstance = getInstanceFromTag(viewTag);
  
      // Handle case where user clicks outside of ReactNative
      if (!closestInstance) {
        return {
          hierarchy: [],
          props: emptyObject,
          selection: null,
          source: null
        };
      }
  
      var fiber = findCurrentFiberUsingSlowPath(closestInstance);
      var fiberHierarchy = getOwnerHierarchy(fiber);
      var instance = lastNonHostInstance(fiberHierarchy);
      var hierarchy = createHierarchy(fiberHierarchy);
      var props = getHostProps(instance);
      var source = instance._debugSource;
      var selection = fiberHierarchy.indexOf(instance);
  
      return {
        hierarchy: hierarchy,
        props: props,
        selection: selection,
        source: source
      };
    };
  }
  
  /**
   * Creates a renderable ReactNative host component.
   * Use this method for view configs that are loaded from UIManager.
   * Use createReactNativeComponentClass() for view configs defined within JavaScript.
   *
   * @param {string} config iOS View configuration.
   * @private
   */
  var createReactNativeComponentClass = function(name, callback) {
    return register(name, callback);
  };
  
  // Module provided by RN:
  /**
   * Capture an image of the screen, window or an individual view. The image
   * will be stored in a temporary file that will only exist for as long as the
   * app is running.
   *
   * The `view` argument can be the literal string `window` if you want to
   * capture the entire window, or it can be a reference to a specific
   * React Native component.
   *
   * The `options` argument may include:
   * - width/height (number) - the width and height of the image to capture.
   * - format (string) - either 'png' or 'jpeg'. Defaults to 'png'.
   * - quality (number) - the quality when using jpeg. 0.0 - 1.0 (default).
   *
   * Returns a Promise.
   * @platform ios
   */
  function takeSnapshot(view, options) {
    if (typeof view !== "number" && view !== "window") {
      view = findNumericNodeHandleFiber(view) || "window";
    }
  
    // Call the hidden '__takeSnapshot' method; the main one throws an error to
    // prevent accidental backwards-incompatible usage.
    return UIManager.__takeSnapshot(view, options);
  }
  
  injectFindHostInstanceFabric(ReactFabricRenderer.findHostInstance);
  
  injection$2.injectRenderer(ReactFabricRenderer);
  
  var roots = new Map();
  
  var ReactFabric = {
    NativeComponent: ReactNativeComponent,
  
    findNodeHandle: findNumericNodeHandleFiber,
  
    render: function(element, containerTag, callback) {
      var root = roots.get(containerTag);
  
      if (!root) {
        // TODO (bvaughn): If we decide to keep the wrapper component,
        // We could create a wrapper for containerTag as well to reduce special casing.
        root = ReactFabricRenderer.createContainer(containerTag, false, false);
        roots.set(containerTag, root);
      }
      ReactFabricRenderer.updateContainer(element, root, null, callback);
  
      return ReactFabricRenderer.getPublicRootInstance(root);
    },
    unmountComponentAtNode: function(containerTag) {
      var root = roots.get(containerTag);
      if (root) {
        // TODO: Is it safe to reset this now or should I wait since this unmount could be deferred?
        ReactFabricRenderer.updateContainer(null, root, null, function() {
          roots["delete"](containerTag);
        });
      }
    },
    unmountComponentAtNodeAndRemoveContainer: function(containerTag) {
      ReactFabric.unmountComponentAtNode(containerTag);
    },
    createPortal: function(children, containerTag) {
      var key =
        arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
  
      return createPortal(children, containerTag, null, key);
    },
  
    unstable_batchedUpdates: batchedUpdates,
  
    flushSync: ReactFabricRenderer.flushSync,
  
    __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
      // Used as a mixin in many createClass-based components
      NativeMethodsMixin: NativeMethodsMixin,
      // Used by react-native-github/Libraries/ components
      ReactNativeBridgeEventPlugin: ReactNativeBridgeEventPlugin, // requireNativeComponent
      ReactGlobalSharedState: ReactGlobalSharedState, // Systrace
      ReactNativeComponentTree: ReactNativeComponentTree, // InspectorUtils, ScrollResponder
      ReactNativePropRegistry: ReactNativePropRegistry, // flattenStyle, Stylesheet
      TouchHistoryMath: TouchHistoryMath, // PanResponder
      createReactNativeComponentClass: createReactNativeComponentClass, // RCTText, RCTView, ReactNativeART
      takeSnapshot: takeSnapshot
    }
  };
  
  {
    // $FlowFixMe
    Object.assign(
      ReactFabric.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
      {
        // TODO: none of these work since Fiber. Remove these dependencies.
        // Used by RCTRenderingPerf, Systrace:
        ReactDebugTool: {
          addHook: function() {},
          removeHook: function() {}
        },
        // Used by ReactPerfStallHandler, RCTRenderingPerf:
        ReactPerf: {
          start: function() {},
          stop: function() {},
          printInclusive: function() {},
          printWasted: function() {}
        }
      }
    );
  }
  
  ReactFabricRenderer.injectIntoDevTools({
    findFiberByHostInstance: getInstanceFromTag,
    getInspectorDataForViewTag: getInspectorDataForViewTag,
    bundleType: 1,
    version: ReactVersion,
    rendererPackageName: "react-native-renderer"
  });
  
  var ReactFabric$2 = Object.freeze({
    default: ReactFabric
  });
  
  var ReactFabric$3 = (ReactFabric$2 && ReactFabric) || ReactFabric$2;
  
  // TODO: decide on the top-level export form.
  // This is hacky but makes it work with both Rollup and Jest.
  var fabric = ReactFabric$3["default"]
    ? ReactFabric$3["default"]
    : ReactFabric$3;
  
  module.exports = fabric;
  
    })();
  }
  