aboutsummaryrefslogtreecommitdiff
path: root/node_modules/react-dom/umd/react-dom.development.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-12-10 21:51:33 +0100
committerFlorian Dold <florian.dold@gmail.com>2017-12-10 21:51:33 +0100
commit0469abd4a9c9270a1fdc962969e36e63699af8b4 (patch)
treef9864d4a4148621378958794cbbfdc2393733283 /node_modules/react-dom/umd/react-dom.development.js
parent6947e79bbc258f7bc96af424ddb71a511f0c15a3 (diff)
upgrade dependencies
Diffstat (limited to 'node_modules/react-dom/umd/react-dom.development.js')
-rw-r--r--node_modules/react-dom/umd/react-dom.development.js23049
1 files changed, 10345 insertions, 12704 deletions
diff --git a/node_modules/react-dom/umd/react-dom.development.js b/node_modules/react-dom/umd/react-dom.development.js
index eea5c11c5..371c3816e 100644
--- a/node_modules/react-dom/umd/react-dom.development.js
+++ b/node_modules/react-dom/umd/react-dom.development.js
@@ -1,4 +1,4 @@
-/** @license React v16.0.0
+/** @license React v16.2.0
* react-dom.development.js
*
* Copyright (c) 2013-present, Facebook, Inc.
@@ -7,20 +7,19 @@
* LICENSE file in the root directory of this source tree.
*/
+'use strict';
+
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
typeof define === 'function' && define.amd ? define(['react'], factory) :
(global.ReactDOM = factory(global.React));
-}(this, (function (require$$0) { 'use strict';
+}(this, (function (React) { 'use strict';
/**
- * 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.
- *
- * @providesModule reactProdInvariant
- *
+ * WARNING: DO NOT manually require this module.
+ * This is a replacement for `invariant(...)` used by the error code system
+ * and will _only_ be required by the corresponding babel pass.
+ * It always throws.
*/
/**
@@ -31,6 +30,8 @@
*
*/
+
+
/**
* Use invariant() to assert state which your program assumes to be true.
*
@@ -75,110 +76,578 @@ function invariant(condition, format, a, b, c, d, e, f) {
var invariant_1 = invariant;
-/**
- * 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.
- *
- * @providesModule checkReact
- *
- */
+!React ? invariant_1(false, 'ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.') : void 0;
+// These attributes should be all lowercase to allow for
+// case insensitive checks
+var RESERVED_PROPS = {
+ children: true,
+ dangerouslySetInnerHTML: true,
+ defaultValue: true,
+ defaultChecked: true,
+ innerHTML: true,
+ suppressContentEditableWarning: true,
+ suppressHydrationWarning: true,
+ style: true
+};
+function checkMask(value, bitmask) {
+ return (value & bitmask) === bitmask;
+}
+var DOMPropertyInjection = {
+ /**
+ * Mapping from normalized, camelcased property names to a configuration that
+ * specifies how the associated DOM property should be accessed or rendered.
+ */
+ MUST_USE_PROPERTY: 0x1,
+ HAS_BOOLEAN_VALUE: 0x4,
+ HAS_NUMERIC_VALUE: 0x8,
+ HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,
+ HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,
+ HAS_STRING_BOOLEAN_VALUE: 0x40,
-!require$$0 ? invariant_1(false, 'ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.') : void 0;
+ /**
+ * Inject some specialized knowledge about the DOM. This takes a config object
+ * with the following properties:
+ *
+ * Properties: object mapping DOM property name to one of the
+ * DOMPropertyInjection constants or null. If your attribute isn't in here,
+ * it won't get written to the DOM.
+ *
+ * DOMAttributeNames: object mapping React attribute name to the DOM
+ * attribute name. Attribute names not specified use the **lowercase**
+ * normalized name.
+ *
+ * DOMAttributeNamespaces: object mapping React attribute name to the DOM
+ * attribute namespace URL. (Attribute names not specified use no namespace.)
+ *
+ * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.
+ * Property names not specified use the normalized name.
+ *
+ * DOMMutationMethods: Properties that require special mutation methods. If
+ * `value` is undefined, the mutation method should unset the property.
+ *
+ * @param {object} domPropertyConfig the config as described above.
+ */
+ injectDOMPropertyConfig: function (domPropertyConfig) {
+ var Injection = DOMPropertyInjection;
+ var Properties = domPropertyConfig.Properties || {};
+ var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {};
+ var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};
+ var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};
-/**
- * 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.
- *
- * @providesModule DOMNamespaces
- */
+ for (var propName in Properties) {
+ !!properties.hasOwnProperty(propName) ? invariant_1(false, "injectDOMPropertyConfig(...): You're trying to inject DOM property '%s' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.", propName) : void 0;
-var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
-var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
-var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
+ var lowerCased = propName.toLowerCase();
+ var propConfig = Properties[propName];
-var Namespaces = {
- html: HTML_NAMESPACE,
- mathml: MATH_NAMESPACE,
- svg: SVG_NAMESPACE
+ var propertyInfo = {
+ attributeName: lowerCased,
+ attributeNamespace: null,
+ propertyName: propName,
+ mutationMethod: null,
+
+ mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),
+ hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),
+ hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),
+ hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),
+ hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE),
+ hasStringBooleanValue: checkMask(propConfig, Injection.HAS_STRING_BOOLEAN_VALUE)
+ };
+ !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? invariant_1(false, "DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s", propName) : void 0;
+
+ if (DOMAttributeNames.hasOwnProperty(propName)) {
+ var attributeName = DOMAttributeNames[propName];
+
+ propertyInfo.attributeName = attributeName;
+ }
+
+ if (DOMAttributeNamespaces.hasOwnProperty(propName)) {
+ propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName];
+ }
+
+ if (DOMMutationMethods.hasOwnProperty(propName)) {
+ propertyInfo.mutationMethod = DOMMutationMethods[propName];
+ }
+
+ // Downcase references to whitelist properties to check for membership
+ // without case-sensitivity. This allows the whitelist to pick up
+ // `allowfullscreen`, which should be written using the property configuration
+ // for `allowFullscreen`
+ properties[propName] = propertyInfo;
+ }
+ }
};
-// Assumes there is no parent namespace.
-function getIntrinsicNamespace(type) {
- switch (type) {
- case 'svg':
- return SVG_NAMESPACE;
- case 'math':
- return MATH_NAMESPACE;
+/* eslint-disable max-len */
+var ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
+/* eslint-enable max-len */
+var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
+
+
+var ROOT_ATTRIBUTE_NAME = 'data-reactroot';
+
+/**
+ * Map from property "standard name" to an object with info about how to set
+ * the property in the DOM. Each object contains:
+ *
+ * attributeName:
+ * Used when rendering markup or with `*Attribute()`.
+ * attributeNamespace
+ * propertyName:
+ * Used on DOM node instances. (This includes properties that mutate due to
+ * external factors.)
+ * mutationMethod:
+ * If non-null, used instead of the property or `setAttribute()` after
+ * initial render.
+ * mustUseProperty:
+ * Whether the property must be accessed and mutated as an object property.
+ * hasBooleanValue:
+ * Whether the property should be removed when set to a falsey value.
+ * hasNumericValue:
+ * Whether the property must be numeric or parse as a numeric and should be
+ * removed when set to a falsey value.
+ * hasPositiveNumericValue:
+ * Whether the property must be positive numeric or parse as a positive
+ * numeric and should be removed when set to a falsey value.
+ * hasOverloadedBooleanValue:
+ * Whether the property can be used as a flag as well as with a value.
+ * Removed when strictly equal to false; present without a value when
+ * strictly equal to true; present with a value otherwise.
+ */
+var properties = {};
+
+/**
+ * Checks whether a property name is a writeable attribute.
+ * @method
+ */
+function shouldSetAttribute(name, value) {
+ if (isReservedProp(name)) {
+ return false;
+ }
+ if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) {
+ return false;
+ }
+ if (value === null) {
+ return true;
+ }
+ switch (typeof value) {
+ case 'boolean':
+ return shouldAttributeAcceptBooleanValue(name);
+ case 'undefined':
+ case 'number':
+ case 'string':
+ case 'object':
+ return true;
default:
- return HTML_NAMESPACE;
+ // function, symbol
+ return false;
}
}
-function getChildNamespace$1(parentNamespace, type) {
- if (parentNamespace == null || parentNamespace === HTML_NAMESPACE) {
- // No (or default) parent namespace: potential entry point.
- return getIntrinsicNamespace(type);
+function getPropertyInfo(name) {
+ return properties.hasOwnProperty(name) ? properties[name] : null;
+}
+
+function shouldAttributeAcceptBooleanValue(name) {
+ if (isReservedProp(name)) {
+ return true;
}
- if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') {
- // We're leaving SVG.
- return HTML_NAMESPACE;
+ var propertyInfo = getPropertyInfo(name);
+ if (propertyInfo) {
+ return propertyInfo.hasBooleanValue || propertyInfo.hasStringBooleanValue || propertyInfo.hasOverloadedBooleanValue;
}
- // By default, pass namespace below.
- return parentNamespace;
+ var prefix = name.toLowerCase().slice(0, 5);
+ return prefix === 'data-' || prefix === 'aria-';
}
-var Namespaces_1 = Namespaces;
-var getIntrinsicNamespace_1 = getIntrinsicNamespace;
-var getChildNamespace_1 = getChildNamespace$1;
+/**
+ * Checks to see if a property name is within the list of properties
+ * reserved for internal React operations. These properties should
+ * not be set on an HTML element.
+ *
+ * @private
+ * @param {string} name
+ * @return {boolean} If the name is within reserved props
+ */
+function isReservedProp(name) {
+ return RESERVED_PROPS.hasOwnProperty(name);
+}
+
+var injection = DOMPropertyInjection;
+
+var MUST_USE_PROPERTY = injection.MUST_USE_PROPERTY;
+var HAS_BOOLEAN_VALUE = injection.HAS_BOOLEAN_VALUE;
+var HAS_NUMERIC_VALUE = injection.HAS_NUMERIC_VALUE;
+var HAS_POSITIVE_NUMERIC_VALUE = injection.HAS_POSITIVE_NUMERIC_VALUE;
+var HAS_OVERLOADED_BOOLEAN_VALUE = injection.HAS_OVERLOADED_BOOLEAN_VALUE;
+var HAS_STRING_BOOLEAN_VALUE = injection.HAS_STRING_BOOLEAN_VALUE;
-var DOMNamespaces = {
- Namespaces: Namespaces_1,
- getIntrinsicNamespace: getIntrinsicNamespace_1,
- getChildNamespace: getChildNamespace_1
+var HTMLDOMPropertyConfig = {
+ // When adding attributes to this list, be sure to also add them to
+ // the `possibleStandardNames` module to ensure casing and incorrect
+ // name warnings.
+ Properties: {
+ allowFullScreen: HAS_BOOLEAN_VALUE,
+ // specifies target context for links with `preload` type
+ async: HAS_BOOLEAN_VALUE,
+ // Note: there is a special case that prevents it from being written to the DOM
+ // on the client side because the browsers are inconsistent. Instead we call focus().
+ autoFocus: HAS_BOOLEAN_VALUE,
+ autoPlay: HAS_BOOLEAN_VALUE,
+ capture: HAS_OVERLOADED_BOOLEAN_VALUE,
+ checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+ cols: HAS_POSITIVE_NUMERIC_VALUE,
+ contentEditable: HAS_STRING_BOOLEAN_VALUE,
+ controls: HAS_BOOLEAN_VALUE,
+ 'default': HAS_BOOLEAN_VALUE,
+ defer: HAS_BOOLEAN_VALUE,
+ disabled: HAS_BOOLEAN_VALUE,
+ download: HAS_OVERLOADED_BOOLEAN_VALUE,
+ draggable: HAS_STRING_BOOLEAN_VALUE,
+ formNoValidate: HAS_BOOLEAN_VALUE,
+ hidden: HAS_BOOLEAN_VALUE,
+ loop: HAS_BOOLEAN_VALUE,
+ // Caution; `option.selected` is not updated if `select.multiple` is
+ // disabled with `removeAttribute`.
+ multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+ muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+ noValidate: HAS_BOOLEAN_VALUE,
+ open: HAS_BOOLEAN_VALUE,
+ playsInline: HAS_BOOLEAN_VALUE,
+ readOnly: HAS_BOOLEAN_VALUE,
+ required: HAS_BOOLEAN_VALUE,
+ reversed: HAS_BOOLEAN_VALUE,
+ rows: HAS_POSITIVE_NUMERIC_VALUE,
+ rowSpan: HAS_NUMERIC_VALUE,
+ scoped: HAS_BOOLEAN_VALUE,
+ seamless: HAS_BOOLEAN_VALUE,
+ selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
+ size: HAS_POSITIVE_NUMERIC_VALUE,
+ start: HAS_NUMERIC_VALUE,
+ // support for projecting regular DOM Elements via V1 named slots ( shadow dom )
+ span: HAS_POSITIVE_NUMERIC_VALUE,
+ spellCheck: HAS_STRING_BOOLEAN_VALUE,
+ // Style must be explicitly set in the attribute list. React components
+ // expect a style object
+ style: 0,
+ // Keep it in the whitelist because it is case-sensitive for SVG.
+ tabIndex: 0,
+ // itemScope is for for Microdata support.
+ // See http://schema.org/docs/gs.html
+ itemScope: HAS_BOOLEAN_VALUE,
+ // These attributes must stay in the white-list because they have
+ // different attribute names (see DOMAttributeNames below)
+ acceptCharset: 0,
+ className: 0,
+ htmlFor: 0,
+ httpEquiv: 0,
+ // Attributes with mutation methods must be specified in the whitelist
+ // Set the string boolean flag to allow the behavior
+ value: HAS_STRING_BOOLEAN_VALUE
+ },
+ DOMAttributeNames: {
+ acceptCharset: 'accept-charset',
+ className: 'class',
+ htmlFor: 'for',
+ httpEquiv: 'http-equiv'
+ },
+ DOMMutationMethods: {
+ value: function (node, value) {
+ if (value == null) {
+ return node.removeAttribute('value');
+ }
+
+ // Number inputs get special treatment due to some edge cases in
+ // Chrome. Let everything else assign the value attribute as normal.
+ // https://github.com/facebook/react/issues/7253#issuecomment-236074326
+ if (node.type !== 'number' || node.hasAttribute('value') === false) {
+ node.setAttribute('value', '' + value);
+ } else if (node.validity && !node.validity.badInput && node.ownerDocument.activeElement !== node) {
+ // Don't assign an attribute if validation reports bad
+ // input. Chrome will clear the value. Additionally, don't
+ // operate on inputs that have focus, otherwise Chrome might
+ // strip off trailing decimal places and cause the user's
+ // cursor position to jump to the beginning of the input.
+ //
+ // In ReactDOMInput, we have an onBlur event that will trigger
+ // this function again when focus is lost.
+ node.setAttribute('value', '' + value);
+ }
+ }
+ }
+};
+
+var HAS_STRING_BOOLEAN_VALUE$1 = injection.HAS_STRING_BOOLEAN_VALUE;
+
+
+var NS = {
+ xlink: 'http://www.w3.org/1999/xlink',
+ xml: 'http://www.w3.org/XML/1998/namespace'
};
/**
- * Copyright (c) 2013-present, Facebook, Inc.
+ * This is a list of all SVG attributes that need special casing,
+ * namespacing, or boolean value assignment.
*
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
+ * When adding attributes to this list, be sure to also add them to
+ * the `possibleStandardNames` module to ensure casing and incorrect
+ * name warnings.
*
+ * SVG Attributes List:
+ * https://www.w3.org/TR/SVG/attindex.html
+ * SMIL Spec:
+ * https://www.w3.org/TR/smil
*/
+var ATTRS = ['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'x-height', 'xlink:actuate', 'xlink:arcrole', 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type', 'xml:base', 'xmlns:xlink', 'xml:lang', 'xml:space'];
-var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
+var SVGDOMPropertyConfig = {
+ Properties: {
+ autoReverse: HAS_STRING_BOOLEAN_VALUE$1,
+ externalResourcesRequired: HAS_STRING_BOOLEAN_VALUE$1,
+ preserveAlpha: HAS_STRING_BOOLEAN_VALUE$1
+ },
+ DOMAttributeNames: {
+ autoReverse: 'autoReverse',
+ externalResourcesRequired: 'externalResourcesRequired',
+ preserveAlpha: 'preserveAlpha'
+ },
+ DOMAttributeNamespaces: {
+ xlinkActuate: NS.xlink,
+ xlinkArcrole: NS.xlink,
+ xlinkHref: NS.xlink,
+ xlinkRole: NS.xlink,
+ xlinkShow: NS.xlink,
+ xlinkTitle: NS.xlink,
+ xlinkType: NS.xlink,
+ xmlBase: NS.xml,
+ xmlLang: NS.xml,
+ xmlSpace: NS.xml
+ }
+};
-/**
- * Simple, lightweight module assisting with the detection and context of
- * Worker. Helps avoid circular dependencies and allows code to reason about
- * whether or not they are in a Worker, even if they never include the main
- * `ReactWorker` dependency.
- */
-var ExecutionEnvironment = {
+var CAMELIZE = /[\-\:]([a-z])/g;
+var capitalize = function (token) {
+ return token[1].toUpperCase();
+};
- canUseDOM: canUseDOM,
+ATTRS.forEach(function (original) {
+ var reactName = original.replace(CAMELIZE, capitalize);
- canUseWorkers: typeof Worker !== 'undefined',
+ SVGDOMPropertyConfig.Properties[reactName] = 0;
+ SVGDOMPropertyConfig.DOMAttributeNames[reactName] = original;
+});
- canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),
+injection.injectDOMPropertyConfig(HTMLDOMPropertyConfig);
+injection.injectDOMPropertyConfig(SVGDOMPropertyConfig);
- canUseViewport: canUseDOM && !!window.screen,
+var ReactErrorUtils = {
+ // Used by Fiber to simulate a try-catch.
+ _caughtError: null,
+ _hasCaughtError: false,
- isInWorker: !canUseDOM // For now, this is true - might change in the future.
+ // Used by event system to capture/rethrow the first error.
+ _rethrowError: null,
+ _hasRethrowError: false,
+
+ injection: {
+ injectErrorUtils: function (injectedErrorUtils) {
+ !(typeof injectedErrorUtils.invokeGuardedCallback === 'function') ? invariant_1(false, 'Injected invokeGuardedCallback() must be a function.') : void 0;
+ invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback;
+ }
+ },
+
+ /**
+ * 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.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_1(false, 'clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.');
+ }
+ }
};
-var ExecutionEnvironment_1 = ExecutionEnvironment;
+var invokeGuardedCallback = function (name, func, context, a, b, c, d, e, f) {
+ ReactErrorUtils._hasCaughtError = false;
+ ReactErrorUtils._caughtError = null;
+ var funcArgs = Array.prototype.slice.call(arguments, 3);
+ try {
+ func.apply(context, funcArgs);
+ } catch (error) {
+ ReactErrorUtils._caughtError = error;
+ ReactErrorUtils._hasCaughtError = true;
+ }
+};
-var ReactInternals = require$$0.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+{
+ // 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!
-var assign = ReactInternals.assign;
+ // 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) {
+ // 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.
+ var evt = document.createEvent('Event');
+ 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.');
+ }
+ ReactErrorUtils._hasCaughtError = true;
+ ReactErrorUtils._caughtError = error;
+ } else {
+ ReactErrorUtils._hasCaughtError = false;
+ ReactErrorUtils._caughtError = null;
+ }
+
+ // Remove our event listeners
+ window.removeEventListener('error', onError);
+ };
+
+ invokeGuardedCallback = invokeGuardedCallbackDev;
+ }
+}
+
+var rethrowCaughtError = function () {
+ if (ReactErrorUtils._hasRethrowError) {
+ var error = ReactErrorUtils._rethrowError;
+ ReactErrorUtils._rethrowError = null;
+ ReactErrorUtils._hasRethrowError = false;
+ throw error;
+ }
+};
/**
* Injectable ordering of event plugins.
@@ -204,11 +673,11 @@ function recomputePluginOrdering() {
var pluginModule = namesToPlugins[pluginName];
var pluginIndex = eventPluginOrder.indexOf(pluginName);
!(pluginIndex > -1) ? invariant_1(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : void 0;
- if (EventPluginRegistry.plugins[pluginIndex]) {
+ if (plugins[pluginIndex]) {
continue;
}
!pluginModule.extractEvents ? invariant_1(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : void 0;
- EventPluginRegistry.plugins[pluginIndex] = pluginModule;
+ plugins[pluginIndex] = pluginModule;
var publishedEvents = pluginModule.eventTypes;
for (var eventName in publishedEvents) {
!publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) ? invariant_1(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : void 0;
@@ -225,8 +694,8 @@ function recomputePluginOrdering() {
* @private
*/
function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
- !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : void 0;
- EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;
+ !!eventNameDispatchConfigs.hasOwnProperty(eventName) ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : void 0;
+ eventNameDispatchConfigs[eventName] = dispatchConfig;
var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
if (phasedRegistrationNames) {
@@ -252,16 +721,16 @@ function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
* @private
*/
function publishRegistrationName(registrationName, pluginModule, eventName) {
- !!EventPluginRegistry.registrationNameModules[registrationName] ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : void 0;
- EventPluginRegistry.registrationNameModules[registrationName] = pluginModule;
- EventPluginRegistry.registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies;
+ !!registrationNameModules[registrationName] ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : void 0;
+ registrationNameModules[registrationName] = pluginModule;
+ registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies;
{
var lowerCasedName = registrationName.toLowerCase();
- EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName;
+ possibleRegistrationNames[lowerCasedName] = registrationName;
if (registrationName === 'onDoubleClick') {
- EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName;
+ possibleRegistrationNames.ondblclick = registrationName;
}
}
}
@@ -271,82 +740,89 @@ function publishRegistrationName(registrationName, pluginModule, eventName) {
*
* @see {EventPluginHub}
*/
-var EventPluginRegistry = {
- /**
- * Ordered list of injected plugins.
- */
- plugins: [],
- /**
- * Mapping from event name to dispatch config
- */
- eventNameDispatchConfigs: {},
+/**
+ * Ordered list of injected plugins.
+ */
+var plugins = [];
- /**
- * Mapping from registration name to plugin module
- */
- registrationNameModules: {},
+/**
+ * Mapping from event name to dispatch config
+ */
+var eventNameDispatchConfigs = {};
- /**
- * Mapping from registration name to event name
- */
- registrationNameDependencies: {},
+/**
+ * Mapping from registration name to plugin module
+ */
+var registrationNameModules = {};
- /**
- * 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}
- */
- possibleRegistrationNames: {},
- // Trust the developer to only use possibleRegistrationNames in true
+/**
+ * Mapping from registration name to event name
+ */
+var registrationNameDependencies = {};
- /**
- * 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}
- */
- injectEventPluginOrder: function (injectedEventPluginOrder) {
- !!eventPluginOrder ? invariant_1(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : void 0;
- // Clone the ordering so it cannot be dynamically mutated.
- eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder);
- recomputePluginOrdering();
- },
+/**
+ * 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}
+ */
+var possibleRegistrationNames = {};
+// Trust the developer to only use possibleRegistrationNames in true
- /**
- * 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}
- */
- injectEventPluginsByName: function (injectedNamesToPlugins) {
- var isOrderingDirty = false;
- for (var pluginName in injectedNamesToPlugins) {
- if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
- continue;
- }
- var pluginModule = injectedNamesToPlugins[pluginName];
- if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) {
- !!namesToPlugins[pluginName] ? invariant_1(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : void 0;
- namesToPlugins[pluginName] = pluginModule;
- isOrderingDirty = 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) {
+ !!eventPluginOrder ? invariant_1(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : void 0;
+ // Clone the ordering so it cannot be dynamically mutated.
+ eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder);
+ recomputePluginOrdering();
+}
+
+/**
+ * Injects plugins to be used by `EventPluginHub`. The plugin names must be
+ * in the ordering injected by `injectEventPluginOrder`.
+ *
+ * Plugins can be injected as part of page initialization or on-the-fly.
+ *
+ * @param {object} injectedNamesToPlugins Map from names to plugin modules.
+ * @internal
+ * @see {EventPluginHub.injection.injectEventPluginsByName}
+ */
+function injectEventPluginsByName(injectedNamesToPlugins) {
+ var isOrderingDirty = false;
+ for (var pluginName in injectedNamesToPlugins) {
+ if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
+ continue;
}
- if (isOrderingDirty) {
- recomputePluginOrdering();
+ var pluginModule = injectedNamesToPlugins[pluginName];
+ if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) {
+ !!namesToPlugins[pluginName] ? invariant_1(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : void 0;
+ namesToPlugins[pluginName] = pluginModule;
+ isOrderingDirty = true;
}
}
-};
+ if (isOrderingDirty) {
+ recomputePluginOrdering();
+ }
+}
-var EventPluginRegistry_1 = EventPluginRegistry;
+var EventPluginRegistry = Object.freeze({
+ plugins: plugins,
+ eventNameDispatchConfigs: eventNameDispatchConfigs,
+ registrationNameModules: registrationNameModules,
+ registrationNameDependencies: registrationNameDependencies,
+ possibleRegistrationNames: possibleRegistrationNames,
+ injectEventPluginOrder: injectEventPluginOrder,
+ injectEventPluginsByName: injectEventPluginsByName
+});
/**
* Copyright (c) 2013-present, Facebook, Inc.
@@ -384,462 +860,424 @@ emptyFunction.thatReturnsArgument = function (arg) {
var emptyFunction_1 = emptyFunction;
/**
- * Copyright (c) 2013-present, Facebook, Inc.
+ * Copyright (c) 2014-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.
*
- * @typechecks
*/
+
+
/**
- * Upstream version of event listener. Does not take into account specific
- * nature of platform.
+ * 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 EventListener = {
- /**
- * Listen to DOM events during the bubble phase.
- *
- * @param {DOMEventTarget} target DOM element to register listener on.
- * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
- * @param {function} callback Callback function.
- * @return {object} Object with a `remove` method.
- */
- listen: function listen(target, eventType, callback) {
- if (target.addEventListener) {
- target.addEventListener(eventType, callback, false);
- return {
- remove: function remove() {
- target.removeEventListener(eventType, callback, false);
- }
- };
- } else if (target.attachEvent) {
- target.attachEvent('on' + eventType, callback);
- return {
- remove: function remove() {
- target.detachEvent('on' + eventType, callback);
- }
- };
+
+var warning = emptyFunction_1;
+
+{
+ var printWarning = function printWarning(format) {
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ args[_key - 1] = arguments[_key];
}
- },
- /**
- * Listen to DOM events during the capture phase.
- *
- * @param {DOMEventTarget} target DOM element to register listener on.
- * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
- * @param {function} callback Callback function.
- * @return {object} Object with a `remove` method.
- */
- capture: function capture(target, eventType, callback) {
- if (target.addEventListener) {
- target.addEventListener(eventType, callback, true);
- return {
- remove: function remove() {
- target.removeEventListener(eventType, callback, true);
- }
- };
- } else {
- {
- console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');
+ var argIndex = 0;
+ var message = 'Warning: ' + format.replace(/%s/g, function () {
+ return args[argIndex++];
+ });
+ if (typeof console !== 'undefined') {
+ console.error(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) {}
+ };
+
+ warning = function warning(condition, format) {
+ if (format === undefined) {
+ throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
+ }
+
+ if (format.indexOf('Failed Composite propType: ') === 0) {
+ return; // Ignore CompositeComponent proptype check.
+ }
+
+ if (!condition) {
+ for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
+ args[_key2 - 2] = arguments[_key2];
}
- return {
- remove: emptyFunction_1
- };
+
+ printWarning.apply(undefined, [format].concat(args));
}
- },
+ };
+}
- registerDefault: function registerDefault() {}
-};
+var warning_1 = warning;
-var EventListener_1 = EventListener;
+var getFiberCurrentPropsFromNode = null;
+var getInstanceFromNode = null;
+var getNodeFromInstance = null;
-// These attributes should be all lowercase to allow for
-// case insensitive checks
-var RESERVED_PROPS = {
- children: true,
- dangerouslySetInnerHTML: true,
- autoFocus: true,
- defaultValue: true,
- defaultChecked: true,
- innerHTML: true,
- suppressContentEditableWarning: true,
- style: true
+var injection$2 = {
+ injectComponentTree: function (Injected) {
+ getFiberCurrentPropsFromNode = Injected.getFiberCurrentPropsFromNode;
+ getInstanceFromNode = Injected.getInstanceFromNode;
+ getNodeFromInstance = Injected.getNodeFromInstance;
+
+ {
+ warning_1(getNodeFromInstance && getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.');
+ }
+ }
};
-function checkMask(value, bitmask) {
- return (value & bitmask) === bitmask;
-}
-var DOMPropertyInjection = {
- /**
- * Mapping from normalized, camelcased property names to a configuration that
- * specifies how the associated DOM property should be accessed or rendered.
- */
- MUST_USE_PROPERTY: 0x1,
- HAS_BOOLEAN_VALUE: 0x4,
- HAS_NUMERIC_VALUE: 0x8,
- HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,
- HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,
- HAS_STRING_BOOLEAN_VALUE: 0x40,
- /**
- * Inject some specialized knowledge about the DOM. This takes a config object
- * with the following properties:
- *
- * Properties: object mapping DOM property name to one of the
- * DOMPropertyInjection constants or null. If your attribute isn't in here,
- * it won't get written to the DOM.
- *
- * DOMAttributeNames: object mapping React attribute name to the DOM
- * attribute name. Attribute names not specified use the **lowercase**
- * normalized name.
- *
- * DOMAttributeNamespaces: object mapping React attribute name to the DOM
- * attribute namespace URL. (Attribute names not specified use no namespace.)
- *
- * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.
- * Property names not specified use the normalized name.
- *
- * DOMMutationMethods: Properties that require special mutation methods. If
- * `value` is undefined, the mutation method should unset the property.
- *
- * @param {object} domPropertyConfig the config as described above.
- */
- injectDOMPropertyConfig: function (domPropertyConfig) {
- var Injection = DOMPropertyInjection;
- var Properties = domPropertyConfig.Properties || {};
- var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {};
- var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};
- var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};
- for (var propName in Properties) {
- !!DOMProperty.properties.hasOwnProperty(propName) ? invariant_1(false, 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property \'%s\' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.', propName) : void 0;
- var lowerCased = propName.toLowerCase();
- var propConfig = Properties[propName];
- var propertyInfo = {
- attributeName: lowerCased,
- attributeNamespace: null,
- propertyName: propName,
- mutationMethod: null,
+var validateEventDispatches;
+{
+ validateEventDispatches = function (event) {
+ var dispatchListeners = event._dispatchListeners;
+ var dispatchInstances = event._dispatchInstances;
- mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),
- hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),
- hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),
- hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),
- hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE),
- hasStringBooleanValue: checkMask(propConfig, Injection.HAS_STRING_BOOLEAN_VALUE)
- };
- !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? invariant_1(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s', propName) : void 0;
+ var listenersIsArr = Array.isArray(dispatchListeners);
+ var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
- if (DOMAttributeNames.hasOwnProperty(propName)) {
- var attributeName = DOMAttributeNames[propName];
+ var instancesIsArr = Array.isArray(dispatchInstances);
+ var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
- propertyInfo.attributeName = attributeName;
- }
+ warning_1(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.');
+ };
+}
- if (DOMAttributeNamespaces.hasOwnProperty(propName)) {
- propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName];
- }
+/**
+ * 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;
+}
- if (DOMMutationMethods.hasOwnProperty(propName)) {
- propertyInfo.mutationMethod = DOMMutationMethods[propName];
+/**
+ * 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;
}
-
- // Downcase references to whitelist properties to check for membership
- // without case-sensitivity. This allows the whitelist to pick up
- // `allowfullscreen`, which should be written using the property configuration
- // for `allowFullscreen`
- DOMProperty.properties[propName] = propertyInfo;
+ // 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;
+}
+
+/**
+ * @see executeDispatchesInOrderStopAtTrueImpl
+ */
-/* eslint-disable max-len */
-var ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD';
-/* eslint-enable max-len */
/**
- * DOMProperty exports lookup objects that can be used like functions:
+ * 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.
*
- * > DOMProperty.isValid['id']
- * true
- * > DOMProperty.isValid['foobar']
- * undefined
+ * @return {*} The return value of executing the single dispatch.
+ */
+
+
+/**
+ * @param {SyntheticEvent} event
+ * @return {boolean} True iff number of dispatches accumulated is greater than 0.
+ */
+
+/**
+ * Accumulates items that must not be null or undefined into the first one. This
+ * is used to conserve memory by avoiding array allocations, and thus sacrifices
+ * API cleanness. Since `current` can be null before being passed in and not
+ * null after this function, make sure to assign it back to `current`:
*
- * Although this may be confusing, it performs better in general.
+ * `a = accumulateInto(a, b);`
+ *
+ * This API should be sparingly used. Try `accumulate` for something cleaner.
*
- * @see http://jsperf.com/key-exists
- * @see http://jsperf.com/key-missing
+ * @return {*|array<*>} An accumulation of items.
*/
-var DOMProperty = {
- ID_ATTRIBUTE_NAME: 'data-reactid',
- ROOT_ATTRIBUTE_NAME: 'data-reactroot',
-
- ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR,
- ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040',
- /**
- * Map from property "standard name" to an object with info about how to set
- * the property in the DOM. Each object contains:
- *
- * attributeName:
- * Used when rendering markup or with `*Attribute()`.
- * attributeNamespace
- * propertyName:
- * Used on DOM node instances. (This includes properties that mutate due to
- * external factors.)
- * mutationMethod:
- * If non-null, used instead of the property or `setAttribute()` after
- * initial render.
- * mustUseProperty:
- * Whether the property must be accessed and mutated as an object property.
- * hasBooleanValue:
- * Whether the property should be removed when set to a falsey value.
- * hasNumericValue:
- * Whether the property must be numeric or parse as a numeric and should be
- * removed when set to a falsey value.
- * hasPositiveNumericValue:
- * Whether the property must be positive numeric or parse as a positive
- * numeric and should be removed when set to a falsey value.
- * hasOverloadedBooleanValue:
- * Whether the property can be used as a flag as well as with a value.
- * Removed when strictly equal to false; present without a value when
- * strictly equal to true; present with a value otherwise.
- */
- properties: {},
+function accumulateInto(current, next) {
+ !(next != null) ? invariant_1(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : void 0;
- /**
- * Checks whether a property name is a writeable attribute.
- * @method
- */
- shouldSetAttribute: function (name, value) {
- if (DOMProperty.isReservedProp(name)) {
- return false;
- }
- if ((name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) {
- return false;
- }
- if (value === null) {
- return true;
- }
- switch (typeof value) {
- case 'boolean':
- return DOMProperty.shouldAttributeAcceptBooleanValue(name);
- case 'undefined':
- case 'number':
- case 'string':
- case 'object':
- return true;
- default:
- // function, symbol
- return false;
- }
- },
+ if (current == null) {
+ return next;
+ }
- getPropertyInfo: function (name) {
- return DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
- },
- shouldAttributeAcceptBooleanValue: function (name) {
- if (DOMProperty.isReservedProp(name)) {
- return true;
- }
- var propertyInfo = DOMProperty.getPropertyInfo(name);
- if (propertyInfo) {
- return propertyInfo.hasBooleanValue || propertyInfo.hasStringBooleanValue || propertyInfo.hasOverloadedBooleanValue;
+ // 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;
}
- var prefix = name.toLowerCase().slice(0, 5);
- return prefix === 'data-' || prefix === 'aria-';
- },
-
+ current.push(next);
+ return current;
+ }
- /**
- * Checks to see if a property name is within the list of properties
- * reserved for internal React operations. These properties should
- * not be set on an HTML element.
- *
- * @private
- * @param {string} name
- * @return {boolean} If the name is within reserved props
- */
- isReservedProp: function (name) {
- return RESERVED_PROPS.hasOwnProperty(name);
- },
+ if (Array.isArray(next)) {
+ // A bit too dangerous to mutate `next`.
+ return [current].concat(next);
+ }
+ return [current, next];
+}
- injection: DOMPropertyInjection
-};
+/**
+ * @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);
+ }
+}
-var DOMProperty_1 = DOMProperty;
+/**
+ * Internal queue of events that have accumulated their dispatches and are
+ * waiting to have their dispatches executed.
+ */
+var eventQueue = null;
/**
- * Copyright (c) 2015-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.
+ * Dispatches an event and releases it back into the pool, unless persistent.
*
- * @providesModule ReactDOMComponentFlags
+ * @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);
-var ReactDOMComponentFlags = {
- hasCachedChildNodes: 1 << 0
+ if (!event.isPersistent()) {
+ event.constructor.release(event);
+ }
+ }
+};
+var executeDispatchesAndReleaseSimulated = function (e) {
+ return executeDispatchesAndRelease(e, true);
+};
+var executeDispatchesAndReleaseTopLevel = function (e) {
+ return executeDispatchesAndRelease(e, false);
};
-var ReactDOMComponentFlags_1 = ReactDOMComponentFlags;
+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;
+ }
+}
/**
- * Copyright (c) 2013-present, Facebook, Inc.
+ * This is a unified interface for event plugins to be installed and configured.
*
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
+ * Event plugins can implement the following properties:
*
- * @providesModule ReactTypeOfWork
- *
- */
-
-var ReactTypeOfWork = {
- IndeterminateComponent: 0, // Before we know whether it is functional or class
- FunctionalComponent: 1,
- ClassComponent: 2,
- HostRoot: 3, // Root of a host tree. Could be nested inside another node.
- HostPortal: 4, // A subtree. Could be an entry point to a different renderer.
- HostComponent: 5,
- HostText: 6,
- CoroutineComponent: 7,
- CoroutineHandlerPhase: 8,
- YieldComponent: 9,
- Fragment: 10
-};
-
-/**
- * Copyright (c) 2013-present, Facebook, Inc.
+ * `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.
*
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
+ * `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`.
*
- * @providesModule HTMLNodeType
+ * `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
*/
/**
- * HTML nodeType values that represent the type of the node
+ * Methods for injecting dependencies.
*/
+var injection$1 = {
+ /**
+ * @param {array} InjectedEventPluginOrder
+ * @public
+ */
+ injectEventPluginOrder: injectEventPluginOrder,
-var HTMLNodeType = {
- ELEMENT_NODE: 1,
- TEXT_NODE: 3,
- COMMENT_NODE: 8,
- DOCUMENT_NODE: 9,
- DOCUMENT_FRAGMENT_NODE: 11
+ /**
+ * @param {object} injectedNamesToPlugins Map from names to plugin modules.
+ */
+ injectEventPluginsByName: injectEventPluginsByName
};
-var HTMLNodeType_1 = HTMLNodeType;
-
-var HostComponent = ReactTypeOfWork.HostComponent;
-var HostText = ReactTypeOfWork.HostText;
-
-var ELEMENT_NODE$1 = HTMLNodeType_1.ELEMENT_NODE;
-var COMMENT_NODE$1 = HTMLNodeType_1.COMMENT_NODE;
-
-
-
-var ATTR_NAME = DOMProperty_1.ID_ATTRIBUTE_NAME;
-var Flags = ReactDOMComponentFlags_1;
-
-var randomKey = Math.random().toString(36).slice(2);
-
-var internalInstanceKey = '__reactInternalInstance$' + randomKey;
-
-var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
-
/**
- * Check if a given node should be cached.
+ * @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 shouldPrecacheNode(node, nodeID) {
- return node.nodeType === ELEMENT_NODE$1 && node.getAttribute(ATTR_NAME) === '' + nodeID || node.nodeType === COMMENT_NODE$1 && node.nodeValue === ' react-text: ' + nodeID + ' ' || node.nodeType === COMMENT_NODE$1 && node.nodeValue === ' react-empty: ' + nodeID + ' ';
+function getListener(inst, registrationName) {
+ var listener;
+
+ // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
+ // live here; needs to be moved to a better place soon
+ var stateNode = inst.stateNode;
+ if (!stateNode) {
+ // Work in progress (ex: onload events in incremental mode).
+ return null;
+ }
+ var props = getFiberCurrentPropsFromNode(stateNode);
+ if (!props) {
+ // Work in progress.
+ return null;
+ }
+ listener = props[registrationName];
+ if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
+ return null;
+ }
+ !(!listener || typeof listener === 'function') ? invariant_1(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener) : void 0;
+ return listener;
}
/**
- * Drill down (through composites and empty components) until we get a host or
- * host text component.
+ * Allows registered plugins an opportunity to extract events from top-level
+ * native browser events.
*
- * This is pretty polymorphic but unavoidable with the current structure we have
- * for `_renderedChildren`.
+ * @return {*} An accumulation of synthetic events.
+ * @internal
*/
-function getRenderedHostOrTextFromComponent(component) {
- var rendered;
- while (rendered = component._renderedComponent) {
- component = rendered;
+function extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var events;
+ 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 component;
+ return events;
}
/**
- * Populate `_hostNode` on the rendered host/text component with the given
- * DOM node. The passed `inst` can be a composite.
+ * Enqueues a synthetic event that should be dispatched when
+ * `processEventQueue` is invoked.
+ *
+ * @param {*} events An accumulation of synthetic events.
+ * @internal
*/
-function precacheNode(inst, node) {
- var hostInst = getRenderedHostOrTextFromComponent(inst);
- hostInst._hostNode = node;
- node[internalInstanceKey] = hostInst;
-}
-
-function precacheFiberNode$1(hostInst, node) {
- node[internalInstanceKey] = hostInst;
-}
-
-function uncacheNode(inst) {
- var node = inst._hostNode;
- if (node) {
- delete node[internalInstanceKey];
- inst._hostNode = null;
+function enqueueEvents(events) {
+ if (events) {
+ eventQueue = accumulateInto(eventQueue, events);
}
}
/**
- * Populate `_hostNode` on each child of `inst`, assuming that the children
- * match up with the DOM (element) children of `node`.
- *
- * We cache entire levels at once to avoid an n^2 problem where we access the
- * children of a node sequentially and have to walk from the start to our target
- * node every time.
+ * Dispatches all synthetic events on the event queue.
*
- * Since we update `_renderedChildren` and the actual DOM at (slightly)
- * different times, we could race here and see a newer `_renderedChildren` than
- * the DOM nodes we see. To avoid this, ReactMultiChild calls
- * `prepareToManageChildren` before we change `_renderedChildren`, at which
- * time the container's child nodes are always cached (until it unmounts).
+ * @internal
*/
-function precacheChildNodes(inst, node) {
- if (inst._flags & Flags.hasCachedChildNodes) {
+function processEventQueue(simulated) {
+ // 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;
}
- var children = inst._renderedChildren;
- var childNode = node.firstChild;
- outer: for (var name in children) {
- if (!children.hasOwnProperty(name)) {
- continue;
- }
- var childInst = children[name];
- var childID = getRenderedHostOrTextFromComponent(childInst)._domID;
- if (childID === 0) {
- // We're currently unmounting this child in ReactMultiChild; skip it.
- continue;
- }
- // We assume the child nodes are in the same order as the child instances.
- for (; childNode !== null; childNode = childNode.nextSibling) {
- if (shouldPrecacheNode(childNode, childID)) {
- precacheNode(childInst, childNode);
- continue outer;
- }
- }
- // We reached the end of the DOM children without finding an ID match.
- invariant_1(false, 'Unable to find element with ID %s.', childID);
+
+ if (simulated) {
+ forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);
+ } else {
+ forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);
}
- inst._flags |= Flags.hasCachedChildNodes;
+ !!eventQueue ? invariant_1(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : void 0;
+ // This would be a good time to rethrow if any of the event handlers threw.
+ ReactErrorUtils.rethrowCaughtError();
+}
+
+var EventPluginHub = Object.freeze({
+ injection: injection$1,
+ getListener: getListener,
+ extractEvents: extractEvents,
+ enqueueEvents: enqueueEvents,
+ processEventQueue: processEventQueue
+});
+
+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 randomKey = Math.random().toString(36).slice(2);
+var internalInstanceKey = '__reactInternalInstance$' + randomKey;
+var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
+
+function precacheFiberNode$1(hostInst, node) {
+ node[internalInstanceKey] = hostInst;
}
/**
@@ -864,7 +1302,7 @@ function getClosestInstanceFromNode(node) {
}
}
- var closest;
+ var closest = void 0;
var inst = node[internalInstanceKey];
if (inst.tag === HostComponent || inst.tag === HostText) {
// In Fiber, this will always be the deepest root.
@@ -872,9 +1310,6 @@ function getClosestInstanceFromNode(node) {
}
for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {
closest = inst;
- if (parents.length) {
- precacheChildNodes(inst, node);
- }
}
return closest;
@@ -884,30 +1319,23 @@ function getClosestInstanceFromNode(node) {
* Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
* instance, or null if the node was not rendered by this React.
*/
-function getInstanceFromNode(node) {
+function getInstanceFromNode$1(node) {
var inst = node[internalInstanceKey];
if (inst) {
if (inst.tag === HostComponent || inst.tag === HostText) {
return inst;
- } else if (inst._hostNode === node) {
- return inst;
} else {
return null;
}
}
- inst = getClosestInstanceFromNode(node);
- if (inst != null && inst._hostNode === node) {
- return inst;
- } else {
- return null;
- }
+ return null;
}
/**
* Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
* DOM node.
*/
-function getNodeFromInstance(inst) {
+function getNodeFromInstance$1(inst) {
if (inst.tag === HostComponent || inst.tag === HostText) {
// In Fiber this, is just the state node right now. We assume it will be
// a host component or host text.
@@ -916,50 +1344,265 @@ function getNodeFromInstance(inst) {
// Without this first invariant, passing a non-DOM-component triggers the next
// invariant for a missing parent, which is super confusing.
- !(inst._hostNode !== undefined) ? invariant_1(false, 'getNodeFromInstance: Invalid argument.') : void 0;
+ invariant_1(false, 'getNodeFromInstance: Invalid argument.');
+}
+
+function getFiberCurrentPropsFromNode$1(node) {
+ return node[internalEventHandlersKey] || null;
+}
+
+function updateFiberProps$1(node, props) {
+ node[internalEventHandlersKey] = props;
+}
+
+var ReactDOMComponentTree = Object.freeze({
+ precacheFiberNode: precacheFiberNode$1,
+ getClosestInstanceFromNode: getClosestInstanceFromNode,
+ getInstanceFromNode: getInstanceFromNode$1,
+ getNodeFromInstance: getNodeFromInstance$1,
+ getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode$1,
+ updateFiberProps: updateFiberProps$1
+});
- if (inst._hostNode) {
- return inst._hostNode;
+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;
+}
- // Walk up the tree until we find an ancestor whose DOM node we have cached.
- var parents = [];
- while (!inst._hostNode) {
- parents.push(inst);
- !inst._hostParent ? invariant_1(false, 'React DOM tree root should always have a node reference.') : void 0;
- inst = inst._hostParent;
+/**
+ * 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--;
}
- // Now parents contains each ancestor that does *not* have a cached native
- // node, and `inst` is the deepest ancestor that does.
- for (; parents.length; inst = parents.pop()) {
- precacheChildNodes(inst, inst._hostNode);
+ // If B is deeper, crawl up.
+ while (depthB - depthA > 0) {
+ instB = getParent(instB);
+ depthB--;
}
- return inst._hostNode;
+ // 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;
}
-function getFiberCurrentPropsFromNode(node) {
- return node[internalEventHandlersKey] || null;
+/**
+ * Return if A is an ancestor of B.
+ */
+
+
+/**
+ * Return the parent instance of the passed-in instance.
+ */
+function getParentInstance(inst) {
+ return getParent(inst);
}
-function updateFiberProps$1(node, props) {
- node[internalEventHandlersKey] = props;
+/**
+ * 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;
+ for (i = path.length; i-- > 0;) {
+ fn(path[i], 'captured', arg);
+ }
+ for (i = 0; i < path.length; i++) {
+ fn(path[i], 'bubbled', arg);
+ }
}
-var ReactDOMComponentTree = {
- getClosestInstanceFromNode: getClosestInstanceFromNode,
- getInstanceFromNode: getInstanceFromNode,
- getNodeFromInstance: getNodeFromInstance,
- precacheChildNodes: precacheChildNodes,
- precacheNode: precacheNode,
- uncacheNode: uncacheNode,
- precacheFiberNode: precacheFiberNode$1,
- getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode,
- updateFiberProps: updateFiberProps$1
-};
+/**
+ * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
+ * should would receive a `mouseEnter` or `mouseLeave` event.
+ *
+ * Does not invoke the callback on the nearest common ancestor because nothing
+ * "entered" or "left" that element.
+ */
+function traverseEnterLeave(from, to, fn, argFrom, argTo) {
+ var common = from && to ? getLowestCommonAncestor(from, to) : null;
+ var pathFrom = [];
+ while (true) {
+ if (!from) {
+ break;
+ }
+ if (from === common) {
+ break;
+ }
+ var alternate = from.alternate;
+ if (alternate !== null && alternate === common) {
+ break;
+ }
+ pathFrom.push(from);
+ from = getParent(from);
+ }
+ var pathTo = [];
+ while (true) {
+ if (!to) {
+ break;
+ }
+ if (to === common) {
+ break;
+ }
+ var _alternate = to.alternate;
+ if (_alternate !== null && _alternate === common) {
+ break;
+ }
+ pathTo.push(to);
+ to = getParent(to);
+ }
+ for (var i = 0; i < pathFrom.length; i++) {
+ fn(pathFrom[i], 'bubbled', argFrom);
+ }
+ for (var _i = pathTo.length; _i-- > 0;) {
+ fn(pathTo[_i], 'captured', argTo);
+ }
+}
+
+/**
+ * Some event types have a notion of different registration names for different
+ * "phases" of propagation. This finds listeners by a given phase.
+ */
+function listenerAtPhase(inst, event, propagationPhase) {
+ var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
+ return getListener(inst, registrationName);
+}
+
+/**
+ * A small set of propagation patterns, each of which will accept a small amount
+ * of information, and generate a set of "dispatch ready event objects" - which
+ * are sets of events that have already been annotated with a set of dispatched
+ * listener functions/ids. The API is designed this way to discourage these
+ * propagation strategies from actually executing the dispatches, since we
+ * always want to collect the entire set of dispatches before executing even a
+ * single one.
+ */
+
+/**
+ * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
+ * here, allows us to not have to bind or create functions for each event.
+ * Mutating the event's members allows us to not have to create a wrapping
+ * "dispatch" object that pairs the event with the listener.
+ */
+function accumulateDirectionalDispatches(inst, phase, event) {
+ {
+ warning_1(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 accumulateEnterLeaveDispatches(leave, enter, from, to) {
+ traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
+}
+
+function accumulateDirectDispatches(events) {
+ forEachAccumulated(events, accumulateDirectDispatchesSingle);
+}
-var ReactDOMComponentTree_1 = ReactDOMComponentTree;
+var EventPropagators = Object.freeze({
+ accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
+ accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
+ accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches,
+ accumulateDirectDispatches: accumulateDirectDispatches
+});
/**
* Copyright (c) 2013-present, Facebook, Inc.
@@ -967,183 +1610,1604 @@ var ReactDOMComponentTree_1 = ReactDOMComponentTree;
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- * @providesModule ReactInstanceMap
*/
+
+
+var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
+
/**
- * `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.
+ * Simple, lightweight module assisting with the detection and context of
+ * Worker. Helps avoid circular dependencies and allows code to reason about
+ * whether or not they are in a Worker, even if they never include the main
+ * `ReactWorker` dependency.
*/
+var ExecutionEnvironment = {
-// TODO: Replace this with ES6: var ReactInstanceMap = new Map();
+ canUseDOM: canUseDOM,
-var ReactInstanceMap = {
- /**
- * 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.
- */
- remove: function (key) {
- key._reactInternalFiber = undefined;
+ canUseWorkers: typeof Worker !== 'undefined',
+
+ canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),
+
+ canUseViewport: canUseDOM && !!window.screen,
+
+ isInWorker: !canUseDOM // For now, this is true - might change in the future.
+
+};
+
+var ExecutionEnvironment_1 = ExecutionEnvironment;
+
+var contentKey = null;
+
+/**
+ * Gets the key used to access text content on a DOM node.
+ *
+ * @return {?string} Key used to access text content.
+ * @internal
+ */
+function getTextContentAccessor() {
+ if (!contentKey && ExecutionEnvironment_1.canUseDOM) {
+ // Prefer textContent to innerText because many browsers support both but
+ // SVG <text> elements don't support innerText even when <div> does.
+ contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';
+ }
+ return contentKey;
+}
+
+/**
+ * This helper object stores information about text content of a target node,
+ * allowing comparison of content before and after a given event.
+ *
+ * Identify the node where selection currently begins, then observe
+ * both its text content and its current position in the DOM. Since the
+ * browser may natively replace the target node during composition, we can
+ * use its position to find its replacement.
+ *
+ *
+ */
+var compositionState = {
+ _root: null,
+ _startText: null,
+ _fallbackText: null
+};
+
+function initialize(nativeEventTarget) {
+ compositionState._root = nativeEventTarget;
+ compositionState._startText = getText();
+ return true;
+}
+
+function reset() {
+ compositionState._root = null;
+ compositionState._startText = null;
+ compositionState._fallbackText = null;
+}
+
+function getData() {
+ if (compositionState._fallbackText) {
+ return compositionState._fallbackText;
+ }
+
+ var start;
+ var startValue = compositionState._startText;
+ var startLength = startValue.length;
+ var end;
+ var endValue = getText();
+ var endLength = endValue.length;
+
+ for (start = 0; start < startLength; start++) {
+ if (startValue[start] !== endValue[start]) {
+ break;
+ }
+ }
+
+ var minEnd = startLength - start;
+ for (end = 1; end <= minEnd; end++) {
+ if (startValue[startLength - end] !== endValue[endLength - end]) {
+ break;
+ }
+ }
+
+ var sliceTail = end > 1 ? 1 - end : undefined;
+ compositionState._fallbackText = endValue.slice(start, sliceTail);
+ return compositionState._fallbackText;
+}
+
+function getText() {
+ if ('value' in compositionState._root) {
+ return compositionState._root.value;
+ }
+ return compositionState._root[getTextContentAccessor()];
+}
+
+var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+var _assign = ReactInternals.assign;
+
+/* eslint valid-typeof: 0 */
+
+var didWarnForAddedNewProperty = false;
+var isProxySupported = typeof Proxy === 'function';
+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_1.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_1.thatReturnsTrue;
+ } else {
+ this.isDefaultPrevented = emptyFunction_1.thatReturnsFalse;
+ }
+ this.isPropagationStopped = emptyFunction_1.thatReturnsFalse;
+ return this;
+}
+
+_assign(SyntheticEvent.prototype, {
+ preventDefault: function () {
+ this.defaultPrevented = true;
+ var event = this.nativeEvent;
+ if (!event) {
+ return;
+ }
+
+ if (event.preventDefault) {
+ event.preventDefault();
+ } else if (typeof event.returnValue !== 'unknown') {
+ event.returnValue = false;
+ }
+ this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue;
},
- get: function (key) {
- return key._reactInternalFiber;
+ 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_1.thatReturnsTrue;
},
- has: function (key) {
- return key._reactInternalFiber !== undefined;
+ /**
+ * 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_1.thatReturnsTrue;
},
- set: function (key, value) {
- key._reactInternalFiber = value;
+ /**
+ * Checks if this event should be released back into the pool.
+ *
+ * @return {boolean} True if this should not be released, false otherwise.
+ */
+ isPersistent: emptyFunction_1.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_1));
+ Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction_1));
+ }
}
-};
+});
-var ReactInstanceMap_1 = ReactInstanceMap;
+SyntheticEvent.Interface = EventInterface;
-var ReactInternals$1 = require$$0.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+/**
+ * Helper to reduce boilerplate when creating subclasses.
+ *
+ * @param {function} Class
+ * @param {?object} Interface
+ */
+SyntheticEvent.augmentClass = function (Class, Interface) {
+ var Super = this;
-var ReactGlobalSharedState = {
- ReactCurrentOwner: ReactInternals$1.ReactCurrentOwner
+ var E = function () {};
+ E.prototype = Super.prototype;
+ var prototype = new E();
+
+ _assign(prototype, Class.prototype);
+ Class.prototype = prototype;
+ Class.prototype.constructor = Class;
+
+ Class.Interface = _assign({}, Super.Interface, Interface);
+ Class.augmentClass = Super.augmentClass;
+ addEventPoolingTo(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)
+ */
{
- assign(ReactGlobalSharedState, {
- ReactComponentTreeHook: ReactInternals$1.ReactComponentTreeHook,
- ReactDebugCurrentFrame: ReactInternals$1.ReactDebugCurrentFrame
- });
+ 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_1(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 */
+ }
}
-var ReactGlobalSharedState_1 = ReactGlobalSharedState;
+addEventPoolingTo(SyntheticEvent);
/**
- * Copyright (c) 2013-present, Facebook, Inc.
+ * Helper to nullify syntheticEvent instance properties when destructing
*
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
+ * @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_1(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;
+ !(event instanceof EventConstructor) ? invariant_1(false, 'Trying to release an event instance into a pool of a different type.') : void 0;
+ event.destructor();
+ if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
+ EventConstructor.eventPool.push(event);
+ }
+}
+
+function addEventPoolingTo(EventConstructor) {
+ EventConstructor.eventPool = [];
+ EventConstructor.getPooled = getPooledEvent;
+ EventConstructor.release = releasePooledEvent;
+}
+
+var SyntheticEvent$1 = SyntheticEvent;
+
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents
+ */
+var CompositionEventInterface = {
+ data: null
+};
+
+/**
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticEvent}
+ */
+function SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+}
+
+SyntheticEvent$1.augmentClass(SyntheticCompositionEvent, CompositionEventInterface);
+
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
+ * /#events-inputevents
+ */
+var InputEventInterface = {
+ data: null
+};
+
+/**
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticEvent}
+ */
+function SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+}
+
+SyntheticEvent$1.augmentClass(SyntheticInputEvent, InputEventInterface);
+
+var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
+var START_KEYCODE = 229;
+
+var canUseCompositionEvent = ExecutionEnvironment_1.canUseDOM && 'CompositionEvent' in window;
+
+var documentMode = null;
+if (ExecutionEnvironment_1.canUseDOM && 'documentMode' in document) {
+ documentMode = document.documentMode;
+}
+
+// Webkit offers a very useful `textInput` event that can be used to
+// directly represent `beforeInput`. The IE `textinput` event is not as
+// useful, so we don't use it.
+var canUseTextInputEvent = ExecutionEnvironment_1.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto();
+
+// In IE9+, we have access to composition events, but the data supplied
+// by the native compositionend event may be incorrect. Japanese ideographic
+// spaces, for instance (\u3000) are not recorded correctly.
+var useFallbackCompositionData = ExecutionEnvironment_1.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);
+
+/**
+ * Opera <= 12 includes TextEvent in window, but does not fire
+ * text input events. Rely on keypress instead.
+ */
+function isPresto() {
+ var opera = window.opera;
+ return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12;
+}
+
+var SPACEBAR_CODE = 32;
+var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
+
+// Events and their corresponding property names.
+var eventTypes = {
+ beforeInput: {
+ phasedRegistrationNames: {
+ bubbled: 'onBeforeInput',
+ captured: 'onBeforeInputCapture'
+ },
+ dependencies: ['topCompositionEnd', 'topKeyPress', 'topTextInput', 'topPaste']
+ },
+ compositionEnd: {
+ phasedRegistrationNames: {
+ bubbled: 'onCompositionEnd',
+ captured: 'onCompositionEndCapture'
+ },
+ dependencies: ['topBlur', 'topCompositionEnd', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
+ },
+ compositionStart: {
+ phasedRegistrationNames: {
+ bubbled: 'onCompositionStart',
+ captured: 'onCompositionStartCapture'
+ },
+ dependencies: ['topBlur', 'topCompositionStart', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
+ },
+ compositionUpdate: {
+ phasedRegistrationNames: {
+ bubbled: 'onCompositionUpdate',
+ captured: 'onCompositionUpdateCapture'
+ },
+ dependencies: ['topBlur', 'topCompositionUpdate', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
+ }
+};
+
+// Track whether we've ever handled a keypress on the space key.
+var hasSpaceKeypress = false;
+
+/**
+ * Return whether a native keypress event is assumed to be a command.
+ * This is required because Firefox fires `keypress` events for key commands
+ * (cut, copy, select-all, etc.) even though no character is inserted.
+ */
+function isKeypressCommand(nativeEvent) {
+ return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
+ // ctrlKey && altKey is equivalent to AltGr, and is not a command.
+ !(nativeEvent.ctrlKey && nativeEvent.altKey);
+}
+
+/**
+ * Translate native top level events into event types.
*
- * @providesModule getComponentName
- *
+ * @param {string} topLevelType
+ * @return {object}
*/
+function getCompositionEventType(topLevelType) {
+ switch (topLevelType) {
+ case 'topCompositionStart':
+ return eventTypes.compositionStart;
+ case 'topCompositionEnd':
+ return eventTypes.compositionEnd;
+ case 'topCompositionUpdate':
+ return eventTypes.compositionUpdate;
+ }
+}
-function getComponentName(instanceOrFiber) {
- if (typeof instanceOrFiber.getName === 'function') {
- // Stack reconciler
- var instance = instanceOrFiber;
- return instance.getName();
+/**
+ * Does our fallback best-guess model think this event signifies that
+ * composition has begun?
+ *
+ * @param {string} topLevelType
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isFallbackCompositionStart(topLevelType, nativeEvent) {
+ return topLevelType === 'topKeyDown' && nativeEvent.keyCode === START_KEYCODE;
+}
+
+/**
+ * Does our fallback mode think that this event is the end of composition?
+ *
+ * @param {string} topLevelType
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isFallbackCompositionEnd(topLevelType, nativeEvent) {
+ switch (topLevelType) {
+ case 'topKeyUp':
+ // Command keys insert or clear IME input.
+ return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
+ case 'topKeyDown':
+ // Expect IME keyCode on each keydown. If we get any other
+ // code we must have exited earlier.
+ return nativeEvent.keyCode !== START_KEYCODE;
+ case 'topKeyPress':
+ case 'topMouseDown':
+ case 'topBlur':
+ // Events are not possible without cancelling IME.
+ return true;
+ default:
+ return false;
}
- if (typeof instanceOrFiber.tag === 'number') {
- // Fiber reconciler
- var fiber = instanceOrFiber;
- var type = fiber.type;
+}
- if (typeof type === 'string') {
- return type;
- }
- if (typeof type === 'function') {
- return type.displayName || type.name;
- }
+/**
+ * Google Input Tools provides composition data via a CustomEvent,
+ * with the `data` property populated in the `detail` object. If this
+ * is available on the event object, use it. If not, this is a plain
+ * composition event and we have nothing special to extract.
+ *
+ * @param {object} nativeEvent
+ * @return {?string}
+ */
+function getDataFromCustomEvent(nativeEvent) {
+ var detail = nativeEvent.detail;
+ if (typeof detail === 'object' && 'data' in detail) {
+ return detail.data;
}
return null;
}
-var getComponentName_1 = getComponentName;
+// Track the current IME composition status, if any.
+var isComposing = false;
/**
- * 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.
+ * @return {?object} A SyntheticCompositionEvent.
*/
+function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var eventType;
+ var fallbackData;
-var warning$2 = emptyFunction_1;
-
-{
- var printWarning = function printWarning(format) {
- for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- args[_key - 1] = arguments[_key];
+ if (canUseCompositionEvent) {
+ eventType = getCompositionEventType(topLevelType);
+ } else if (!isComposing) {
+ if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
+ eventType = eventTypes.compositionStart;
}
+ } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
+ eventType = eventTypes.compositionEnd;
+ }
- var argIndex = 0;
- var message = 'Warning: ' + format.replace(/%s/g, function () {
- return args[argIndex++];
- });
- if (typeof console !== 'undefined') {
- console.error(message);
+ if (!eventType) {
+ return null;
+ }
+
+ if (useFallbackCompositionData) {
+ // The current composition is stored statically and must not be
+ // overwritten while composition continues.
+ if (!isComposing && eventType === eventTypes.compositionStart) {
+ isComposing = initialize(nativeEventTarget);
+ } else if (eventType === eventTypes.compositionEnd) {
+ if (isComposing) {
+ fallbackData = getData();
+ }
}
- 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) {}
- };
+ }
- warning$2 = function warning(condition, format) {
- if (format === undefined) {
- throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
+ var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);
+
+ if (fallbackData) {
+ // Inject data generated from fallback path into the synthetic event.
+ // This matches the property of native CompositionEventInterface.
+ event.data = fallbackData;
+ } else {
+ var customData = getDataFromCustomEvent(nativeEvent);
+ if (customData !== null) {
+ event.data = customData;
}
+ }
- if (format.indexOf('Failed Composite propType: ') === 0) {
- return; // Ignore CompositeComponent proptype check.
+ accumulateTwoPhaseDispatches(event);
+ return event;
+}
+
+/**
+ * @param {TopLevelTypes} topLevelType Record from `BrowserEventConstants`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?string} The string corresponding to this `beforeInput` event.
+ */
+function getNativeBeforeInputChars(topLevelType, nativeEvent) {
+ switch (topLevelType) {
+ case 'topCompositionEnd':
+ return getDataFromCustomEvent(nativeEvent);
+ case 'topKeyPress':
+ /**
+ * If native `textInput` events are available, our goal is to make
+ * use of them. However, there is a special case: the spacebar key.
+ * In Webkit, preventing default on a spacebar `textInput` event
+ * cancels character insertion, but it *also* causes the browser
+ * to fall back to its default spacebar behavior of scrolling the
+ * page.
+ *
+ * Tracking at:
+ * https://code.google.com/p/chromium/issues/detail?id=355103
+ *
+ * To avoid this issue, use the keypress event as if no `textInput`
+ * event is available.
+ */
+ var which = nativeEvent.which;
+ if (which !== SPACEBAR_CODE) {
+ return null;
+ }
+
+ hasSpaceKeypress = true;
+ return SPACEBAR_CHAR;
+
+ case 'topTextInput':
+ // Record the characters to be added to the DOM.
+ var chars = nativeEvent.data;
+
+ // If it's a spacebar character, assume that we have already handled
+ // it at the keypress level and bail immediately. Android Chrome
+ // doesn't give us keycodes, so we need to blacklist it.
+ if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
+ return null;
+ }
+
+ return chars;
+
+ default:
+ // For other native event types, do nothing.
+ return null;
+ }
+}
+
+/**
+ * For browsers that do not provide the `textInput` event, extract the
+ * appropriate string to use for SyntheticInputEvent.
+ *
+ * @param {string} topLevelType Record from `BrowserEventConstants`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?string} The fallback string for this `beforeInput` event.
+ */
+function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
+ // If we are currently composing (IME) and using a fallback to do so,
+ // try to extract the composed characters from the fallback object.
+ // If composition event is available, we extract a string only at
+ // compositionevent, otherwise extract it at fallback events.
+ if (isComposing) {
+ if (topLevelType === 'topCompositionEnd' || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) {
+ var chars = getData();
+ reset();
+ isComposing = false;
+ return chars;
}
+ return null;
+ }
- if (!condition) {
- for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
- args[_key2 - 2] = arguments[_key2];
+ switch (topLevelType) {
+ case 'topPaste':
+ // If a paste event occurs after a keypress, throw out the input
+ // chars. Paste events should not lead to BeforeInput events.
+ return null;
+ case 'topKeyPress':
+ /**
+ * As of v27, Firefox may fire keypress events even when no character
+ * will be inserted. A few possibilities:
+ *
+ * - `which` is `0`. Arrow keys, Esc key, etc.
+ *
+ * - `which` is the pressed key code, but no char is available.
+ * Ex: 'AltGr + d` in Polish. There is no modified character for
+ * this key combination and no character is inserted into the
+ * document, but FF fires the keypress for char code `100` anyway.
+ * No `input` event will occur.
+ *
+ * - `which` is the pressed key code, but a command combination is
+ * being used. Ex: `Cmd+C`. No character is inserted, and no
+ * `input` event will occur.
+ */
+ if (!isKeypressCommand(nativeEvent)) {
+ // IE fires the `keypress` event when a user types an emoji via
+ // Touch keyboard of Windows. In such a case, the `char` property
+ // holds an emoji character like `\uD83D\uDE0A`. Because its length
+ // is 2, the property `which` does not represent an emoji correctly.
+ // In such a case, we directly return the `char` property instead of
+ // using `which`.
+ if (nativeEvent.char && nativeEvent.char.length > 1) {
+ return nativeEvent.char;
+ } else if (nativeEvent.which) {
+ return String.fromCharCode(nativeEvent.which);
+ }
}
+ return null;
+ case 'topCompositionEnd':
+ return useFallbackCompositionData ? null : nativeEvent.data;
+ default:
+ return null;
+ }
+}
- printWarning.apply(undefined, [format].concat(args));
+/**
+ * Extract a SyntheticInputEvent for `beforeInput`, based on either native
+ * `textInput` or fallback behavior.
+ *
+ * @return {?object} A SyntheticInputEvent.
+ */
+function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var chars;
+
+ if (canUseTextInputEvent) {
+ chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
+ } else {
+ chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
+ }
+
+ // If no characters are being inserted, no BeforeInput event should
+ // be fired.
+ if (!chars) {
+ return null;
+ }
+
+ var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);
+
+ event.data = chars;
+ accumulateTwoPhaseDispatches(event);
+ return event;
+}
+
+/**
+ * Create an `onBeforeInput` event to match
+ * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
+ *
+ * This event plugin is based on the native `textInput` event
+ * available in Chrome, Safari, Opera, and IE. This event fires after
+ * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
+ *
+ * `beforeInput` is spec'd but not implemented in any browsers, and
+ * the `input` event does not provide any useful information about what has
+ * actually been added, contrary to the spec. Thus, `textInput` is the best
+ * available event to identify the characters that have actually been inserted
+ * into the target node.
+ *
+ * This plugin is also responsible for emitting `composition` events, thus
+ * allowing us to share composition fallback code for both `beforeInput` and
+ * `composition` event types.
+ */
+var BeforeInputEventPlugin = {
+ eventTypes: eventTypes,
+
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];
+ }
+};
+
+// Use to restore controlled state after a change event has fired.
+
+var fiberHostComponent = null;
+
+var ReactControlledComponentInjection = {
+ injectFiberControlledHostComponent: function (hostComponentImpl) {
+ // The fiber implementation doesn't use dynamic dispatch so we need to
+ // inject the implementation.
+ fiberHostComponent = hostComponentImpl;
+ }
+};
+
+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;
+ }
+ !(fiberHostComponent && typeof fiberHostComponent.restoreControlledState === 'function') ? invariant_1(false, '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.') : void 0;
+ var props = getFiberCurrentPropsFromNode(internalInstance.stateNode);
+ fiberHostComponent.restoreControlledState(internalInstance.stateNode, internalInstance.type, props);
+}
+
+var injection$3 = ReactControlledComponentInjection;
+
+function enqueueStateRestore(target) {
+ if (restoreTarget) {
+ if (restoreQueue) {
+ restoreQueue.push(target);
+ } else {
+ restoreQueue = [target];
+ }
+ } else {
+ restoreTarget = target;
+ }
+}
+
+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]);
+ }
+ }
+}
+
+var ReactControlledComponent = Object.freeze({
+ injection: injection$3,
+ enqueueStateRestore: enqueueStateRestore,
+ restoreStateIfNeeded: restoreStateIfNeeded
+});
+
+// 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 fiberBatchedUpdates = function (fn, bookkeeping) {
+ return fn(bookkeeping);
+};
+
+var isNestingBatched = false;
+function batchedUpdates(fn, bookkeeping) {
+ if (isNestingBatched) {
+ // If we are currently inside another batch, we need to wait until it
+ // fully completes before restoring state. Therefore, we add the target to
+ // a queue of work.
+ return fiberBatchedUpdates(fn, bookkeeping);
+ }
+ isNestingBatched = true;
+ try {
+ return fiberBatchedUpdates(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.
+ isNestingBatched = false;
+ restoreStateIfNeeded();
+ }
+}
+
+var ReactGenericBatchingInjection = {
+ injectFiberBatchedUpdates: function (_batchedUpdates) {
+ fiberBatchedUpdates = _batchedUpdates;
+ }
+};
+
+var injection$4 = ReactGenericBatchingInjection;
+
+/**
+ * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
+ */
+var supportedInputTypes = {
+ color: true,
+ date: true,
+ datetime: true,
+ 'datetime-local': true,
+ email: true,
+ month: true,
+ number: true,
+ password: true,
+ range: true,
+ search: true,
+ tel: true,
+ text: true,
+ time: true,
+ url: true,
+ week: true
+};
+
+function isTextInputElement(elem) {
+ var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
+
+ if (nodeName === 'input') {
+ return !!supportedInputTypes[elem.type];
+ }
+
+ if (nodeName === 'textarea') {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * HTML nodeType values that represent the type of the node
+ */
+
+var ELEMENT_NODE = 1;
+var TEXT_NODE = 3;
+var COMMENT_NODE = 8;
+var DOCUMENT_NODE = 9;
+var DOCUMENT_FRAGMENT_NODE = 11;
+
+/**
+ * Gets the target node from a native browser event by accounting for
+ * inconsistencies in browser DOM APIs.
+ *
+ * @param {object} nativeEvent Native browser event.
+ * @return {DOMEventTarget} Target node.
+ */
+function getEventTarget(nativeEvent) {
+ var target = nativeEvent.target || nativeEvent.srcElement || window;
+
+ // Normalize SVG <use> element events #4963
+ if (target.correspondingUseElement) {
+ target = target.correspondingUseElement;
+ }
+
+ // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
+ // @see http://www.quirksmode.org/js/events_properties.html
+ return target.nodeType === TEXT_NODE ? target.parentNode : target;
+}
+
+var useHasFeature;
+if (ExecutionEnvironment_1.canUseDOM) {
+ useHasFeature = document.implementation && document.implementation.hasFeature &&
+ // always returns true in newer browsers as per the standard.
+ // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
+ document.implementation.hasFeature('', '') !== true;
+}
+
+/**
+ * Checks if an event is supported in the current execution environment.
+ *
+ * NOTE: This will not work correctly for non-generic events such as `change`,
+ * `reset`, `load`, `error`, and `select`.
+ *
+ * Borrows from Modernizr.
+ *
+ * @param {string} eventNameSuffix Event name, e.g. "click".
+ * @param {?boolean} capture Check if the capture phase is supported.
+ * @return {boolean} True if the event is supported.
+ * @internal
+ * @license Modernizr 3.0.0pre (Custom Build) | MIT
+ */
+function isEventSupported(eventNameSuffix, capture) {
+ if (!ExecutionEnvironment_1.canUseDOM || capture && !('addEventListener' in document)) {
+ return false;
+ }
+
+ var eventName = 'on' + eventNameSuffix;
+ var isSupported = eventName in document;
+
+ if (!isSupported) {
+ var element = document.createElement('div');
+ element.setAttribute(eventName, 'return;');
+ isSupported = typeof element[eventName] === 'function';
+ }
+
+ if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {
+ // This is the only way to test support for the `wheel` event in IE9+.
+ isSupported = document.implementation.hasFeature('Events.wheel', '3.0');
+ }
+
+ return isSupported;
+}
+
+function isCheckable(elem) {
+ var type = elem.type;
+ var nodeName = elem.nodeName;
+ return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
+}
+
+function getTracker(node) {
+ return node._valueTracker;
+}
+
+function detachTracker(node) {
+ node._valueTracker = null;
+}
+
+function getValueFromNode(node) {
+ var value = '';
+ if (!node) {
+ return value;
+ }
+
+ if (isCheckable(node)) {
+ value = node.checked ? 'true' : 'false';
+ } else {
+ value = node.value;
+ }
+
+ return value;
+}
+
+function trackValueOnNode(node) {
+ var valueField = isCheckable(node) ? 'checked' : 'value';
+ var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);
+
+ var currentValue = '' + node[valueField];
+
+ // if someone has already defined a value or Safari, then bail
+ // and don't track value will cause over reporting of changes,
+ // but it's better then a hard failure
+ // (needed for certain tests that spyOn input values and Safari)
+ if (node.hasOwnProperty(valueField) || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
+ return;
+ }
+
+ Object.defineProperty(node, valueField, {
+ enumerable: descriptor.enumerable,
+ configurable: true,
+ get: function () {
+ return descriptor.get.call(this);
+ },
+ set: function (value) {
+ currentValue = '' + value;
+ descriptor.set.call(this, value);
+ }
+ });
+
+ var tracker = {
+ getValue: function () {
+ return currentValue;
+ },
+ setValue: function (value) {
+ currentValue = '' + value;
+ },
+ stopTracking: function () {
+ detachTracker(node);
+ delete node[valueField];
}
};
+ return tracker;
+}
+
+function track(node) {
+ if (getTracker(node)) {
+ return;
+ }
+
+ // TODO: Once it's just Fiber we can move this to node._wrapperState
+ node._valueTracker = trackValueOnNode(node);
}
-var warning_1 = warning$2;
+function updateValueIfChanged(node) {
+ if (!node) {
+ return false;
+ }
+ var tracker = getTracker(node);
+ // if there is no tracker at this point it's unlikely
+ // that trying again will succeed
+ if (!tracker) {
+ return true;
+ }
+
+ var lastValue = tracker.getValue();
+ var nextValue = getValueFromNode(node);
+ if (nextValue !== lastValue) {
+ tracker.setValue(nextValue);
+ return true;
+ }
+ return false;
+}
+
+var eventTypes$1 = {
+ change: {
+ phasedRegistrationNames: {
+ bubbled: 'onChange',
+ captured: 'onChangeCapture'
+ },
+ dependencies: ['topBlur', 'topChange', 'topClick', 'topFocus', 'topInput', 'topKeyDown', 'topKeyUp', 'topSelectionChange']
+ }
+};
+
+function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
+ var event = SyntheticEvent$1.getPooled(eventTypes$1.change, inst, nativeEvent, target);
+ event.type = 'change';
+ // Flag this event loop as needing state restore.
+ enqueueStateRestore(target);
+ accumulateTwoPhaseDispatches(event);
+ return event;
+}
/**
- * Copyright (c) 2013-present, Facebook, Inc.
+ * For IE shims
+ */
+var activeElement = null;
+var activeElementInst = null;
+
+/**
+ * SECTION: handle `change` event
+ */
+function shouldUseChangeEvent(elem) {
+ var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
+ return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
+}
+
+function manualDispatchChangeEvent(nativeEvent) {
+ var event = createAndAccumulateChangeEvent(activeElementInst, nativeEvent, getEventTarget(nativeEvent));
+
+ // If change and propertychange bubbled, we'd just bind to it like all the
+ // other events and have it go through ReactBrowserEventEmitter. Since it
+ // doesn't, we manually listen for the events and so we have to enqueue and
+ // process the abstract event manually.
+ //
+ // Batching is necessary here in order to ensure that all event handlers run
+ // before the next rerender (including event handlers attached to ancestor
+ // elements instead of directly on the input). Without this, controlled
+ // components don't work properly in conjunction with event bubbling because
+ // the component is rerendered and the value reverted before all the event
+ // handlers can run. See https://github.com/facebook/react/issues/708.
+ batchedUpdates(runEventInBatch, event);
+}
+
+function runEventInBatch(event) {
+ enqueueEvents(event);
+ processEventQueue(false);
+}
+
+function getInstIfValueChanged(targetInst) {
+ var targetNode = getNodeFromInstance$1(targetInst);
+ if (updateValueIfChanged(targetNode)) {
+ return targetInst;
+ }
+}
+
+function getTargetInstForChangeEvent(topLevelType, targetInst) {
+ if (topLevelType === 'topChange') {
+ return targetInst;
+ }
+}
+
+/**
+ * SECTION: handle `input` event
+ */
+var isInputEventSupported = false;
+if (ExecutionEnvironment_1.canUseDOM) {
+ // IE9 claims to support the input event but fails to trigger it when
+ // deleting text, so we ignore its input events.
+ isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9);
+}
+
+/**
+ * (For IE <=9) Starts tracking propertychange events on the passed-in element
+ * and override the value property so that we can distinguish user events from
+ * value changes in JS.
+ */
+function startWatchingForValueChange(target, targetInst) {
+ activeElement = target;
+ activeElementInst = targetInst;
+ activeElement.attachEvent('onpropertychange', handlePropertyChange);
+}
+
+/**
+ * (For IE <=9) Removes the event listeners from the currently-tracked element,
+ * if any exists.
+ */
+function stopWatchingForValueChange() {
+ if (!activeElement) {
+ return;
+ }
+ activeElement.detachEvent('onpropertychange', handlePropertyChange);
+ activeElement = null;
+ activeElementInst = null;
+}
+
+/**
+ * (For IE <=9) Handles a propertychange event, sending a `change` event if
+ * the value of the active element has changed.
+ */
+function handlePropertyChange(nativeEvent) {
+ if (nativeEvent.propertyName !== 'value') {
+ return;
+ }
+ if (getInstIfValueChanged(activeElementInst)) {
+ manualDispatchChangeEvent(nativeEvent);
+ }
+}
+
+function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) {
+ if (topLevelType === 'topFocus') {
+ // In IE9, propertychange fires for most input events but is buggy and
+ // doesn't fire when text is deleted, but conveniently, selectionchange
+ // appears to fire in all of the remaining cases so we catch those and
+ // forward the event if the value has changed
+ // In either case, we don't want to call the event handler if the value
+ // is changed from JS so we redefine a setter for `.value` that updates
+ // our activeElementValue variable, allowing us to ignore those changes
+ //
+ // stopWatching() should be a noop here but we call it just in case we
+ // missed a blur event somehow.
+ stopWatchingForValueChange();
+ startWatchingForValueChange(target, targetInst);
+ } else if (topLevelType === 'topBlur') {
+ stopWatchingForValueChange();
+ }
+}
+
+// For IE8 and IE9.
+function getTargetInstForInputEventPolyfill(topLevelType, targetInst) {
+ if (topLevelType === 'topSelectionChange' || topLevelType === 'topKeyUp' || topLevelType === 'topKeyDown') {
+ // On the selectionchange event, the target is just document which isn't
+ // helpful for us so just check activeElement instead.
+ //
+ // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
+ // propertychange on the first input event after setting `value` from a
+ // script and fires only keydown, keypress, keyup. Catching keyup usually
+ // gets it and catching keydown lets us fire an event for the first
+ // keystroke if user does a key repeat (it'll be a little delayed: right
+ // before the second keystroke). Other input methods (e.g., paste) seem to
+ // fire selectionchange normally.
+ return getInstIfValueChanged(activeElementInst);
+ }
+}
+
+/**
+ * SECTION: handle `click` event
+ */
+function shouldUseClickEvent(elem) {
+ // Use the `click` event to detect changes to checkbox and radio inputs.
+ // This approach works across all browsers, whereas `change` does not fire
+ // until `blur` in IE8.
+ var nodeName = elem.nodeName;
+ return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
+}
+
+function getTargetInstForClickEvent(topLevelType, targetInst) {
+ if (topLevelType === 'topClick') {
+ return getInstIfValueChanged(targetInst);
+ }
+}
+
+function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) {
+ if (topLevelType === 'topInput' || topLevelType === 'topChange') {
+ return getInstIfValueChanged(targetInst);
+ }
+}
+
+function handleControlledInputBlur(inst, node) {
+ // TODO: In IE, inst is occasionally null. Why?
+ if (inst == null) {
+ return;
+ }
+
+ // Fiber and ReactDOM keep wrapper state in separate places
+ var state = inst._wrapperState || node._wrapperState;
+
+ if (!state || !state.controlled || node.type !== 'number') {
+ return;
+ }
+
+ // If controlled, assign the value attribute to the current value on blur
+ var value = '' + node.value;
+ if (node.getAttribute('value') !== value) {
+ node.setAttribute('value', value);
+ }
+}
+
+/**
+ * This plugin creates an `onChange` event that normalizes change events
+ * across form elements. This event fires at a time when it's possible to
+ * change the element's value without seeing a flicker.
*
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
+ * Supported elements are:
+ * - input (see `isTextInputElement`)
+ * - textarea
+ * - select
+ */
+var ChangeEventPlugin = {
+ eventTypes: eventTypes$1,
+
+ _isInputEventSupported: isInputEventSupported,
+
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
+
+ var getTargetInstFunc, handleEventFunc;
+ if (shouldUseChangeEvent(targetNode)) {
+ getTargetInstFunc = getTargetInstForChangeEvent;
+ } else if (isTextInputElement(targetNode)) {
+ if (isInputEventSupported) {
+ getTargetInstFunc = getTargetInstForInputOrChangeEvent;
+ } else {
+ getTargetInstFunc = getTargetInstForInputEventPolyfill;
+ handleEventFunc = handleEventsForInputEventPolyfill;
+ }
+ } else if (shouldUseClickEvent(targetNode)) {
+ getTargetInstFunc = getTargetInstForClickEvent;
+ }
+
+ if (getTargetInstFunc) {
+ var inst = getTargetInstFunc(topLevelType, targetInst);
+ if (inst) {
+ var event = createAndAccumulateChangeEvent(inst, nativeEvent, nativeEventTarget);
+ return event;
+ }
+ }
+
+ if (handleEventFunc) {
+ handleEventFunc(topLevelType, targetNode, targetInst);
+ }
+
+ // When blurring, set the value attribute for number inputs
+ if (topLevelType === 'topBlur') {
+ handleControlledInputBlur(targetInst, targetNode);
+ }
+ }
+};
+
+/**
+ * Module that is injectable into `EventPluginHub`, that specifies a
+ * deterministic ordering of `EventPlugin`s. A convenient way to reason about
+ * plugins, without having to package every one of them. This is better than
+ * having plugins be ordered in the same order that they are injected because
+ * that ordering would be influenced by the packaging order.
+ * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
+ * preventing default on events is convenient in `SimpleEventPlugin` handlers.
+ */
+var DOMEventPluginOrder = ['ResponderEventPlugin', 'SimpleEventPlugin', 'TapEventPlugin', 'EnterLeaveEventPlugin', 'ChangeEventPlugin', 'SelectEventPlugin', 'BeforeInputEventPlugin'];
+
+/**
+ * @interface UIEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var UIEventInterface = {
+ view: null,
+ detail: null
+};
+
+/**
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticEvent}
+ */
+function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+}
+
+SyntheticEvent$1.augmentClass(SyntheticUIEvent, UIEventInterface);
+
+/**
+ * Translation from modifier key to the associated property in the event.
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
+ */
+
+var modifierKeyToProp = {
+ Alt: 'altKey',
+ Control: 'ctrlKey',
+ Meta: 'metaKey',
+ Shift: 'shiftKey'
+};
+
+// IE8 does not implement getModifierState so we simply map it to the only
+// modifier keys exposed by the event itself, does not support Lock-keys.
+// Currently, all major browsers except Chrome seems to support Lock-keys.
+function modifierStateGetter(keyArg) {
+ var syntheticEvent = this;
+ var nativeEvent = syntheticEvent.nativeEvent;
+ if (nativeEvent.getModifierState) {
+ return nativeEvent.getModifierState(keyArg);
+ }
+ var keyProp = modifierKeyToProp[keyArg];
+ return keyProp ? !!nativeEvent[keyProp] : false;
+}
+
+function getEventModifierState(nativeEvent) {
+ return modifierStateGetter;
+}
+
+/**
+ * @interface MouseEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var MouseEventInterface = {
+ screenX: null,
+ screenY: null,
+ clientX: null,
+ clientY: null,
+ pageX: null,
+ pageY: null,
+ ctrlKey: null,
+ shiftKey: null,
+ altKey: null,
+ metaKey: null,
+ getModifierState: getEventModifierState,
+ button: null,
+ buttons: null,
+ relatedTarget: function (event) {
+ return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);
+ }
+};
+
+/**
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticUIEvent}
+ */
+function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+}
+
+SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);
+
+var eventTypes$2 = {
+ mouseEnter: {
+ registrationName: 'onMouseEnter',
+ dependencies: ['topMouseOut', 'topMouseOver']
+ },
+ mouseLeave: {
+ registrationName: 'onMouseLeave',
+ dependencies: ['topMouseOut', 'topMouseOver']
+ }
+};
+
+var EnterLeaveEventPlugin = {
+ eventTypes: eventTypes$2,
+
+ /**
+ * For almost every interaction we care about, there will be both a top-level
+ * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
+ * we do not extract duplicate events. However, moving the mouse into the
+ * browser from outside will not fire a `mouseout` event. In this case, we use
+ * the `mouseover` top-level event.
+ */
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
+ return null;
+ }
+ if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') {
+ // Must not be a mouse in or mouse out - ignoring.
+ return null;
+ }
+
+ var win;
+ if (nativeEventTarget.window === nativeEventTarget) {
+ // `nativeEventTarget` is probably a window object.
+ win = nativeEventTarget;
+ } else {
+ // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
+ var doc = nativeEventTarget.ownerDocument;
+ if (doc) {
+ win = doc.defaultView || doc.parentWindow;
+ } else {
+ win = window;
+ }
+ }
+
+ var from;
+ var to;
+ if (topLevelType === 'topMouseOut') {
+ from = targetInst;
+ var related = nativeEvent.relatedTarget || nativeEvent.toElement;
+ to = related ? getClosestInstanceFromNode(related) : null;
+ } else {
+ // Moving to a node from outside the window.
+ from = null;
+ to = targetInst;
+ }
+
+ if (from === to) {
+ // Nothing pertains to our managed components.
+ return null;
+ }
+
+ var fromNode = from == null ? win : getNodeFromInstance$1(from);
+ var toNode = to == null ? win : getNodeFromInstance$1(to);
+
+ var leave = SyntheticMouseEvent.getPooled(eventTypes$2.mouseLeave, from, nativeEvent, nativeEventTarget);
+ leave.type = 'mouseleave';
+ leave.target = fromNode;
+ leave.relatedTarget = toNode;
+
+ var enter = SyntheticMouseEvent.getPooled(eventTypes$2.mouseEnter, to, nativeEvent, nativeEventTarget);
+ enter.type = 'mouseenter';
+ enter.target = toNode;
+ enter.relatedTarget = fromNode;
+
+ accumulateEnterLeaveDispatches(leave, enter, from, to);
+
+ return [leave, enter];
+ }
+};
+
+/**
+ * `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.
*
- * @providesModule ReactTypeOfSideEffect
- *
+ * Note that this module is currently shared and assumed to be stateless.
+ * If this becomes an actual Map, that will break.
*/
-var ReactTypeOfSideEffect = {
- // Don't change these two values:
- NoEffect: 0, // 0b00000000
- PerformedWork: 1, // 0b00000001
- // You can change the rest (and add more).
- Placement: 2, // 0b00000010
- Update: 4, // 0b00000100
- PlacementAndUpdate: 6, // 0b00000110
- Deletion: 8, // 0b00001000
- ContentReset: 16, // 0b00010000
- Callback: 32, // 0b00100000
- Err: 64, // 0b01000000
- Ref: 128 };
+/**
+ * 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.
+ */
-var ReactCurrentOwner = ReactGlobalSharedState_1.ReactCurrentOwner;
+function get(key) {
+ return key._reactInternalFiber;
+}
+function has(key) {
+ return key._reactInternalFiber !== undefined;
+}
+function set(key, value) {
+ key._reactInternalFiber = value;
+}
-{
- var warning$1 = warning_1;
+var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
+
+var ReactCurrentOwner = ReactInternals$1.ReactCurrentOwner;
+var ReactDebugCurrentFrame = ReactInternals$1.ReactDebugCurrentFrame;
+
+function getComponentName(fiber) {
+ var type = fiber.type;
+
+ if (typeof type === 'string') {
+ return type;
+ }
+ if (typeof type === 'function') {
+ return type.displayName || type.name;
+ }
+ return null;
}
-var ClassComponent = ReactTypeOfWork.ClassComponent;
-var HostComponent$1 = ReactTypeOfWork.HostComponent;
-var HostRoot$1 = ReactTypeOfWork.HostRoot;
-var HostPortal = ReactTypeOfWork.HostPortal;
-var HostText$1 = ReactTypeOfWork.HostText;
+// Don't change these two values:
+var NoEffect = 0; // 0b00000000
+var PerformedWork = 1; // 0b00000001
-var NoEffect = ReactTypeOfSideEffect.NoEffect;
-var Placement = ReactTypeOfSideEffect.Placement;
+// You can change the rest (and add more).
+var Placement = 2; // 0b00000010
+var Update = 4; // 0b00000100
+var PlacementAndUpdate = 6; // 0b00000110
+var Deletion = 8; // 0b00001000
+var ContentReset = 16; // 0b00010000
+var Callback = 32; // 0b00100000
+var Err = 64; // 0b01000000
+var Ref = 128; // 0b10000000
var MOUNTING = 1;
var MOUNTED = 2;
@@ -1168,7 +3232,7 @@ function isFiberMountedImpl(fiber) {
node = node['return'];
}
}
- if (node.tag === HostRoot$1) {
+ if (node.tag === HostRoot) {
// TODO: Check if this was a nested HostRoot when used with
// renderContainerIntoSubtree.
return MOUNTED;
@@ -1177,27 +3241,28 @@ function isFiberMountedImpl(fiber) {
// that has been unmounted.
return UNMOUNTED;
}
-var isFiberMounted = function (fiber) {
+
+function isFiberMounted(fiber) {
return isFiberMountedImpl(fiber) === MOUNTED;
-};
+}
-var isMounted = function (component) {
+function isMounted(component) {
{
var owner = ReactCurrentOwner.current;
if (owner !== null && owner.tag === ClassComponent) {
var ownerFiber = owner;
var instance = ownerFiber.stateNode;
- warning$1(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_1(ownerFiber) || 'A component');
+ warning_1(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 = ReactInstanceMap_1.get(component);
+ var fiber = get(component);
if (!fiber) {
return false;
}
return isFiberMountedImpl(fiber) === MOUNTED;
-};
+}
function assertIsMounted(fiber) {
!(isFiberMountedImpl(fiber) === MOUNTED) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
@@ -1306,7 +3371,7 @@ function findCurrentFiberUsingSlowPath(fiber) {
}
// If the root is not a host container, we're in a disconnected tree. I.e.
// unmounted.
- !(a.tag === HostRoot$1) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
+ !(a.tag === HostRoot) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
if (a.stateNode.current === a) {
// We've determined that A is the current branch.
return fiber;
@@ -1314,9 +3379,8 @@ function findCurrentFiberUsingSlowPath(fiber) {
// Otherwise B has to be current branch.
return alternate;
}
-var findCurrentFiberUsingSlowPath_1 = findCurrentFiberUsingSlowPath;
-var findCurrentHostFiber = function (parent) {
+function findCurrentHostFiber(parent) {
var currentParent = findCurrentFiberUsingSlowPath(parent);
if (!currentParent) {
return null;
@@ -1325,7 +3389,7 @@ var findCurrentHostFiber = function (parent) {
// Next we'll drill down this component to find the first HostComponent/Text.
var node = currentParent;
while (true) {
- if (node.tag === HostComponent$1 || node.tag === HostText$1) {
+ if (node.tag === HostComponent || node.tag === HostText) {
return node;
} else if (node.child) {
node.child['return'] = node;
@@ -1347,9 +3411,9 @@ var findCurrentHostFiber = function (parent) {
// Flow needs the return null here, but ESLint complains about it.
// eslint-disable-next-line no-unreachable
return null;
-};
+}
-var findCurrentHostFiberWithNoPortals = function (parent) {
+function findCurrentHostFiberWithNoPortals(parent) {
var currentParent = findCurrentFiberUsingSlowPath(parent);
if (!currentParent) {
return null;
@@ -1358,7 +3422,7 @@ var findCurrentHostFiberWithNoPortals = function (parent) {
// Next we'll drill down this component to find the first HostComponent/Text.
var node = currentParent;
while (true) {
- if (node.tag === HostComponent$1 || node.tag === HostText$1) {
+ if (node.tag === HostComponent || node.tag === HostText) {
return node;
} else if (node.child && node.tag !== HostPortal) {
node.child['return'] = node;
@@ -1380,570 +3444,80 @@ var findCurrentHostFiberWithNoPortals = function (parent) {
// Flow needs the return null here, but ESLint complains about it.
// eslint-disable-next-line no-unreachable
return null;
-};
-
-var ReactFiberTreeReflection = {
- isFiberMounted: isFiberMounted,
- isMounted: isMounted,
- findCurrentFiberUsingSlowPath: findCurrentFiberUsingSlowPath_1,
- findCurrentHostFiber: findCurrentHostFiber,
- findCurrentHostFiberWithNoPortals: findCurrentHostFiberWithNoPortals
-};
-
-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,
+/**
+ * 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.
+ *
+ * @typechecks
+ */
- injection: {
- injectErrorUtils: function (injectedErrorUtils) {
- !(typeof injectedErrorUtils.invokeGuardedCallback === 'function') ? invariant_1(false, 'Injected invokeGuardedCallback() must be a function.') : void 0;
- invokeGuardedCallback = injectedErrorUtils.invokeGuardedCallback;
- }
- },
- /**
- * 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.apply(ReactErrorUtils, arguments);
- },
+/**
+ * Upstream version of event listener. Does not take into account specific
+ * nature of platform.
+ */
+var EventListener = {
/**
- * 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.
+ * Listen to DOM events during the bubble phase.
*
- * @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
+ * @param {DOMEventTarget} target DOM element to register listener on.
+ * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
+ * @param {function} callback Callback function.
+ * @return {object} Object with a `remove` method.
*/
- 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;
- }
+ listen: function listen(target, eventType, callback) {
+ if (target.addEventListener) {
+ target.addEventListener(eventType, callback, false);
+ return {
+ remove: function remove() {
+ target.removeEventListener(eventType, callback, false);
+ }
+ };
+ } else if (target.attachEvent) {
+ target.attachEvent('on' + eventType, callback);
+ return {
+ remove: function remove() {
+ target.detachEvent('on' + eventType, callback);
+ }
+ };
}
},
/**
- * During execution of guarded functions we will capture the first error which
- * we will rethrow to be handled by the top level error handler.
+ * Listen to DOM events during the capture phase.
+ *
+ * @param {DOMEventTarget} target DOM element to register listener on.
+ * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.
+ * @param {function} callback Callback function.
+ * @return {object} Object with a `remove` method.
*/
- 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_1(false, 'clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.');
- }
- }
-};
-
-var invokeGuardedCallback = function (name, func, context, a, b, c, d, e, f) {
- ReactErrorUtils._hasCaughtError = false;
- ReactErrorUtils._caughtError = null;
- var funcArgs = Array.prototype.slice.call(arguments, 3);
- try {
- func.apply(context, funcArgs);
- } catch (error) {
- ReactErrorUtils._caughtError = error;
- ReactErrorUtils._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) {
- // 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.
- var evt = document.createEvent('Event');
- 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.');
+ capture: function capture(target, eventType, callback) {
+ if (target.addEventListener) {
+ target.addEventListener(eventType, callback, true);
+ return {
+ remove: function remove() {
+ target.removeEventListener(eventType, callback, true);
}
- ReactErrorUtils._hasCaughtError = true;
- ReactErrorUtils._caughtError = error;
- } else {
- ReactErrorUtils._hasCaughtError = false;
- ReactErrorUtils._caughtError = null;
- }
-
- // Remove our event listeners
- window.removeEventListener('error', onError);
- };
-
- invokeGuardedCallback = invokeGuardedCallbackDev;
- }
-}
-
-var rethrowCaughtError = function () {
- if (ReactErrorUtils._hasRethrowError) {
- var error = ReactErrorUtils._rethrowError;
- ReactErrorUtils._rethrowError = null;
- ReactErrorUtils._hasRethrowError = false;
- throw error;
- }
-};
-
-var ReactErrorUtils_1 = ReactErrorUtils;
-
-{
- var warning$3 = warning_1;
-}
-
-/**
- * Injected dependencies:
- */
-
-/**
- * - `ComponentTree`: [required] Module that can convert between React instances
- * and actual node references.
- */
-var ComponentTree;
-var injection = {
- injectComponentTree: function (Injected) {
- ComponentTree = Injected;
- {
- warning$3(Injected && Injected.getNodeFromInstance && Injected.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;
-{
- 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$3(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 = EventPluginUtils.getNodeFromInstance(inst);
- ReactErrorUtils_1.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;
- !!Array.isArray(dispatchListener) ? invariant_1(false, 'executeDirectDispatch(...): Invalid `event`.') : void 0;
- event.currentTarget = dispatchListener ? EventPluginUtils.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;
-}
-
-/**
- * General utilities that are useful in creating custom Event Plugins.
- */
-var EventPluginUtils = {
- isEndish: isEndish,
- isMoveish: isMoveish,
- isStartish: isStartish,
-
- executeDirectDispatch: executeDirectDispatch,
- executeDispatchesInOrder: executeDispatchesInOrder,
- executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
- hasDispatches: hasDispatches,
-
- getFiberCurrentPropsFromNode: function (node) {
- return ComponentTree.getFiberCurrentPropsFromNode(node);
- },
- getInstanceFromNode: function (node) {
- return ComponentTree.getInstanceFromNode(node);
- },
- getNodeFromInstance: function (node) {
- return ComponentTree.getNodeFromInstance(node);
- },
-
- injection: injection
-};
-
-var EventPluginUtils_1 = EventPluginUtils;
-
-// Use to restore controlled state after a change event has fired.
-
-var fiberHostComponent = null;
-
-var ReactControlledComponentInjection = {
- injectFiberControlledHostComponent: function (hostComponentImpl) {
- // The fiber implementation doesn't use dynamic dispatch so we need to
- // inject the implementation.
- fiberHostComponent = hostComponentImpl;
- }
-};
-
-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 = EventPluginUtils_1.getInstanceFromNode(target);
- if (!internalInstance) {
- // Unmounted
- return;
- }
- if (typeof internalInstance.tag === 'number') {
- !(fiberHostComponent && typeof fiberHostComponent.restoreControlledState === 'function') ? invariant_1(false, '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.') : void 0;
- var props = EventPluginUtils_1.getFiberCurrentPropsFromNode(internalInstance.stateNode);
- fiberHostComponent.restoreControlledState(internalInstance.stateNode, internalInstance.type, props);
- return;
- }
- !(typeof internalInstance.restoreControlledState === 'function') ? invariant_1(false, 'The internal instance must be a React host component. This error is likely caused by a bug in React. Please file an issue.') : void 0;
- // If it is not a Fiber, we can just use dynamic dispatch.
- internalInstance.restoreControlledState();
-}
-
-var ReactControlledComponent = {
- injection: ReactControlledComponentInjection,
-
- enqueueStateRestore: function (target) {
- if (restoreTarget) {
- if (restoreQueue) {
- restoreQueue.push(target);
- } else {
- restoreQueue = [target];
- }
+ };
} else {
- restoreTarget = target;
- }
- },
- restoreStateIfNeeded: function () {
- 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]);
+ {
+ console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');
}
+ return {
+ remove: emptyFunction_1
+ };
}
- }
-};
-
-var ReactControlledComponent_1 = ReactControlledComponent;
-
-// Used as a way to call batchedUpdates when we don't know if we're in a Fiber
-// or Stack context. 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 stackBatchedUpdates = function (fn, a, b, c, d, e) {
- return fn(a, b, c, d, e);
-};
-var fiberBatchedUpdates = function (fn, bookkeeping) {
- return fn(bookkeeping);
-};
-
-function performFiberBatchedUpdates(fn, bookkeeping) {
- // If we have Fiber loaded, we need to wrap this in a batching call so that
- // Fiber can apply its default priority for this call.
- return fiberBatchedUpdates(fn, bookkeeping);
-}
-function batchedUpdates(fn, bookkeeping) {
- // We first perform work with the stack batching strategy, by passing our
- // indirection to it.
- return stackBatchedUpdates(performFiberBatchedUpdates, fn, bookkeeping);
-}
-
-var isNestingBatched = false;
-function batchedUpdatesWithControlledComponents(fn, bookkeeping) {
- if (isNestingBatched) {
- // If we are currently inside another batch, we need to wait until it
- // fully completes before restoring state. Therefore, we add the target to
- // a queue of work.
- return batchedUpdates(fn, bookkeeping);
- }
- isNestingBatched = 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.
- isNestingBatched = false;
- ReactControlledComponent_1.restoreStateIfNeeded();
- }
-}
-
-var ReactGenericBatchingInjection = {
- injectStackBatchedUpdates: function (_batchedUpdates) {
- stackBatchedUpdates = _batchedUpdates;
},
- injectFiberBatchedUpdates: function (_batchedUpdates) {
- fiberBatchedUpdates = _batchedUpdates;
- }
-};
-var ReactGenericBatching = {
- batchedUpdates: batchedUpdatesWithControlledComponents,
- injection: ReactGenericBatchingInjection
+ registerDefault: function registerDefault() {}
};
-var ReactGenericBatching_1 = ReactGenericBatching;
-
-var TEXT_NODE$1 = HTMLNodeType_1.TEXT_NODE;
-
-/**
- * Gets the target node from a native browser event by accounting for
- * inconsistencies in browser DOM APIs.
- *
- * @param {object} nativeEvent Native browser event.
- * @return {DOMEventTarget} Target node.
- */
-
-
-function getEventTarget(nativeEvent) {
- var target = nativeEvent.target || nativeEvent.srcElement || window;
-
- // Normalize SVG <use> element events #4963
- if (target.correspondingUseElement) {
- target = target.correspondingUseElement;
- }
-
- // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
- // @see http://www.quirksmode.org/js/events_properties.html
- return target.nodeType === TEXT_NODE$1 ? target.parentNode : target;
-}
-
-var getEventTarget_1 = getEventTarget;
-
-var HostRoot = ReactTypeOfWork.HostRoot;
-
+var EventListener_1 = EventListener;
var CALLBACK_BOOKKEEPING_POOL_SIZE = 10;
var callbackBookkeepingPool = [];
@@ -1957,22 +3531,14 @@ function findRootContainerNode(inst) {
// TODO: It may be a good idea to cache this to prevent unnecessary DOM
// traversal, but caching is difficult to do correctly without using a
// mutation observer to listen for all DOM changes.
- if (typeof inst.tag === 'number') {
- while (inst['return']) {
- inst = inst['return'];
- }
- if (inst.tag !== HostRoot) {
- // This can happen if we're in a detached tree.
- return null;
- }
- return inst.stateNode.containerInfo;
- } else {
- while (inst._hostParent) {
- inst = inst._hostParent;
- }
- var rootNode = ReactDOMComponentTree_1.getNodeFromInstance(inst);
- return rootNode.parentNode;
+ while (inst['return']) {
+ inst = inst['return'];
+ }
+ if (inst.tag !== HostRoot) {
+ // This can happen if we're in a detached tree.
+ return null;
}
+ return inst.stateNode.containerInfo;
}
// Used to store ancestor hierarchy in top level callback
@@ -2020,423 +3586,101 @@ function handleTopLevelImpl(bookKeeping) {
break;
}
bookKeeping.ancestors.push(ancestor);
- ancestor = ReactDOMComponentTree_1.getClosestInstanceFromNode(root);
+ ancestor = getClosestInstanceFromNode(root);
} while (ancestor);
for (var i = 0; i < bookKeeping.ancestors.length; i++) {
targetInst = bookKeeping.ancestors[i];
- ReactDOMEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget_1(bookKeeping.nativeEvent));
+ _handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
}
}
-var ReactDOMEventListener = {
- _enabled: true,
- _handleTopLevel: null,
-
- setHandleTopLevel: function (handleTopLevel) {
- ReactDOMEventListener._handleTopLevel = handleTopLevel;
- },
-
- setEnabled: function (enabled) {
- ReactDOMEventListener._enabled = !!enabled;
- },
-
- isEnabled: function () {
- return ReactDOMEventListener._enabled;
- },
-
- /**
- * Traps top-level events by using event bubbling.
- *
- * @param {string} topLevelType Record from `BrowserEventConstants`.
- * @param {string} handlerBaseName Event name (e.g. "click").
- * @param {object} element Element on which to attach listener.
- * @return {?object} An object with a remove function which will forcefully
- * remove the listener.
- * @internal
- */
- trapBubbledEvent: function (topLevelType, handlerBaseName, element) {
- if (!element) {
- return null;
- }
- return EventListener_1.listen(element, handlerBaseName, ReactDOMEventListener.dispatchEvent.bind(null, topLevelType));
- },
-
- /**
- * Traps a top-level event by using event capturing.
- *
- * @param {string} topLevelType Record from `BrowserEventConstants`.
- * @param {string} handlerBaseName Event name (e.g. "click").
- * @param {object} element Element on which to attach listener.
- * @return {?object} An object with a remove function which will forcefully
- * remove the listener.
- * @internal
- */
- trapCapturedEvent: function (topLevelType, handlerBaseName, element) {
- if (!element) {
- return null;
- }
- return EventListener_1.capture(element, handlerBaseName, ReactDOMEventListener.dispatchEvent.bind(null, topLevelType));
- },
-
- dispatchEvent: function (topLevelType, nativeEvent) {
- if (!ReactDOMEventListener._enabled) {
- return;
- }
-
- var nativeEventTarget = getEventTarget_1(nativeEvent);
- var targetInst = ReactDOMComponentTree_1.getClosestInstanceFromNode(nativeEventTarget);
- if (targetInst !== null && typeof targetInst.tag === 'number' && !ReactFiberTreeReflection.isFiberMounted(targetInst)) {
- // If we get an event (ex: img onload) before committing that
- // component's mount, ignore it for now (that is, treat it as if it was an
- // event on a non-React tree). We might also consider queueing events and
- // dispatching them after the mount.
- targetInst = null;
- }
-
- var bookKeeping = getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst);
-
- try {
- // Event queue being processed in the same cycle allows
- // `preventDefault`.
- ReactGenericBatching_1.batchedUpdates(handleTopLevelImpl, bookKeeping);
- } finally {
- releaseTopLevelCallbackBookKeeping(bookKeeping);
- }
- }
-};
-
-var ReactDOMEventListener_1 = ReactDOMEventListener;
-
-/**
- * Accumulates items that must not be null or undefined into the first one. This
- * is used to conserve memory by avoiding array allocations, and thus sacrifices
- * API cleanness. Since `current` can be null before being passed in and not
- * null after this function, make sure to assign it back to `current`:
- *
- * `a = accumulateInto(a, b);`
- *
- * This API should be sparingly used. Try `accumulate` for something cleaner.
- *
- * @return {*|array<*>} An accumulation of items.
- */
-
-function accumulateInto(current, next) {
- !(next != null) ? invariant_1(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : void 0;
-
- if (current == null) {
- return next;
- }
-
- // Both are not empty. Warning: Never call x.concat(y) when you are not
- // certain that x is an Array (x could be a string with concat method).
- if (Array.isArray(current)) {
- if (Array.isArray(next)) {
- current.push.apply(current, next);
- return current;
- }
- current.push(next);
- return current;
- }
-
- if (Array.isArray(next)) {
- // A bit too dangerous to mutate `next`.
- return [current].concat(next);
- }
+// TODO: can we stop exporting these?
+var _enabled = true;
+var _handleTopLevel = void 0;
- return [current, next];
+function setHandleTopLevel(handleTopLevel) {
+ _handleTopLevel = handleTopLevel;
}
-var accumulateInto_1 = accumulateInto;
-
-/**
- * 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.
- *
- * @providesModule forEachAccumulated
- *
- */
-
-/**
- * @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);
- }
+function setEnabled(enabled) {
+ _enabled = !!enabled;
}
-var forEachAccumulated_1 = forEachAccumulated;
-
-/**
- * Internal queue of events that have accumulated their dispatches and are
- * waiting to have their dispatches executed.
- */
-var eventQueue = null;
+function isEnabled() {
+ return _enabled;
+}
/**
- * Dispatches an event and releases it back into the pool, unless persistent.
+ * Traps top-level events by using event bubbling.
*
- * @param {?object} event Synthetic event to be dispatched.
- * @param {boolean} simulated If the event is simulated (changes exn behavior)
- * @private
+ * @param {string} topLevelType Record from `BrowserEventConstants`.
+ * @param {string} handlerBaseName Event name (e.g. "click").
+ * @param {object} element Element on which to attach listener.
+ * @return {?object} An object with a remove function which will forcefully
+ * remove the listener.
+ * @internal
*/
-var executeDispatchesAndRelease = function (event, simulated) {
- if (event) {
- EventPluginUtils_1.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;
+function trapBubbledEvent(topLevelType, handlerBaseName, element) {
+ if (!element) {
+ return null;
}
+ return EventListener_1.listen(element, handlerBaseName, dispatchEvent.bind(null, topLevelType));
}
/**
- * 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.
+ * Traps a top-level event by using event capturing.
*
- * Each plugin that is injected into `EventsPluginHub` is immediately operable.
- *
- * @public
+ * @param {string} topLevelType Record from `BrowserEventConstants`.
+ * @param {string} handlerBaseName Event name (e.g. "click").
+ * @param {object} element Element on which to attach listener.
+ * @return {?object} An object with a remove function which will forcefully
+ * remove the listener.
+ * @internal
*/
-var EventPluginHub = {
- /**
- * Methods for injecting dependencies.
- */
- injection: {
- /**
- * @param {array} InjectedEventPluginOrder
- * @public
- */
- injectEventPluginOrder: EventPluginRegistry_1.injectEventPluginOrder,
-
- /**
- * @param {object} injectedNamesToPlugins Map from names to plugin modules.
- */
- injectEventPluginsByName: EventPluginRegistry_1.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.
- */
- getListener: function (inst, registrationName) {
- var listener;
-
- // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
- // live here; needs to be moved to a better place soon
- if (typeof inst.tag === 'number') {
- var stateNode = inst.stateNode;
- if (!stateNode) {
- // Work in progress (ex: onload events in incremental mode).
- return null;
- }
- var props = EventPluginUtils_1.getFiberCurrentPropsFromNode(stateNode);
- if (!props) {
- // Work in progress.
- return null;
- }
- listener = props[registrationName];
- if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
- return null;
- }
- } else {
- var currentElement = inst._currentElement;
- if (typeof currentElement === 'string' || typeof currentElement === 'number') {
- // Text node, let it bubble through.
- return null;
- }
- if (!inst._rootNodeID) {
- // If the instance is already unmounted, we have no listeners.
- return null;
- }
- var _props = currentElement.props;
- listener = _props[registrationName];
- if (shouldPreventMouseEvent(registrationName, currentElement.type, _props)) {
- return null;
- }
- }
-
- !(!listener || typeof listener === 'function') ? invariant_1(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener) : void 0;
- return listener;
- },
-
- /**
- * Allows registered plugins an opportunity to extract events from top-level
- * native browser events.
- *
- * @return {*} An accumulation of synthetic events.
- * @internal
- */
- extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- var events;
- var plugins = EventPluginRegistry_1.plugins;
- 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_1(events, extractedEvents);
- }
- }
- }
- return events;
- },
-
- /**
- * Enqueues a synthetic event that should be dispatched when
- * `processEventQueue` is invoked.
- *
- * @param {*} events An accumulation of synthetic events.
- * @internal
- */
- enqueueEvents: function (events) {
- if (events) {
- eventQueue = accumulateInto_1(eventQueue, events);
- }
- },
-
- /**
- * Dispatches all synthetic events on the event queue.
- *
- * @internal
- */
- processEventQueue: function (simulated) {
- // 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 (simulated) {
- forEachAccumulated_1(processingEventQueue, executeDispatchesAndReleaseSimulated);
- } else {
- forEachAccumulated_1(processingEventQueue, executeDispatchesAndReleaseTopLevel);
- }
- !!eventQueue ? invariant_1(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : void 0;
- // This would be a good time to rethrow if any of the event handlers threw.
- ReactErrorUtils_1.rethrowCaughtError();
+function trapCapturedEvent(topLevelType, handlerBaseName, element) {
+ if (!element) {
+ return null;
}
-};
-
-var EventPluginHub_1 = EventPluginHub;
-
-function runEventQueueInBatch(events) {
- EventPluginHub_1.enqueueEvents(events);
- EventPluginHub_1.processEventQueue(false);
+ return EventListener_1.capture(element, handlerBaseName, dispatchEvent.bind(null, topLevelType));
}
-var ReactEventEmitterMixin = {
- /**
- * Streams a fired top-level event to `EventPluginHub` where plugins have the
- * opportunity to create `ReactEvent`s to be dispatched.
- */
- handleTopLevel: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- var events = EventPluginHub_1.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
- runEventQueueInBatch(events);
+function dispatchEvent(topLevelType, nativeEvent) {
+ if (!_enabled) {
+ return;
}
-};
-
-var ReactEventEmitterMixin_1 = ReactEventEmitterMixin;
-
-var useHasFeature;
-if (ExecutionEnvironment_1.canUseDOM) {
- useHasFeature = document.implementation && document.implementation.hasFeature &&
- // always returns true in newer browsers as per the standard.
- // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
- document.implementation.hasFeature('', '') !== true;
-}
-/**
- * Checks if an event is supported in the current execution environment.
- *
- * NOTE: This will not work correctly for non-generic events such as `change`,
- * `reset`, `load`, `error`, and `select`.
- *
- * Borrows from Modernizr.
- *
- * @param {string} eventNameSuffix Event name, e.g. "click".
- * @param {?boolean} capture Check if the capture phase is supported.
- * @return {boolean} True if the event is supported.
- * @internal
- * @license Modernizr 3.0.0pre (Custom Build) | MIT
- */
-function isEventSupported(eventNameSuffix, capture) {
- if (!ExecutionEnvironment_1.canUseDOM || capture && !('addEventListener' in document)) {
- return false;
+ var nativeEventTarget = getEventTarget(nativeEvent);
+ var targetInst = getClosestInstanceFromNode(nativeEventTarget);
+ if (targetInst !== null && typeof targetInst.tag === 'number' && !isFiberMounted(targetInst)) {
+ // If we get an event (ex: img onload) before committing that
+ // component's mount, ignore it for now (that is, treat it as if it was an
+ // event on a non-React tree). We might also consider queueing events and
+ // dispatching them after the mount.
+ targetInst = null;
}
- var eventName = 'on' + eventNameSuffix;
- var isSupported = eventName in document;
-
- if (!isSupported) {
- var element = document.createElement('div');
- element.setAttribute(eventName, 'return;');
- isSupported = typeof element[eventName] === 'function';
- }
+ var bookKeeping = getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst);
- if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {
- // This is the only way to test support for the `wheel` event in IE9+.
- isSupported = document.implementation.hasFeature('Events.wheel', '3.0');
+ try {
+ // Event queue being processed in the same cycle allows
+ // `preventDefault`.
+ batchedUpdates(handleTopLevelImpl, bookKeeping);
+ } finally {
+ releaseTopLevelCallbackBookKeeping(bookKeeping);
}
-
- return isSupported;
}
-var isEventSupported_1 = isEventSupported;
+var ReactDOMEventListener = Object.freeze({
+ get _enabled () { return _enabled; },
+ get _handleTopLevel () { return _handleTopLevel; },
+ setHandleTopLevel: setHandleTopLevel,
+ setEnabled: setEnabled,
+ isEnabled: isEnabled,
+ trapBubbledEvent: trapBubbledEvent,
+ trapCapturedEvent: trapCapturedEvent,
+ dispatchEvent: dispatchEvent
+});
/**
* Generate a mapping of standard vendor prefixes using the defined style property and event name.
@@ -2523,8 +3767,6 @@ function getVendorPrefixedEventName(eventName) {
return '';
}
-var getVendorPrefixedEventName_1 = getVendorPrefixedEventName;
-
/**
* Types of raw signals from the browser caught at the top level.
*
@@ -2534,9 +3776,9 @@ var getVendorPrefixedEventName_1 = getVendorPrefixedEventName;
*/
var topLevelTypes$1 = {
topAbort: 'abort',
- topAnimationEnd: getVendorPrefixedEventName_1('animationend') || 'animationend',
- topAnimationIteration: getVendorPrefixedEventName_1('animationiteration') || 'animationiteration',
- topAnimationStart: getVendorPrefixedEventName_1('animationstart') || 'animationstart',
+ topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',
+ topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',
+ topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',
topBlur: 'blur',
topCancel: 'cancel',
topCanPlay: 'canplay',
@@ -2597,7 +3839,7 @@ var topLevelTypes$1 = {
topTouchEnd: 'touchend',
topTouchMove: 'touchmove',
topTouchStart: 'touchstart',
- topTransitionEnd: getVendorPrefixedEventName_1('transitionend') || 'transitionend',
+ topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',
topVolumeChange: 'volumechange',
topWaiting: 'waiting',
topWheel: 'wheel'
@@ -2607,9 +3849,21 @@ var BrowserEventConstants = {
topLevelTypes: topLevelTypes$1
};
-var BrowserEventConstants_1 = BrowserEventConstants;
+function runEventQueueInBatch(events) {
+ enqueueEvents(events);
+ processEventQueue(false);
+}
+
+/**
+ * Streams a fired top-level event to `EventPluginHub` where plugins have the
+ * opportunity to create `ReactEvent`s to be dispatched.
+ */
+function handleTopLevel(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var events = extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
+ runEventQueueInBatch(events);
+}
-var topLevelTypes = BrowserEventConstants_1.topLevelTypes;
+var topLevelTypes = BrowserEventConstants.topLevelTypes;
/**
* Summary of `ReactBrowserEventEmitter` event handling:
@@ -2685,114 +3939,74 @@ function getListeningForDocument(mountAt) {
return alreadyListeningTo[mountAt[topListenersIDKey]];
}
-var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin_1, {
- /**
- * Sets whether or not any created callbacks should be enabled.
- *
- * @param {boolean} enabled True if callbacks should be enabled.
- */
- setEnabled: function (enabled) {
- if (ReactDOMEventListener_1) {
- ReactDOMEventListener_1.setEnabled(enabled);
- }
- },
+/**
+ * We listen for bubbled touch events on the document object.
+ *
+ * Firefox v8.01 (and possibly others) exhibited strange behavior when
+ * mounting `onmousemove` events at some node that was not the document
+ * element. The symptoms were that if your mouse is not moving over something
+ * contained within that mount point (for example on the background) the
+ * top-level listeners for `onmousemove` won't be called. However, if you
+ * register the `mousemove` on the document object, then it will of course
+ * catch all `mousemove`s. This along with iOS quirks, justifies restricting
+ * top-level listeners to the document object only, at least for these
+ * movement types of events and possibly all events.
+ *
+ * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
+ *
+ * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
+ * they bubble to document.
+ *
+ * @param {string} registrationName Name of listener (e.g. `onClick`).
+ * @param {object} contentDocumentHandle Document which owns the container
+ */
+function listenTo(registrationName, contentDocumentHandle) {
+ var mountAt = contentDocumentHandle;
+ var isListening = getListeningForDocument(mountAt);
+ var dependencies = registrationNameDependencies[registrationName];
- /**
- * @return {boolean} True if callbacks are enabled.
- */
- isEnabled: function () {
- return !!(ReactDOMEventListener_1 && ReactDOMEventListener_1.isEnabled());
- },
+ for (var i = 0; i < dependencies.length; i++) {
+ var dependency = dependencies[i];
+ if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
+ if (dependency === 'topScroll') {
+ trapCapturedEvent('topScroll', 'scroll', mountAt);
+ } else if (dependency === 'topFocus' || dependency === 'topBlur') {
+ trapCapturedEvent('topFocus', 'focus', mountAt);
+ trapCapturedEvent('topBlur', 'blur', mountAt);
- /**
- * We listen for bubbled touch events on the document object.
- *
- * Firefox v8.01 (and possibly others) exhibited strange behavior when
- * mounting `onmousemove` events at some node that was not the document
- * element. The symptoms were that if your mouse is not moving over something
- * contained within that mount point (for example on the background) the
- * top-level listeners for `onmousemove` won't be called. However, if you
- * register the `mousemove` on the document object, then it will of course
- * catch all `mousemove`s. This along with iOS quirks, justifies restricting
- * top-level listeners to the document object only, at least for these
- * movement types of events and possibly all events.
- *
- * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
- *
- * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
- * they bubble to document.
- *
- * @param {string} registrationName Name of listener (e.g. `onClick`).
- * @param {object} contentDocumentHandle Document which owns the container
- */
- listenTo: function (registrationName, contentDocumentHandle) {
- var mountAt = contentDocumentHandle;
- var isListening = getListeningForDocument(mountAt);
- var dependencies = EventPluginRegistry_1.registrationNameDependencies[registrationName];
-
- for (var i = 0; i < dependencies.length; i++) {
- var dependency = dependencies[i];
- if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
- if (dependency === 'topWheel') {
- if (isEventSupported_1('wheel')) {
- ReactDOMEventListener_1.trapBubbledEvent('topWheel', 'wheel', mountAt);
- } else if (isEventSupported_1('mousewheel')) {
- ReactDOMEventListener_1.trapBubbledEvent('topWheel', 'mousewheel', mountAt);
- } else {
- // Firefox needs to capture a different mouse scroll event.
- // @see http://www.quirksmode.org/dom/events/tests/scroll.html
- ReactDOMEventListener_1.trapBubbledEvent('topWheel', 'DOMMouseScroll', mountAt);
- }
- } else if (dependency === 'topScroll') {
- ReactDOMEventListener_1.trapCapturedEvent('topScroll', 'scroll', mountAt);
- } else if (dependency === 'topFocus' || dependency === 'topBlur') {
- ReactDOMEventListener_1.trapCapturedEvent('topFocus', 'focus', mountAt);
- ReactDOMEventListener_1.trapCapturedEvent('topBlur', 'blur', mountAt);
-
- // to make sure blur and focus event listeners are only attached once
- isListening.topBlur = true;
- isListening.topFocus = true;
- } else if (dependency === 'topCancel') {
- if (isEventSupported_1('cancel', true)) {
- ReactDOMEventListener_1.trapCapturedEvent('topCancel', 'cancel', mountAt);
- }
- isListening.topCancel = true;
- } else if (dependency === 'topClose') {
- if (isEventSupported_1('close', true)) {
- ReactDOMEventListener_1.trapCapturedEvent('topClose', 'close', mountAt);
- }
- isListening.topClose = true;
- } else if (topLevelTypes.hasOwnProperty(dependency)) {
- ReactDOMEventListener_1.trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt);
+ // to make sure blur and focus event listeners are only attached once
+ isListening.topBlur = true;
+ isListening.topFocus = true;
+ } else if (dependency === 'topCancel') {
+ if (isEventSupported('cancel', true)) {
+ trapCapturedEvent('topCancel', 'cancel', mountAt);
}
-
- isListening[dependency] = true;
+ isListening.topCancel = true;
+ } else if (dependency === 'topClose') {
+ if (isEventSupported('close', true)) {
+ trapCapturedEvent('topClose', 'close', mountAt);
+ }
+ isListening.topClose = true;
+ } else if (topLevelTypes.hasOwnProperty(dependency)) {
+ trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt);
}
- }
- },
- isListeningToAllDependencies: function (registrationName, mountAt) {
- var isListening = getListeningForDocument(mountAt);
- var dependencies = EventPluginRegistry_1.registrationNameDependencies[registrationName];
- for (var i = 0; i < dependencies.length; i++) {
- var dependency = dependencies[i];
- if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
- return false;
- }
+ isListening[dependency] = true;
}
- return true;
- },
-
- trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {
- return ReactDOMEventListener_1.trapBubbledEvent(topLevelType, handlerBaseName, handle);
- },
-
- trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {
- return ReactDOMEventListener_1.trapCapturedEvent(topLevelType, handlerBaseName, handle);
}
-});
+}
-var ReactBrowserEventEmitter_1 = ReactBrowserEventEmitter;
+function isListeningToAllDependencies(registrationName, mountAt) {
+ var isListening = getListeningForDocument(mountAt);
+ var dependencies = registrationNameDependencies[registrationName];
+ for (var i = 0; i < dependencies.length; i++) {
+ var dependency = dependencies[i];
+ if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
+ return false;
+ }
+ }
+ return true;
+}
/**
* Copyright (c) 2013-present, Facebook, Inc.
@@ -2800,15 +4014,34 @@ var ReactBrowserEventEmitter_1 = ReactBrowserEventEmitter;
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- * @providesModule ReactDOMFeatureFlags
+ * @typechecks
*/
-var ReactDOMFeatureFlags = {
- fiberAsyncScheduling: false,
- useFiber: true
-};
+/* eslint-disable fb-www/typeof-undefined */
+
+/**
+ * Same as document.activeElement but wraps in a try-catch block. In IE it is
+ * not safe to call document.activeElement if there is nothing focused.
+ *
+ * The activeElement will be null only if the document or document body is not
+ * yet defined.
+ *
+ * @param {?DOMDocument} doc Defaults to current document.
+ * @return {?DOMElement}
+ */
+function getActiveElement(doc) /*?DOMElement*/{
+ doc = doc || (typeof document !== 'undefined' ? document : undefined);
+ if (typeof doc === 'undefined') {
+ return null;
+ }
+ try {
+ return doc.activeElement || doc.body;
+ } catch (e) {
+ return doc.body;
+ }
+}
-var ReactDOMFeatureFlags_1 = ReactDOMFeatureFlags;
+var getActiveElement_1 = getActiveElement;
/**
* Copyright (c) 2013-present, Facebook, Inc.
@@ -2816,187 +4049,65 @@ var ReactDOMFeatureFlags_1 = ReactDOMFeatureFlags;
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- * @providesModule CSSProperty
+ * @typechecks
+ *
*/
-/**
- * CSS properties which accept numbers but are not in units of "px".
- */
+/*eslint-disable no-self-compare */
-var isUnitlessNumber = {
- animationIterationCount: true,
- borderImageOutset: true,
- borderImageSlice: true,
- borderImageWidth: true,
- boxFlex: true,
- boxFlexGroup: true,
- boxOrdinalGroup: true,
- columnCount: true,
- columns: true,
- flex: true,
- flexGrow: true,
- flexPositive: true,
- flexShrink: true,
- flexNegative: true,
- flexOrder: true,
- gridRow: true,
- gridRowEnd: true,
- gridRowSpan: true,
- gridRowStart: true,
- gridColumn: true,
- gridColumnEnd: true,
- gridColumnSpan: true,
- gridColumnStart: true,
- fontWeight: true,
- lineClamp: true,
- lineHeight: true,
- opacity: true,
- order: true,
- orphans: true,
- tabSize: true,
- widows: true,
- zIndex: true,
- zoom: true,
- // SVG-related properties
- fillOpacity: true,
- floodOpacity: true,
- stopOpacity: true,
- strokeDasharray: true,
- strokeDashoffset: true,
- strokeMiterlimit: true,
- strokeOpacity: true,
- strokeWidth: true
-};
-/**
- * @param {string} prefix vendor-specific prefix, eg: Webkit
- * @param {string} key style name, eg: transitionDuration
- * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
- * WebkitTransitionDuration
- */
-function prefixKey(prefix, key) {
- return prefix + key.charAt(0).toUpperCase() + key.substring(1);
-}
+var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
- * Support style names that may come passed in prefixed by adding permutations
- * of vendor prefixes.
+ * inlined Object.is polyfill to avoid requiring consumers ship their own
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
-var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
-
-// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
-// infinite loop, because it iterates over the newly added props too.
-Object.keys(isUnitlessNumber).forEach(function (prop) {
- prefixes.forEach(function (prefix) {
- isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
- });
-});
+function is(x, y) {
+ // SameValue algorithm
+ if (x === y) {
+ // Steps 1-5, 7-10
+ // Steps 6.b-6.e: +0 != -0
+ // Added the nonzero y check to make Flow happy, but it is redundant
+ return x !== 0 || y !== 0 || 1 / x === 1 / y;
+ } else {
+ // Step 6.a: NaN == NaN
+ return x !== x && y !== y;
+ }
+}
/**
- * Most style properties can be unset by doing .style[prop] = '' but IE8
- * doesn't like doing that with shorthand properties so for the properties that
- * IE8 breaks on, which are listed here, we instead unset each of the
- * individual properties. See http://bugs.jquery.com/ticket/12385.
- * The 4-value 'clock' properties like margin, padding, border-width seem to
- * behave without any problems. Curiously, list-style works too without any
- * special prodding.
+ * Performs equality by iterating through keys on an object and returning false
+ * when any key has values which are not strictly equal between the arguments.
+ * Returns true when the values of all keys are strictly equal.
*/
-var shorthandPropertyExpansions = {
- background: {
- backgroundAttachment: true,
- backgroundColor: true,
- backgroundImage: true,
- backgroundPositionX: true,
- backgroundPositionY: true,
- backgroundRepeat: true
- },
- backgroundPosition: {
- backgroundPositionX: true,
- backgroundPositionY: true
- },
- border: {
- borderWidth: true,
- borderStyle: true,
- borderColor: true
- },
- borderBottom: {
- borderBottomWidth: true,
- borderBottomStyle: true,
- borderBottomColor: true
- },
- borderLeft: {
- borderLeftWidth: true,
- borderLeftStyle: true,
- borderLeftColor: true
- },
- borderRight: {
- borderRightWidth: true,
- borderRightStyle: true,
- borderRightColor: true
- },
- borderTop: {
- borderTopWidth: true,
- borderTopStyle: true,
- borderTopColor: true
- },
- font: {
- fontStyle: true,
- fontVariant: true,
- fontWeight: true,
- fontSize: true,
- lineHeight: true,
- fontFamily: true
- },
- outline: {
- outlineWidth: true,
- outlineStyle: true,
- outlineColor: true
+function shallowEqual(objA, objB) {
+ if (is(objA, objB)) {
+ return true;
}
-};
-
-var CSSProperty = {
- isUnitlessNumber: isUnitlessNumber,
- shorthandPropertyExpansions: shorthandPropertyExpansions
-};
-var CSSProperty_1 = CSSProperty;
-
-var isUnitlessNumber$1 = CSSProperty_1.isUnitlessNumber;
+ if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
+ return false;
+ }
-/**
- * Convert a value into the proper css writable value. The style name `name`
- * should be logical (no hyphens), as specified
- * in `CSSProperty.isUnitlessNumber`.
- *
- * @param {string} name CSS property name such as `topMargin`.
- * @param {*} value CSS property value such as `10px`.
- * @return {string} Normalized style value with dimensions applied.
- */
-function dangerousStyleValue(name, value, isCustomProperty) {
- // Note that we've removed escapeTextForBrowser() calls here since the
- // whole string will be escaped when the attribute is injected into
- // the markup. If you provide unsafe user data here they can inject
- // arbitrary CSS which may be problematic (I couldn't repro this):
- // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
- // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
- // This is not an XSS hole but instead a potential CSS injection issue
- // which has lead to a greater discussion about how we're going to
- // trust URLs moving forward. See #2115901
+ var keysA = Object.keys(objA);
+ var keysB = Object.keys(objB);
- var isEmpty = value == null || typeof value === 'boolean' || value === '';
- if (isEmpty) {
- return '';
+ if (keysA.length !== keysB.length) {
+ return false;
}
- if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber$1.hasOwnProperty(name) && isUnitlessNumber$1[name])) {
- return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
+ // Test for A's keys different from B.
+ for (var i = 0; i < keysA.length; i++) {
+ if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
+ return false;
+ }
}
- return ('' + value).trim();
+ return true;
}
-var dangerousStyleValue_1 = dangerousStyleValue;
+var shallowEqual_1 = shallowEqual;
/**
* Copyright (c) 2013-present, Facebook, Inc.
@@ -3007,49 +4118,17 @@ var dangerousStyleValue_1 = dangerousStyleValue;
* @typechecks
*/
-var _uppercasePattern = /([A-Z])/g;
-
/**
- * Hyphenates a camelcased string, for example:
- *
- * > hyphenate('backgroundColor')
- * < "background-color"
- *
- * For CSS style names, use `hyphenateStyleName` instead which works properly
- * with all vendor prefixes, including `ms`.
- *
- * @param {string} string
- * @return {string}
- */
-function hyphenate(string) {
- return string.replace(_uppercasePattern, '-$1').toLowerCase();
-}
-
-var hyphenate_1 = hyphenate;
-
-var msPattern = /^ms-/;
-
-/**
- * Hyphenates a camelcased CSS property name, for example:
- *
- * > hyphenateStyleName('backgroundColor')
- * < "background-color"
- * > hyphenateStyleName('MozTransition')
- * < "-moz-transition"
- * > hyphenateStyleName('msTransition')
- * < "-ms-transition"
- *
- * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
- * is converted to `-ms-`.
- *
- * @param {string} string
- * @return {string}
+ * @param {*} object The object to check.
+ * @return {boolean} Whether or not the object is a DOM node.
*/
-function hyphenateStyleName$1(string) {
- return hyphenate_1(string).replace(msPattern, '-ms-');
+function isNode(object) {
+ var doc = object ? object.ownerDocument || object : document;
+ var defaultView = doc.defaultView || window;
+ return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
}
-var hyphenateStyleName_1 = hyphenateStyleName$1;
+var isNode_1 = isNode;
/**
* Copyright (c) 2013-present, Facebook, Inc.
@@ -3060,439 +4139,53 @@ var hyphenateStyleName_1 = hyphenateStyleName$1;
* @typechecks
*/
-var _hyphenPattern = /-(.)/g;
-/**
- * Camelcases a hyphenated string, for example:
- *
- * > camelize('background-color')
- * < "backgroundColor"
- *
- * @param {string} string
- * @return {string}
- */
-function camelize(string) {
- return string.replace(_hyphenPattern, function (_, character) {
- return character.toUpperCase();
- });
-}
-
-var camelize_1 = camelize;
-
-var msPattern$1 = /^-ms-/;
/**
- * Camelcases a hyphenated CSS property name, for example:
- *
- * > camelizeStyleName('background-color')
- * < "backgroundColor"
- * > camelizeStyleName('-moz-transition')
- * < "MozTransition"
- * > camelizeStyleName('-ms-transition')
- * < "msTransition"
- *
- * As Andi Smith suggests
- * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
- * is converted to lowercase `ms`.
- *
- * @param {string} string
- * @return {string}
+ * @param {*} object The object to check.
+ * @return {boolean} Whether or not the object is a DOM text node.
*/
-function camelizeStyleName$1(string) {
- return camelize_1(string.replace(msPattern$1, 'ms-'));
+function isTextNode(object) {
+ return isNode_1(object) && object.nodeType == 3;
}
-var camelizeStyleName_1 = camelizeStyleName$1;
+var isTextNode_1 = isTextNode;
/**
- * Copyright (c) 2016-present, Facebook, Inc.
+ * 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.
*
*
- * @providesModule describeComponentFrame
*/
-var describeComponentFrame = function (name, source, ownerName) {
- return '\n in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
-};
-
-var IndeterminateComponent = ReactTypeOfWork.IndeterminateComponent;
-var FunctionalComponent = ReactTypeOfWork.FunctionalComponent;
-var ClassComponent$1 = ReactTypeOfWork.ClassComponent;
-var HostComponent$2 = ReactTypeOfWork.HostComponent;
-
-
-function describeFiber(fiber) {
- switch (fiber.tag) {
- case IndeterminateComponent:
- case FunctionalComponent:
- case ClassComponent$1:
- case HostComponent$2:
- var owner = fiber._debugOwner;
- var source = fiber._debugSource;
- var name = getComponentName_1(fiber);
- var ownerName = null;
- if (owner) {
- ownerName = getComponentName_1(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$1(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;
-}
-
-var ReactFiberComponentTreeHook = {
- getStackAddendumByWorkInProgressFiber: getStackAddendumByWorkInProgressFiber$1
-};
-
-var ReactDebugCurrentFrame = ReactGlobalSharedState_1.ReactDebugCurrentFrame;
-
-{
- var getComponentName$3 = getComponentName_1;
-
- var _require2$2 = ReactFiberComponentTreeHook,
- getStackAddendumByWorkInProgressFiber = _require2$2.getStackAddendumByWorkInProgressFiber;
-}
-
-function getCurrentFiberOwnerName$2() {
- {
- var fiber = ReactDebugCurrentFiber.current;
- if (fiber === null) {
- return null;
- }
- if (fiber._debugOwner != null) {
- return getComponentName$3(fiber._debugOwner);
- }
- }
- return null;
-}
-
-function getCurrentFiberStackAddendum$1() {
- {
- 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, phase) {
- ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum$1;
- ReactDebugCurrentFiber.current = fiber;
- ReactDebugCurrentFiber.phase = phase;
-}
-
-var ReactDebugCurrentFiber = {
- current: null,
- phase: null,
- resetCurrentFiber: resetCurrentFiber,
- setCurrentFiber: setCurrentFiber,
- getCurrentFiberOwnerName: getCurrentFiberOwnerName$2,
- getCurrentFiberStackAddendum: getCurrentFiberStackAddendum$1
-};
-
-var ReactDebugCurrentFiber_1 = ReactDebugCurrentFiber;
-
-var warnValidStyle$1 = emptyFunction_1;
-
-{
- var camelizeStyleName = camelizeStyleName_1;
- var getComponentName$2 = getComponentName_1;
- var warning$5 = warning_1;
-
- var _require$3 = ReactDebugCurrentFiber_1,
- getCurrentFiberOwnerName$1 = _require$3.getCurrentFiberOwnerName;
-
- // 'msTransform' is correct, but the other prefixes should be capitalized
-
-
- var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
-
- // style values shouldn't contain a semicolon
- var badStyleValueWithSemicolonPattern = /;\s*$/;
-
- var warnedStyleNames = {};
- var warnedStyleValues = {};
- var warnedForNaNValue = false;
- var warnedForInfinityValue = false;
-
- var warnHyphenatedStyleName = function (name, owner) {
- if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
- return;
- }
-
- warnedStyleNames[name] = true;
- warning$5(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner));
- };
-
- var warnBadVendoredStyleName = function (name, owner) {
- if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
- return;
- }
-
- warnedStyleNames[name] = true;
- warning$5(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner));
- };
-
- var warnStyleValueWithSemicolon = function (name, value, owner) {
- if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
- return;
- }
-
- warnedStyleValues[value] = true;
- warning$5(false, "Style property values shouldn't contain a semicolon.%s " + 'Try "%s: %s" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, ''));
- };
-
- var warnStyleValueIsNaN = function (name, value, owner) {
- if (warnedForNaNValue) {
- return;
- }
-
- warnedForNaNValue = true;
- warning$5(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner));
- };
-
- var warnStyleValueIsInfinity = function (name, value, owner) {
- if (warnedForInfinityValue) {
- return;
- }
-
- warnedForInfinityValue = true;
- warning$5(false, '`Infinity` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner));
- };
-
- var checkRenderMessage = function (owner) {
- var ownerName;
- if (owner != null) {
- // Stack passes the owner manually all the way to CSSPropertyOperations.
- ownerName = getComponentName$2(owner);
- } else {
- // Fiber doesn't pass it but uses ReactDebugCurrentFiber to track it.
- // It is only enabled in development and tracks host components too.
- ownerName = getCurrentFiberOwnerName$1();
- // TODO: also report the stack.
- }
- if (ownerName) {
- return '\n\nCheck the render method of `' + ownerName + '`.';
- }
- return '';
- };
-
- warnValidStyle$1 = function (name, value, component) {
- var owner;
- if (component) {
- // TODO: this only works with Stack. Seems like we need to add unit tests?
- owner = component._currentElement._owner;
- }
- if (name.indexOf('-') > -1) {
- warnHyphenatedStyleName(name, owner);
- } else if (badVendoredStyleNamePattern.test(name)) {
- warnBadVendoredStyleName(name, owner);
- } else if (badStyleValueWithSemicolonPattern.test(value)) {
- warnStyleValueWithSemicolon(name, value, owner);
- }
-
- if (typeof value === 'number') {
- if (isNaN(value)) {
- warnStyleValueIsNaN(name, value, owner);
- } else if (!isFinite(value)) {
- warnStyleValueIsInfinity(name, value, owner);
- }
- }
- };
-}
-
-var warnValidStyle_1 = warnValidStyle$1;
-
-{
- var hyphenateStyleName = hyphenateStyleName_1;
- var warnValidStyle = warnValidStyle_1;
-}
-
-var hasShorthandPropertyBug = false;
-if (ExecutionEnvironment_1.canUseDOM) {
- var tempStyle = document.createElement('div').style;
- try {
- // IE8 throws "Invalid argument." if resetting shorthand style properties.
- tempStyle.font = '';
- } catch (e) {
- hasShorthandPropertyBug = true;
- }
-}
+/*eslint-disable no-bitwise */
/**
- * Operations for dealing with CSS properties.
+ * Checks if a given DOM node contains or is another DOM node.
*/
-var CSSPropertyOperations = {
- /**
- * This creates a string that is expected to be equivalent to the style
- * attribute generated by server-side rendering. It by-passes warnings and
- * security checks so it's not safe to use this value for anything other than
- * comparison. It is only used in DEV for SSR validation.
- */
- createDangerousStringForStyles: function (styles) {
- {
- var serialized = '';
- var delimiter = '';
- for (var styleName in styles) {
- if (!styles.hasOwnProperty(styleName)) {
- continue;
- }
- var styleValue = styles[styleName];
- if (styleValue != null) {
- var isCustomProperty = styleName.indexOf('--') === 0;
- serialized += delimiter + hyphenateStyleName(styleName) + ':';
- serialized += dangerousStyleValue_1(styleName, styleValue, isCustomProperty);
-
- delimiter = ';';
- }
- }
- return serialized || null;
- }
- },
-
- /**
- * Sets the value for multiple styles on a node. If a value is specified as
- * '' (empty string), the corresponding style property will be unset.
- *
- * @param {DOMElement} node
- * @param {object} styles
- * @param {ReactDOMComponent} component
- */
- setValueForStyles: function (node, styles, component) {
- var style = node.style;
- for (var styleName in styles) {
- if (!styles.hasOwnProperty(styleName)) {
- continue;
- }
- var isCustomProperty = styleName.indexOf('--') === 0;
- {
- if (!isCustomProperty) {
- warnValidStyle(styleName, styles[styleName], component);
- }
- }
- var styleValue = dangerousStyleValue_1(styleName, styles[styleName], isCustomProperty);
- if (styleName === 'float') {
- styleName = 'cssFloat';
- }
- if (isCustomProperty) {
- style.setProperty(styleName, styleValue);
- } else if (styleValue) {
- style[styleName] = styleValue;
- } else {
- var expansion = hasShorthandPropertyBug && CSSProperty_1.shorthandPropertyExpansions[styleName];
- if (expansion) {
- // Shorthand property that IE8 won't like unsetting, so unset each
- // component to placate it
- for (var individualStyleName in expansion) {
- style[individualStyleName] = '';
- }
- } else {
- style[styleName] = '';
- }
- }
- }
+function containsNode(outerNode, innerNode) {
+ if (!outerNode || !innerNode) {
+ return false;
+ } else if (outerNode === innerNode) {
+ return true;
+ } else if (isTextNode_1(outerNode)) {
+ return false;
+ } else if (isTextNode_1(innerNode)) {
+ return containsNode(outerNode, innerNode.parentNode);
+ } else if ('contains' in outerNode) {
+ return outerNode.contains(innerNode);
+ } else if (outerNode.compareDocumentPosition) {
+ return !!(outerNode.compareDocumentPosition(innerNode) & 16);
+ } else {
+ return false;
}
-};
-
-var CSSPropertyOperations_1 = CSSPropertyOperations;
-
-var ReactInvalidSetStateWarningHook = {};
-
-{
- var warning$8 = warning_1;
- var processingChildContext = false;
-
- var warnInvalidSetState = function () {
- warning$8(!processingChildContext, 'setState(...): Cannot call setState() inside getChildContext()');
- };
-
- ReactInvalidSetStateWarningHook = {
- onBeginProcessingChildContext: function () {
- processingChildContext = true;
- },
- onEndProcessingChildContext: function () {
- processingChildContext = false;
- },
- onSetState: function () {
- warnInvalidSetState();
- }
- };
}
-var ReactInvalidSetStateWarningHook_1 = ReactInvalidSetStateWarningHook;
-
-/**
- * Copyright (c) 2016-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.
- *
- * @providesModule ReactHostOperationHistoryHook
- *
- */
-
-// Trust the developer to only use this with a true check
-var ReactHostOperationHistoryHook = null;
-
-{
- var history = [];
-
- ReactHostOperationHistoryHook = {
- onHostOperation: function (operation) {
- history.push(operation);
- },
- clearHistory: function () {
- if (ReactHostOperationHistoryHook._preventClearing) {
- // Should only be used for tests.
- return;
- }
-
- history = [];
- },
- getHistory: function () {
- return history;
- }
- };
-}
-
-var ReactHostOperationHistoryHook_1 = ReactHostOperationHistoryHook;
-
-var performance$1;
-
-if (ExecutionEnvironment_1.canUseDOM) {
- performance$1 = window.performance || window.msPerformance || window.webkitPerformance;
-}
-
-var performance_1 = performance$1 || {};
+var containsNode_1 = containsNode;
/**
* Copyright (c) 2013-present, Facebook, Inc.
@@ -3500,5222 +4193,1688 @@ var performance_1 = performance$1 || {};
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- * @typechecks
*/
-var performanceNow;
-
/**
- * Detect if we can use `window.performance.now()` and gracefully fallback to
- * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now
- * because of Facebook's testing infrastructure.
+ * @param {DOMElement} node input/textarea to focus
*/
-if (performance_1.now) {
- performanceNow = function performanceNow() {
- return performance_1.now();
- };
-} else {
- performanceNow = function performanceNow() {
- return Date.now();
- };
-}
-
-var performanceNow_1 = performanceNow;
-
-var ReactComponentTreeHook = ReactGlobalSharedState_1.ReactComponentTreeHook;
-
-
-{
- var warning$7 = warning_1;
-}
-
-// Trust the developer to only use this with a true check
-var ReactDebugTool$1 = null;
-
-{
- var hooks = [];
- var didHookThrowForEvent = {};
-
- var callHook = function (event, fn, context, arg1, arg2, arg3, arg4, arg5) {
- try {
- fn.call(context, arg1, arg2, arg3, arg4, arg5);
- } catch (e) {
- warning$7(didHookThrowForEvent[event], 'Exception thrown by hook while handling %s: %s', event, e + '\n' + e.stack);
- didHookThrowForEvent[event] = true;
- }
- };
-
- var emitEvent = function (event, arg1, arg2, arg3, arg4, arg5) {
- for (var i = 0; i < hooks.length; i++) {
- var hook = hooks[i];
- var fn = hook[event];
- if (fn) {
- callHook(event, fn, hook, arg1, arg2, arg3, arg4, arg5);
- }
- }
- };
-
- var isProfiling = false;
- var flushHistory = [];
- var lifeCycleTimerStack = [];
- var currentFlushNesting = 0;
- var currentFlushMeasurements = [];
- var currentFlushStartTime = 0;
- var currentTimerDebugID = null;
- var currentTimerStartTime = 0;
- var currentTimerNestedFlushDuration = 0;
- var currentTimerType = null;
-
- var lifeCycleTimerHasWarned = false;
-
- var clearHistory = function () {
- ReactComponentTreeHook.purgeUnmountedComponents();
- ReactHostOperationHistoryHook_1.clearHistory();
- };
-
- var getTreeSnapshot = function (registeredIDs) {
- return registeredIDs.reduce(function (tree, id) {
- var ownerID = ReactComponentTreeHook.getOwnerID(id);
- var parentID = ReactComponentTreeHook.getParentID(id);
- tree[id] = {
- displayName: ReactComponentTreeHook.getDisplayName(id),
- text: ReactComponentTreeHook.getText(id),
- updateCount: ReactComponentTreeHook.getUpdateCount(id),
- childIDs: ReactComponentTreeHook.getChildIDs(id),
- // Text nodes don't have owners but this is close enough.
- ownerID: ownerID || parentID && ReactComponentTreeHook.getOwnerID(parentID) || 0,
- parentID: parentID
- };
- return tree;
- }, {});
- };
-
- var resetMeasurements = function () {
- var previousStartTime = currentFlushStartTime;
- var previousMeasurements = currentFlushMeasurements;
- var previousOperations = ReactHostOperationHistoryHook_1.getHistory();
-
- if (currentFlushNesting === 0) {
- currentFlushStartTime = 0;
- currentFlushMeasurements = [];
- clearHistory();
- return;
- }
-
- if (previousMeasurements.length || previousOperations.length) {
- var registeredIDs = ReactComponentTreeHook.getRegisteredIDs();
- flushHistory.push({
- duration: performanceNow_1() - previousStartTime,
- measurements: previousMeasurements || [],
- operations: previousOperations || [],
- treeSnapshot: getTreeSnapshot(registeredIDs)
- });
- }
-
- clearHistory();
- currentFlushStartTime = performanceNow_1();
- currentFlushMeasurements = [];
- };
-
- var checkDebugID = function (debugID) {
- var allowRoot = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- if (allowRoot && debugID === 0) {
- return;
- }
- if (!debugID) {
- warning$7(false, 'ReactDebugTool: debugID may not be empty.');
- }
- };
-
- var beginLifeCycleTimer = function (debugID, timerType) {
- if (currentFlushNesting === 0) {
- return;
- }
- if (currentTimerType && !lifeCycleTimerHasWarned) {
- warning$7(false, 'There is an internal error in the React performance measurement code.' + '\n\nDid not expect %s timer to start while %s timer is still in ' + 'progress for %s instance.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another');
- lifeCycleTimerHasWarned = true;
- }
- currentTimerStartTime = performanceNow_1();
- currentTimerNestedFlushDuration = 0;
- currentTimerDebugID = debugID;
- currentTimerType = timerType;
- };
-
- var endLifeCycleTimer = function (debugID, timerType) {
- if (currentFlushNesting === 0) {
- return;
- }
- if (currentTimerType !== timerType && !lifeCycleTimerHasWarned) {
- warning$7(false, 'There is an internal error in the React performance measurement code. ' + 'We did not expect %s timer to stop while %s timer is still in ' + 'progress for %s instance. Please report this as a bug in React.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another');
- lifeCycleTimerHasWarned = true;
- }
- if (isProfiling) {
- currentFlushMeasurements.push({
- timerType: timerType,
- instanceID: debugID,
- duration: performanceNow_1() - currentTimerStartTime - currentTimerNestedFlushDuration
- });
- }
- currentTimerStartTime = 0;
- currentTimerNestedFlushDuration = 0;
- currentTimerDebugID = null;
- currentTimerType = null;
- };
-
- var pauseCurrentLifeCycleTimer = function () {
- var currentTimer = {
- startTime: currentTimerStartTime,
- nestedFlushStartTime: performanceNow_1(),
- debugID: currentTimerDebugID,
- timerType: currentTimerType
- };
- lifeCycleTimerStack.push(currentTimer);
- currentTimerStartTime = 0;
- currentTimerNestedFlushDuration = 0;
- currentTimerDebugID = null;
- currentTimerType = null;
- };
-
- var resumeCurrentLifeCycleTimer = function () {
- var _lifeCycleTimerStack$ = lifeCycleTimerStack.pop(),
- startTime = _lifeCycleTimerStack$.startTime,
- nestedFlushStartTime = _lifeCycleTimerStack$.nestedFlushStartTime,
- debugID = _lifeCycleTimerStack$.debugID,
- timerType = _lifeCycleTimerStack$.timerType;
-
- var nestedFlushDuration = performanceNow_1() - nestedFlushStartTime;
- currentTimerStartTime = startTime;
- currentTimerNestedFlushDuration += nestedFlushDuration;
- currentTimerDebugID = debugID;
- currentTimerType = timerType;
- };
-
- var lastMarkTimeStamp = 0;
- var canUsePerformanceMeasure = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function';
-
- var shouldMark = function (debugID) {
- if (!isProfiling || !canUsePerformanceMeasure) {
- return false;
- }
- var element = ReactComponentTreeHook.getElement(debugID);
- if (element == null || typeof element !== 'object') {
- return false;
- }
- var isHostElement = typeof element.type === 'string';
- if (isHostElement) {
- return false;
- }
- return true;
- };
-
- var markBegin = function (debugID, markType) {
- if (!shouldMark(debugID)) {
- return;
- }
-
- var markName = debugID + '::' + markType;
- lastMarkTimeStamp = performanceNow_1();
- performance.mark(markName);
- };
-
- var markEnd = function (debugID, markType) {
- if (!shouldMark(debugID)) {
- return;
- }
-
- var markName = debugID + '::' + markType;
- var displayName = ReactComponentTreeHook.getDisplayName(debugID) || 'Unknown';
-
- // Chrome has an issue of dropping markers recorded too fast:
- // https://bugs.chromium.org/p/chromium/issues/detail?id=640652
- // To work around this, we will not report very small measurements.
- // I determined the magic number by tweaking it back and forth.
- // 0.05ms was enough to prevent the issue, but I set it to 0.1ms to be safe.
- // When the bug is fixed, we can `measure()` unconditionally if we want to.
- var timeStamp = performanceNow_1();
- if (timeStamp - lastMarkTimeStamp > 0.1) {
- var measurementName = displayName + ' [' + markType + ']';
- performance.measure(measurementName, markName);
- }
-
- performance.clearMarks(markName);
- if (measurementName) {
- performance.clearMeasures(measurementName);
- }
- };
-
- ReactDebugTool$1 = {
- addHook: function (hook) {
- hooks.push(hook);
- },
- removeHook: function (hook) {
- for (var i = 0; i < hooks.length; i++) {
- if (hooks[i] === hook) {
- hooks.splice(i, 1);
- i--;
- }
- }
- },
- isProfiling: function () {
- return isProfiling;
- },
- beginProfiling: function () {
- if (isProfiling) {
- return;
- }
-
- isProfiling = true;
- flushHistory.length = 0;
- resetMeasurements();
- ReactDebugTool$1.addHook(ReactHostOperationHistoryHook_1);
- },
- endProfiling: function () {
- if (!isProfiling) {
- return;
- }
-
- isProfiling = false;
- resetMeasurements();
- ReactDebugTool$1.removeHook(ReactHostOperationHistoryHook_1);
- },
- getFlushHistory: function () {
- return flushHistory;
- },
- onBeginFlush: function () {
- currentFlushNesting++;
- resetMeasurements();
- pauseCurrentLifeCycleTimer();
- emitEvent('onBeginFlush');
- },
- onEndFlush: function () {
- resetMeasurements();
- currentFlushNesting--;
- resumeCurrentLifeCycleTimer();
- emitEvent('onEndFlush');
- },
- onBeginLifeCycleTimer: function (debugID, timerType) {
- checkDebugID(debugID);
- emitEvent('onBeginLifeCycleTimer', debugID, timerType);
- markBegin(debugID, timerType);
- beginLifeCycleTimer(debugID, timerType);
- },
- onEndLifeCycleTimer: function (debugID, timerType) {
- checkDebugID(debugID);
- endLifeCycleTimer(debugID, timerType);
- markEnd(debugID, timerType);
- emitEvent('onEndLifeCycleTimer', debugID, timerType);
- },
- onBeginProcessingChildContext: function () {
- emitEvent('onBeginProcessingChildContext');
- },
- onEndProcessingChildContext: function () {
- emitEvent('onEndProcessingChildContext');
- },
- onHostOperation: function (operation) {
- checkDebugID(operation.instanceID);
- emitEvent('onHostOperation', operation);
- },
- onSetState: function () {
- emitEvent('onSetState');
- },
- onSetChildren: function (debugID, childDebugIDs) {
- checkDebugID(debugID);
- childDebugIDs.forEach(checkDebugID);
- emitEvent('onSetChildren', debugID, childDebugIDs);
- },
- onBeforeMountComponent: function (debugID, element, parentDebugID) {
- checkDebugID(debugID);
- checkDebugID(parentDebugID, true);
- emitEvent('onBeforeMountComponent', debugID, element, parentDebugID);
- markBegin(debugID, 'mount');
- },
- onMountComponent: function (debugID) {
- checkDebugID(debugID);
- markEnd(debugID, 'mount');
- emitEvent('onMountComponent', debugID);
- },
- onBeforeUpdateComponent: function (debugID, element) {
- checkDebugID(debugID);
- emitEvent('onBeforeUpdateComponent', debugID, element);
- markBegin(debugID, 'update');
- },
- onUpdateComponent: function (debugID) {
- checkDebugID(debugID);
- markEnd(debugID, 'update');
- emitEvent('onUpdateComponent', debugID);
- },
- onBeforeUnmountComponent: function (debugID) {
- checkDebugID(debugID);
- emitEvent('onBeforeUnmountComponent', debugID);
- markBegin(debugID, 'unmount');
- },
- onUnmountComponent: function (debugID) {
- checkDebugID(debugID);
- markEnd(debugID, 'unmount');
- emitEvent('onUnmountComponent', debugID);
- },
- onTestEvent: function () {
- emitEvent('onTestEvent');
- }
- };
-
- ReactDebugTool$1.addHook(ReactInvalidSetStateWarningHook_1);
- ReactDebugTool$1.addHook(ReactComponentTreeHook);
- var url = ExecutionEnvironment_1.canUseDOM && window.location.href || '';
- if (/[?&]react_perf\b/.test(url)) {
- ReactDebugTool$1.beginProfiling();
- }
-}
-
-var ReactDebugTool_1 = ReactDebugTool$1;
-
-// Trust the developer to only use ReactInstrumentation with a true check
-
-var debugTool = null;
-
-{
- var ReactDebugTool = ReactDebugTool_1;
- debugTool = ReactDebugTool;
-}
-
-var ReactInstrumentation = { debugTool: debugTool };
-
-{
- var warning$6 = warning_1;
-}
-
-// isAttributeNameSafe() is currently duplicated in DOMMarkupOperations.
-// TODO: Find a better place for this.
-var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty_1.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty_1.ATTRIBUTE_NAME_CHAR + ']*$');
-var illegalAttributeNameCache = {};
-var validatedAttributeNameCache = {};
-function isAttributeNameSafe(attributeName) {
- if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
- return true;
- }
- if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
- return false;
- }
- if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
- validatedAttributeNameCache[attributeName] = true;
- return true;
- }
- illegalAttributeNameCache[attributeName] = true;
- {
- warning$6(false, 'Invalid attribute name: `%s`', attributeName);
- }
- return false;
+function focusNode(node) {
+ // IE8 can throw "Can't move focus to the control because it is invisible,
+ // not enabled, or of a type that does not accept the focus." for all kinds of
+ // reasons that are too expensive and fragile to test.
+ try {
+ node.focus();
+ } catch (e) {}
}
-// shouldIgnoreValue() is currently duplicated in DOMMarkupOperations.
-// TODO: Find a better place for this.
-function shouldIgnoreValue(propertyInfo, value) {
- return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;
-}
+var focusNode_1 = focusNode;
/**
- * Operations for dealing with DOM properties.
+ * Given any node return the first leaf node without children.
+ *
+ * @param {DOMElement|DOMTextNode} node
+ * @return {DOMElement|DOMTextNode}
*/
-var DOMPropertyOperations = {
- setAttributeForID: function (node, id) {
- node.setAttribute(DOMProperty_1.ID_ATTRIBUTE_NAME, id);
- },
-
- setAttributeForRoot: function (node) {
- node.setAttribute(DOMProperty_1.ROOT_ATTRIBUTE_NAME, '');
- },
-
- /**
- * Get the value for a property on a node. Only used in DEV for SSR validation.
- * The "expected" argument is used as a hint of what the expected value is.
- * Some properties have multiple equivalent values.
- */
- getValueForProperty: function (node, name, expected) {
- {
- var propertyInfo = DOMProperty_1.getPropertyInfo(name);
- if (propertyInfo) {
- var mutationMethod = propertyInfo.mutationMethod;
- if (mutationMethod || propertyInfo.mustUseProperty) {
- return node[propertyInfo.propertyName];
- } else {
- var attributeName = propertyInfo.attributeName;
-
- var stringValue = null;
-
- if (propertyInfo.hasOverloadedBooleanValue) {
- if (node.hasAttribute(attributeName)) {
- var value = node.getAttribute(attributeName);
- if (value === '') {
- return true;
- }
- if (shouldIgnoreValue(propertyInfo, expected)) {
- return value;
- }
- if (value === '' + expected) {
- return expected;
- }
- return value;
- }
- } else if (node.hasAttribute(attributeName)) {
- if (shouldIgnoreValue(propertyInfo, expected)) {
- // We had an attribute but shouldn't have had one, so read it
- // for the error message.
- return node.getAttribute(attributeName);
- }
- if (propertyInfo.hasBooleanValue) {
- // If this was a boolean, it doesn't matter what the value is
- // the fact that we have it is the same as the expected.
- return expected;
- }
- // Even if this property uses a namespace we use getAttribute
- // because we assume its namespaced name is the same as our config.
- // To use getAttributeNS we need the local name which we don't have
- // in our config atm.
- stringValue = node.getAttribute(attributeName);
- }
-
- if (shouldIgnoreValue(propertyInfo, expected)) {
- return stringValue === null ? expected : stringValue;
- } else if (stringValue === '' + expected) {
- return expected;
- } else {
- return stringValue;
- }
- }
- }
- }
- },
-
- /**
- * Get the value for a attribute on a node. Only used in DEV for SSR validation.
- * The third argument is used as a hint of what the expected value is. Some
- * attributes have multiple equivalent values.
- */
- getValueForAttribute: function (node, name, expected) {
- {
- if (!isAttributeNameSafe(name)) {
- return;
- }
- if (!node.hasAttribute(name)) {
- return expected === undefined ? undefined : null;
- }
- var value = node.getAttribute(name);
- if (value === '' + expected) {
- return expected;
- }
- return value;
- }
- },
-
- /**
- * Sets the value for a property on a node.
- *
- * @param {DOMElement} node
- * @param {string} name
- * @param {*} value
- */
- setValueForProperty: function (node, name, value) {
- var propertyInfo = DOMProperty_1.getPropertyInfo(name);
-
- if (propertyInfo && DOMProperty_1.shouldSetAttribute(name, value)) {
- var mutationMethod = propertyInfo.mutationMethod;
- if (mutationMethod) {
- mutationMethod(node, value);
- } else if (shouldIgnoreValue(propertyInfo, value)) {
- DOMPropertyOperations.deleteValueForProperty(node, name);
- return;
- } else if (propertyInfo.mustUseProperty) {
- // Contrary to `setAttribute`, object properties are properly
- // `toString`ed by IE8/9.
- node[propertyInfo.propertyName] = value;
- } else {
- var attributeName = propertyInfo.attributeName;
- var namespace = propertyInfo.attributeNamespace;
- // `setAttribute` with objects becomes only `[object]` in IE8/9,
- // ('' + value) makes it output the correct toString()-value.
- if (namespace) {
- node.setAttributeNS(namespace, attributeName, '' + value);
- } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
- node.setAttribute(attributeName, '');
- } else {
- node.setAttribute(attributeName, '' + value);
- }
- }
- } else {
- DOMPropertyOperations.setValueForAttribute(node, name, DOMProperty_1.shouldSetAttribute(name, value) ? value : null);
- return;
- }
-
- {
- var payload = {};
- payload[name] = value;
- ReactInstrumentation.debugTool.onHostOperation({
- instanceID: ReactDOMComponentTree_1.getInstanceFromNode(node)._debugID,
- type: 'update attribute',
- payload: payload
- });
- }
- },
-
- setValueForAttribute: function (node, name, value) {
- if (!isAttributeNameSafe(name)) {
- return;
- }
- if (value == null) {
- node.removeAttribute(name);
- } else {
- node.setAttribute(name, '' + value);
- }
-
- {
- var payload = {};
- payload[name] = value;
- ReactInstrumentation.debugTool.onHostOperation({
- instanceID: ReactDOMComponentTree_1.getInstanceFromNode(node)._debugID,
- type: 'update attribute',
- payload: payload
- });
- }
- },
-
- /**
- * Deletes an attributes from a node.
- *
- * @param {DOMElement} node
- * @param {string} name
- */
- deleteValueForAttribute: function (node, name) {
- node.removeAttribute(name);
- {
- ReactInstrumentation.debugTool.onHostOperation({
- instanceID: ReactDOMComponentTree_1.getInstanceFromNode(node)._debugID,
- type: 'remove attribute',
- payload: name
- });
- }
- },
-
- /**
- * Deletes the value for a property on a node.
- *
- * @param {DOMElement} node
- * @param {string} name
- */
- deleteValueForProperty: function (node, name) {
- var propertyInfo = DOMProperty_1.getPropertyInfo(name);
- if (propertyInfo) {
- var mutationMethod = propertyInfo.mutationMethod;
- if (mutationMethod) {
- mutationMethod(node, undefined);
- } else if (propertyInfo.mustUseProperty) {
- var propName = propertyInfo.propertyName;
- if (propertyInfo.hasBooleanValue) {
- node[propName] = false;
- } else {
- node[propName] = '';
- }
- } else {
- node.removeAttribute(propertyInfo.attributeName);
- }
- } else {
- node.removeAttribute(name);
- }
-
- {
- ReactInstrumentation.debugTool.onHostOperation({
- instanceID: ReactDOMComponentTree_1.getInstanceFromNode(node)._debugID,
- type: 'remove attribute',
- payload: name
- });
- }
+function getLeafNode(node) {
+ while (node && node.firstChild) {
+ node = node.firstChild;
}
-};
-
-var DOMPropertyOperations_1 = DOMPropertyOperations;
-
-function createCommonjsModule(fn, module) {
- return module = { exports: {} }, fn(module, module.exports), module.exports;
+ return node;
}
/**
- * Copyright (c) 2013-present, Facebook, Inc.
+ * Get the next sibling within a container. This will walk up the
+ * DOM if a node's siblings have been exhausted.
*
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
+ * @param {DOMElement|DOMTextNode} node
+ * @return {?DOMElement|DOMTextNode}
*/
-
-var ReactPropTypesSecret$1 = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
-
-var ReactPropTypesSecret_1 = ReactPropTypesSecret$1;
-
-{
- var invariant$2 = invariant_1;
- var warning$11 = warning_1;
- var ReactPropTypesSecret$2 = ReactPropTypesSecret_1;
- var loggedTypeFailures$1 = {};
+function getSiblingNode(node) {
+ while (node) {
+ if (node.nextSibling) {
+ return node.nextSibling;
+ }
+ node = node.parentNode;
+ }
}
/**
- * Assert that the values match with the type specs.
- * Error messages are memorized and will only be shown once.
+ * Get object describing the nodes which contain characters at offset.
*
- * @param {object} typeSpecs Map of name to a ReactPropType
- * @param {object} values Runtime values that need to be type-checked
- * @param {string} location e.g. "prop", "context", "child context"
- * @param {string} componentName Name of the component for error messages.
- * @param {?Function} getStack Returns the component stack.
- * @private
+ * @param {DOMElement|DOMTextNode} root
+ * @param {number} offset
+ * @return {?object}
*/
-function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
- {
- for (var typeSpecName in typeSpecs) {
- if (typeSpecs.hasOwnProperty(typeSpecName)) {
- var error;
- // Prop type validation may throw. In case they do, we don't want to
- // fail the render phase where it didn't fail before. So we log it.
- // After these have been cleaned up, we'll let them throw.
- try {
- // This is intentionally an invariant that gets caught. It's the same
- // behavior as without this statement except with a better message.
- invariant$2(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'the `prop-types` package, but received `%s`.', componentName || 'React class', location, typeSpecName, typeof typeSpecs[typeSpecName]);
- error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret$2);
- } catch (ex) {
- error = ex;
- }
- warning$11(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error);
- if (error instanceof Error && !(error.message in loggedTypeFailures$1)) {
- // Only monitor this failure once because there tends to be a lot of the
- // same error.
- loggedTypeFailures$1[error.message] = true;
+function getNodeForCharacterOffset(root, offset) {
+ var node = getLeafNode(root);
+ var nodeStart = 0;
+ var nodeEnd = 0;
- var stack = getStack ? getStack() : '';
+ while (node) {
+ if (node.nodeType === TEXT_NODE) {
+ nodeEnd = nodeStart + node.textContent.length;
- warning$11(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : '');
- }
+ if (nodeStart <= offset && nodeEnd >= offset) {
+ return {
+ node: node,
+ offset: offset - nodeStart
+ };
}
- }
- }
-}
-
-var checkPropTypes_1 = checkPropTypes;
-
-var factoryWithTypeCheckers = function(isValidElement, throwOnDirectAccess) {
- /* global Symbol */
- var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
- var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
-
- /**
- * Returns the iterator method function contained on the iterable object.
- *
- * Be sure to invoke the function with the iterable as context:
- *
- * var iteratorFn = getIteratorFn(myIterable);
- * if (iteratorFn) {
- * var iterator = iteratorFn.call(myIterable);
- * ...
- * }
- *
- * @param {?object} maybeIterable
- * @return {?function}
- */
- function getIteratorFn(maybeIterable) {
- var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
- if (typeof iteratorFn === 'function') {
- return iteratorFn;
- }
- }
-
- /**
- * Collection of methods that allow declaration and validation of props that are
- * supplied to React components. Example usage:
- *
- * var Props = require('ReactPropTypes');
- * var MyArticle = React.createClass({
- * propTypes: {
- * // An optional string prop named "description".
- * description: Props.string,
- *
- * // A required enum prop named "category".
- * category: Props.oneOf(['News','Photos']).isRequired,
- *
- * // A prop named "dialog" that requires an instance of Dialog.
- * dialog: Props.instanceOf(Dialog).isRequired
- * },
- * render: function() { ... }
- * });
- *
- * A more formal specification of how these methods are used:
- *
- * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
- * decl := ReactPropTypes.{type}(.isRequired)?
- *
- * Each and every declaration produces a function with the same signature. This
- * allows the creation of custom validation functions. For example:
- *
- * var MyLink = React.createClass({
- * propTypes: {
- * // An optional string or URI prop named "href".
- * href: function(props, propName, componentName) {
- * var propValue = props[propName];
- * if (propValue != null && typeof propValue !== 'string' &&
- * !(propValue instanceof URI)) {
- * return new Error(
- * 'Expected a string or an URI for ' + propName + ' in ' +
- * componentName
- * );
- * }
- * }
- * },
- * render: function() {...}
- * });
- *
- * @internal
- */
-
- var ANONYMOUS = '<<anonymous>>';
-
- // Important!
- // Keep this list in sync with production version in `./factoryWithThrowingShims.js`.
- var ReactPropTypes = {
- array: createPrimitiveTypeChecker('array'),
- bool: createPrimitiveTypeChecker('boolean'),
- func: createPrimitiveTypeChecker('function'),
- number: createPrimitiveTypeChecker('number'),
- object: createPrimitiveTypeChecker('object'),
- string: createPrimitiveTypeChecker('string'),
- symbol: createPrimitiveTypeChecker('symbol'),
-
- any: createAnyTypeChecker(),
- arrayOf: createArrayOfTypeChecker,
- element: createElementTypeChecker(),
- instanceOf: createInstanceTypeChecker,
- node: createNodeChecker(),
- objectOf: createObjectOfTypeChecker,
- oneOf: createEnumTypeChecker,
- oneOfType: createUnionTypeChecker,
- shape: createShapeTypeChecker,
- exact: createStrictShapeTypeChecker,
- };
-
- /**
- * inlined Object.is polyfill to avoid requiring consumers ship their own
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
- */
- /*eslint-disable no-self-compare*/
- function is(x, y) {
- // SameValue algorithm
- if (x === y) {
- // Steps 1-5, 7-10
- // Steps 6.b-6.e: +0 != -0
- return x !== 0 || 1 / x === 1 / y;
- } else {
- // Step 6.a: NaN == NaN
- return x !== x && y !== y;
- }
- }
- /*eslint-enable no-self-compare*/
- /**
- * We use an Error-like object for backward compatibility as people may call
- * PropTypes directly and inspect their output. However, we don't use real
- * Errors anymore. We don't inspect their stack anyway, and creating them
- * is prohibitively expensive if they are created too often, such as what
- * happens in oneOfType() for any type before the one that matched.
- */
- function PropTypeError(message) {
- this.message = message;
- this.stack = '';
- }
- // Make `instanceof Error` still work for returned errors.
- PropTypeError.prototype = Error.prototype;
-
- function createChainableTypeChecker(validate) {
- {
- var manualPropTypeCallCache = {};
- var manualPropTypeWarningCount = 0;
- }
- function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
- componentName = componentName || ANONYMOUS;
- propFullName = propFullName || propName;
-
- if (secret !== ReactPropTypesSecret_1) {
- if (throwOnDirectAccess) {
- // New behavior only for users of `prop-types` package
- invariant_1(
- false,
- 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
- 'Use `PropTypes.checkPropTypes()` to call them. ' +
- 'Read more at http://fb.me/use-check-prop-types'
- );
- } else if ('development' !== 'production' && typeof console !== 'undefined') {
- // Old behavior for people using React.PropTypes
- var cacheKey = componentName + ':' + propName;
- if (
- !manualPropTypeCallCache[cacheKey] &&
- // Avoid spamming the console because they are often not actionable except for lib authors
- manualPropTypeWarningCount < 3
- ) {
- warning_1(
- false,
- 'You are manually calling a React.PropTypes validation ' +
- 'function for the `%s` prop on `%s`. This is deprecated ' +
- 'and will throw in the standalone `prop-types` package. ' +
- 'You may be seeing this warning due to a third-party PropTypes ' +
- 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.',
- propFullName,
- componentName
- );
- manualPropTypeCallCache[cacheKey] = true;
- manualPropTypeWarningCount++;
- }
- }
- }
- if (props[propName] == null) {
- if (isRequired) {
- if (props[propName] === null) {
- return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
- }
- return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
- }
- return null;
- } else {
- return validate(props, propName, componentName, location, propFullName);
- }
+ nodeStart = nodeEnd;
}
- var chainedCheckType = checkType.bind(null, false);
- chainedCheckType.isRequired = checkType.bind(null, true);
-
- return chainedCheckType;
+ node = getLeafNode(getSiblingNode(node));
}
+}
- function createPrimitiveTypeChecker(expectedType) {
- function validate(props, propName, componentName, location, propFullName, secret) {
- var propValue = props[propName];
- var propType = getPropType(propValue);
- if (propType !== expectedType) {
- // `propValue` being instance of, say, date/regexp, pass the 'object'
- // check, but we can offer a more precise error message here rather than
- // 'of type `object`'.
- var preciseType = getPreciseType(propValue);
-
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));
- }
- return null;
- }
- return createChainableTypeChecker(validate);
- }
+/**
+ * @param {DOMElement} outerNode
+ * @return {?object}
+ */
+function getOffsets(outerNode) {
+ var selection = window.getSelection && window.getSelection();
- function createAnyTypeChecker() {
- return createChainableTypeChecker(emptyFunction_1.thatReturnsNull);
+ if (!selection || selection.rangeCount === 0) {
+ return null;
}
- function createArrayOfTypeChecker(typeChecker) {
- function validate(props, propName, componentName, location, propFullName) {
- if (typeof typeChecker !== 'function') {
- return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');
- }
- var propValue = props[propName];
- if (!Array.isArray(propValue)) {
- var propType = getPropType(propValue);
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
- }
- for (var i = 0; i < propValue.length; i++) {
- var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret_1);
- if (error instanceof Error) {
- return error;
- }
- }
- return null;
- }
- return createChainableTypeChecker(validate);
- }
+ var anchorNode = selection.anchorNode,
+ anchorOffset = selection.anchorOffset,
+ focusNode = selection.focusNode,
+ focusOffset = selection.focusOffset;
- function createElementTypeChecker() {
- function validate(props, propName, componentName, location, propFullName) {
- var propValue = props[propName];
- if (!isValidElement(propValue)) {
- var propType = getPropType(propValue);
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));
- }
- return null;
- }
- return createChainableTypeChecker(validate);
- }
+ // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the
+ // up/down buttons on an <input type="number">. Anonymous divs do not seem to
+ // expose properties, triggering a "Permission denied error" if any of its
+ // properties are accessed. The only seemingly possible way to avoid erroring
+ // is to access a property that typically works for non-anonymous divs and
+ // catch any error that may otherwise arise. See
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
- function createInstanceTypeChecker(expectedClass) {
- function validate(props, propName, componentName, location, propFullName) {
- if (!(props[propName] instanceof expectedClass)) {
- var expectedClassName = expectedClass.name || ANONYMOUS;
- var actualClassName = getClassName(props[propName]);
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
- }
- return null;
- }
- return createChainableTypeChecker(validate);
+ try {
+ /* eslint-disable no-unused-expressions */
+ anchorNode.nodeType;
+ focusNode.nodeType;
+ /* eslint-enable no-unused-expressions */
+ } catch (e) {
+ return null;
}
- function createEnumTypeChecker(expectedValues) {
- if (!Array.isArray(expectedValues)) {
- warning_1(false, 'Invalid argument supplied to oneOf, expected an instance of array.');
- return emptyFunction_1.thatReturnsNull;
- }
+ return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset);
+}
- function validate(props, propName, componentName, location, propFullName) {
- var propValue = props[propName];
- for (var i = 0; i < expectedValues.length; i++) {
- if (is(propValue, expectedValues[i])) {
- return null;
- }
- }
+/**
+ * Returns {start, end} where `start` is the character/codepoint index of
+ * (anchorNode, anchorOffset) within the textContent of `outerNode`, and
+ * `end` is the index of (focusNode, focusOffset).
+ *
+ * Returns null if you pass in garbage input but we should probably just crash.
+ *
+ * Exported only for testing.
+ */
+function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) {
+ var length = 0;
+ var start = -1;
+ var end = -1;
+ var indexWithinAnchor = 0;
+ var indexWithinFocus = 0;
+ var node = outerNode;
+ var parentNode = null;
- var valuesString = JSON.stringify(expectedValues);
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
- }
- return createChainableTypeChecker(validate);
- }
+ outer: while (true) {
+ var next = null;
- function createObjectOfTypeChecker(typeChecker) {
- function validate(props, propName, componentName, location, propFullName) {
- if (typeof typeChecker !== 'function') {
- return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
+ while (true) {
+ if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) {
+ start = length + anchorOffset;
}
- var propValue = props[propName];
- var propType = getPropType(propValue);
- if (propType !== 'object') {
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
+ if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) {
+ end = length + focusOffset;
}
- for (var key in propValue) {
- if (propValue.hasOwnProperty(key)) {
- var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret_1);
- if (error instanceof Error) {
- return error;
- }
- }
- }
- return null;
- }
- return createChainableTypeChecker(validate);
- }
-
- function createUnionTypeChecker(arrayOfTypeCheckers) {
- if (!Array.isArray(arrayOfTypeCheckers)) {
- warning_1(false, 'Invalid argument supplied to oneOfType, expected an instance of array.');
- return emptyFunction_1.thatReturnsNull;
- }
- for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
- var checker = arrayOfTypeCheckers[i];
- if (typeof checker !== 'function') {
- warning_1(
- false,
- 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +
- 'received %s at index %s.',
- getPostfixForTypeWarning(checker),
- i
- );
- return emptyFunction_1.thatReturnsNull;
+ if (node.nodeType === TEXT_NODE) {
+ length += node.nodeValue.length;
}
- }
- function validate(props, propName, componentName, location, propFullName) {
- for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
- var checker = arrayOfTypeCheckers[i];
- if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret_1) == null) {
- return null;
- }
+ if ((next = node.firstChild) === null) {
+ break;
}
-
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));
+ // Moving from `node` to its first child `next`.
+ parentNode = node;
+ node = next;
}
- return createChainableTypeChecker(validate);
- }
- function createNodeChecker() {
- function validate(props, propName, componentName, location, propFullName) {
- if (!isNode(props[propName])) {
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
+ while (true) {
+ if (node === outerNode) {
+ // If `outerNode` has children, this is always the second time visiting
+ // it. If it has no children, this is still the first loop, and the only
+ // valid selection is anchorNode and focusNode both equal to this node
+ // and both offsets 0, in which case we will have handled above.
+ break outer;
}
- return null;
- }
- return createChainableTypeChecker(validate);
- }
-
- function createShapeTypeChecker(shapeTypes) {
- function validate(props, propName, componentName, location, propFullName) {
- var propValue = props[propName];
- var propType = getPropType(propValue);
- if (propType !== 'object') {
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
+ if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) {
+ start = length;
}
- for (var key in shapeTypes) {
- var checker = shapeTypes[key];
- if (!checker) {
- continue;
- }
- var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret_1);
- if (error) {
- return error;
- }
+ if (parentNode === focusNode && ++indexWithinFocus === focusOffset) {
+ end = length;
}
- return null;
- }
- return createChainableTypeChecker(validate);
- }
-
- function createStrictShapeTypeChecker(shapeTypes) {
- function validate(props, propName, componentName, location, propFullName) {
- var propValue = props[propName];
- var propType = getPropType(propValue);
- if (propType !== 'object') {
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
- }
- // We need to check all keys in case some are required but missing from
- // props.
- var allKeys = assign({}, props[propName], shapeTypes);
- for (var key in allKeys) {
- var checker = shapeTypes[key];
- if (!checker) {
- return new PropTypeError(
- 'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +
- '\nBad object: ' + JSON.stringify(props[propName], null, ' ') +
- '\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ')
- );
- }
- var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret_1);
- if (error) {
- return error;
- }
+ if ((next = node.nextSibling) !== null) {
+ break;
}
- return null;
+ node = parentNode;
+ parentNode = node.parentNode;
}
- return createChainableTypeChecker(validate);
+ // Moving from `node` to its next sibling `next`.
+ node = next;
}
- function isNode(propValue) {
- switch (typeof propValue) {
- case 'number':
- case 'string':
- case 'undefined':
- return true;
- case 'boolean':
- return !propValue;
- case 'object':
- if (Array.isArray(propValue)) {
- return propValue.every(isNode);
- }
- if (propValue === null || isValidElement(propValue)) {
- return true;
- }
-
- var iteratorFn = getIteratorFn(propValue);
- if (iteratorFn) {
- var iterator = iteratorFn.call(propValue);
- var step;
- if (iteratorFn !== propValue.entries) {
- while (!(step = iterator.next()).done) {
- if (!isNode(step.value)) {
- return false;
- }
- }
- } else {
- // Iterator will provide entry [k,v] tuples rather than values.
- while (!(step = iterator.next()).done) {
- var entry = step.value;
- if (entry) {
- if (!isNode(entry[1])) {
- return false;
- }
- }
- }
- }
- } else {
- return false;
- }
-
- return true;
- default:
- return false;
- }
+ if (start === -1 || end === -1) {
+ // This should never happen. (Would happen if the anchor/focus nodes aren't
+ // actually inside the passed-in node.)
+ return null;
}
- function isSymbol(propType, propValue) {
- // Native Symbol.
- if (propType === 'symbol') {
- return true;
- }
-
- // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
- if (propValue['@@toStringTag'] === 'Symbol') {
- return true;
- }
-
- // Fallback for non-spec compliant Symbols which are polyfilled.
- if (typeof Symbol === 'function' && propValue instanceof Symbol) {
- return true;
- }
+ return {
+ start: start,
+ end: end
+ };
+}
- return false;
+/**
+ * In modern non-IE browsers, we can support both forward and backward
+ * selections.
+ *
+ * Note: IE10+ supports the Selection object, but it does not support
+ * the `extend` method, which means that even in modern IE, it's not possible
+ * to programmatically create a backward selection. Thus, for all IE
+ * versions, we use the old IE API to create our selections.
+ *
+ * @param {DOMElement|DOMTextNode} node
+ * @param {object} offsets
+ */
+function setOffsets(node, offsets) {
+ if (!window.getSelection) {
+ return;
}
- // Equivalent of `typeof` but with special handling for array and regexp.
- function getPropType(propValue) {
- var propType = typeof propValue;
- if (Array.isArray(propValue)) {
- return 'array';
- }
- if (propValue instanceof RegExp) {
- // Old webkits (at least until Android 4.0) return 'function' rather than
- // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
- // passes PropTypes.object.
- return 'object';
- }
- if (isSymbol(propType, propValue)) {
- return 'symbol';
- }
- return propType;
- }
+ var selection = window.getSelection();
+ var length = node[getTextContentAccessor()].length;
+ var start = Math.min(offsets.start, length);
+ var end = offsets.end === undefined ? start : Math.min(offsets.end, length);
- // This handles more types than `getPropType`. Only used for error messages.
- // See `createPrimitiveTypeChecker`.
- function getPreciseType(propValue) {
- if (typeof propValue === 'undefined' || propValue === null) {
- return '' + propValue;
- }
- var propType = getPropType(propValue);
- if (propType === 'object') {
- if (propValue instanceof Date) {
- return 'date';
- } else if (propValue instanceof RegExp) {
- return 'regexp';
- }
- }
- return propType;
+ // IE 11 uses modern selection, but doesn't support the extend method.
+ // Flip backward selections, so we can set with a single range.
+ if (!selection.extend && start > end) {
+ var temp = end;
+ end = start;
+ start = temp;
}
- // Returns a string that is postfixed to a warning about an invalid type.
- // For example, "undefined" or "of type array"
- function getPostfixForTypeWarning(value) {
- var type = getPreciseType(value);
- switch (type) {
- case 'array':
- case 'object':
- return 'an ' + type;
- case 'boolean':
- case 'date':
- case 'regexp':
- return 'a ' + type;
- default:
- return type;
+ var startMarker = getNodeForCharacterOffset(node, start);
+ var endMarker = getNodeForCharacterOffset(node, end);
+
+ if (startMarker && endMarker) {
+ if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) {
+ return;
}
- }
+ var range = document.createRange();
+ range.setStart(startMarker.node, startMarker.offset);
+ selection.removeAllRanges();
- // Returns class name of the object, if any.
- function getClassName(propValue) {
- if (!propValue.constructor || !propValue.constructor.name) {
- return ANONYMOUS;
+ if (start > end) {
+ selection.addRange(range);
+ selection.extend(endMarker.node, endMarker.offset);
+ } else {
+ range.setEnd(endMarker.node, endMarker.offset);
+ selection.addRange(range);
}
- return propValue.constructor.name;
}
+}
- ReactPropTypes.checkPropTypes = checkPropTypes_1;
- ReactPropTypes.PropTypes = ReactPropTypes;
-
- return ReactPropTypes;
-};
+function isInDocument(node) {
+ return containsNode_1(document.documentElement, node);
+}
-var index = createCommonjsModule(function (module) {
/**
- * 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.
+ * @ReactInputSelection: React input selection module. Based on Selection.js,
+ * but modified to be suitable for react and has a couple of bug fixes (doesn't
+ * assume buttons have range selections allowed).
+ * Input selection module for React.
*/
-{
- var REACT_ELEMENT_TYPE = (typeof Symbol === 'function' &&
- Symbol.for &&
- Symbol.for('react.element')) ||
- 0xeac7;
-
- var isValidElement = function(object) {
- return typeof object === 'object' &&
- object !== null &&
- object.$$typeof === REACT_ELEMENT_TYPE;
- };
-
- // By explicitly using `prop-types` you are opting into new development behavior.
- // http://fb.me/prop-types-in-prod
- var throwOnDirectAccess = true;
- module.exports = factoryWithTypeCheckers(isValidElement, throwOnDirectAccess);
+function hasSelectionCapabilities(elem) {
+ var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
+ return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');
}
-});
-var ReactControlledValuePropTypes = {
- checkPropTypes: null
-};
-
-{
- var warning$10 = warning_1;
- var emptyFunction$2 = emptyFunction_1;
- var PropTypes = index;
- var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
-
- ReactControlledValuePropTypes.checkPropTypes = emptyFunction$2;
- var hasReadOnlyValue = {
- button: true,
- checkbox: true,
- image: true,
- hidden: true,
- radio: true,
- reset: true,
- submit: true
- };
-
- var propTypes = {
- value: function (props, propName, componentName) {
- if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {
- return null;
- }
- return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
- },
- checked: function (props, propName, componentName) {
- if (!props[propName] || props.onChange || props.readOnly || props.disabled) {
- return null;
- }
- return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
- },
- onChange: PropTypes.func
- };
-
- var loggedTypeFailures = {};
-
- /**
- * Provide a linked `value` attribute for controlled forms. You should not use
- * this outside of the ReactDOM controlled form components.
- */
- ReactControlledValuePropTypes.checkPropTypes = function (tagName, props, getStack) {
- for (var propName in propTypes) {
- if (propTypes.hasOwnProperty(propName)) {
- var error = propTypes[propName](props, propName, tagName, 'prop', null, ReactPropTypesSecret);
- }
- if (error instanceof Error && !(error.message in loggedTypeFailures)) {
- // Only monitor this failure once because there tends to be a lot of the
- // same error.
- loggedTypeFailures[error.message] = true;
-
- warning$10(false, 'Failed form propType: %s%s', error.message, getStack());
- }
- }
+function getSelectionInformation() {
+ var focusedElem = getActiveElement_1();
+ return {
+ focusedElem: focusedElem,
+ selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection$1(focusedElem) : null
};
}
-var ReactControlledValuePropTypes_1 = ReactControlledValuePropTypes;
-
-var getCurrentFiberOwnerName$3 = ReactDebugCurrentFiber_1.getCurrentFiberOwnerName;
-
-{
- var _require2$3 = ReactDebugCurrentFiber_1,
- getCurrentFiberStackAddendum$2 = _require2$3.getCurrentFiberStackAddendum;
-
- var warning$9 = warning_1;
-}
-
-
-
-var didWarnValueDefaultValue = false;
-var didWarnCheckedDefaultChecked = false;
-var didWarnControlledToUncontrolled = false;
-var didWarnUncontrolledToControlled = false;
-
-function isControlled(props) {
- var usesChecked = props.type === 'checkbox' || props.type === 'radio';
- return usesChecked ? props.checked != null : props.value != null;
-}
-
/**
- * Implements an <input> host component that allows setting these optional
- * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
- *
- * If `checked` or `value` are not supplied (or null/undefined), user actions
- * that affect the checked state or value will trigger updates to the element.
- *
- * If they are supplied (and not null/undefined), the rendered element will not
- * trigger updates to the element. Instead, the props must change in order for
- * the rendered element to be updated.
- *
- * The rendered element will be initialized as unchecked (or `defaultChecked`)
- * with an empty value (or `defaultValue`).
- *
- * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
+ * @restoreSelection: If any selection information was potentially lost,
+ * restore it. This is useful when performing operations that could remove dom
+ * nodes and place them back in, resulting in focus being lost.
*/
-var ReactDOMInput = {
- getHostProps: function (element, props) {
- var node = element;
- var value = props.value;
- var checked = props.checked;
-
- var hostProps = assign({
- // Make sure we set .type before any other properties (setting .value
- // before .type means .value is lost in IE11 and below)
- type: undefined,
- // Make sure we set .step before .value (setting .value before .step
- // means .value is rounded on mount, based upon step precision)
- step: undefined,
- // Make sure we set .min & .max before .value (to ensure proper order
- // in corner cases such as min or max deriving from value, e.g. Issue #7170)
- min: undefined,
- max: undefined
- }, props, {
- defaultChecked: undefined,
- defaultValue: undefined,
- value: value != null ? value : node._wrapperState.initialValue,
- checked: checked != null ? checked : node._wrapperState.initialChecked
- });
-
- return hostProps;
- },
-
- initWrapperState: function (element, props) {
- {
- ReactControlledValuePropTypes_1.checkPropTypes('input', props, getCurrentFiberStackAddendum$2);
-
- if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
- warning$9(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', getCurrentFiberOwnerName$3() || 'A component', props.type);
- didWarnCheckedDefaultChecked = true;
- }
- if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
- warning$9(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', getCurrentFiberOwnerName$3() || 'A component', props.type);
- didWarnValueDefaultValue = true;
- }
- }
-
- var defaultValue = props.defaultValue;
- var node = element;
- node._wrapperState = {
- initialChecked: props.checked != null ? props.checked : props.defaultChecked,
- initialValue: props.value != null ? props.value : defaultValue,
- controlled: isControlled(props)
- };
- },
-
- updateWrapper: function (element, props) {
- var node = element;
- {
- var controlled = isControlled(props);
-
- if (!node._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
- warning$9(false, 'A component is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components%s', props.type, getCurrentFiberStackAddendum$2());
- didWarnUncontrolledToControlled = true;
- }
- if (node._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
- warning$9(false, 'A component is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components%s', props.type, getCurrentFiberStackAddendum$2());
- didWarnControlledToUncontrolled = true;
- }
+function restoreSelection(priorSelectionInformation) {
+ var curFocusedElem = getActiveElement_1();
+ var priorFocusedElem = priorSelectionInformation.focusedElem;
+ var priorSelectionRange = priorSelectionInformation.selectionRange;
+ if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
+ if (hasSelectionCapabilities(priorFocusedElem)) {
+ setSelection(priorFocusedElem, priorSelectionRange);
}
- var checked = props.checked;
- if (checked != null) {
- DOMPropertyOperations_1.setValueForProperty(node, 'checked', checked || false);
- }
-
- var value = props.value;
- if (value != null) {
- if (value === 0 && node.value === '') {
- node.value = '0';
- // Note: IE9 reports a number inputs as 'text', so check props instead.
- } else if (props.type === 'number') {
- // Simulate `input.valueAsNumber`. IE9 does not support it
- var valueAsNumber = parseFloat(node.value) || 0;
-
- if (
- // eslint-disable-next-line
- value != valueAsNumber ||
- // eslint-disable-next-line
- value == valueAsNumber && node.value != value) {
- // Cast `value` to a string to ensure the value is set correctly. While
- // browsers typically do this as necessary, jsdom doesn't.
- node.value = '' + value;
- }
- } else if (node.value !== '' + value) {
- // Cast `value` to a string to ensure the value is set correctly. While
- // browsers typically do this as necessary, jsdom doesn't.
- node.value = '' + value;
- }
- } else {
- if (props.value == null && props.defaultValue != null) {
- // In Chrome, assigning defaultValue to certain input types triggers input validation.
- // For number inputs, the display value loses trailing decimal points. For email inputs,
- // Chrome raises "The specified value <x> is not a valid email address".
- //
- // Here we check to see if the defaultValue has actually changed, avoiding these problems
- // when the user is inputting text
- //
- // https://github.com/facebook/react/issues/7253
- if (node.defaultValue !== '' + props.defaultValue) {
- node.defaultValue = '' + props.defaultValue;
- }
- }
- if (props.checked == null && props.defaultChecked != null) {
- node.defaultChecked = !!props.defaultChecked;
+ // Focusing a node can change the scroll position, which is undesirable
+ var ancestors = [];
+ var ancestor = priorFocusedElem;
+ while (ancestor = ancestor.parentNode) {
+ if (ancestor.nodeType === ELEMENT_NODE) {
+ ancestors.push({
+ element: ancestor,
+ left: ancestor.scrollLeft,
+ top: ancestor.scrollTop
+ });
}
}
- },
-
- postMountWrapper: function (element, props) {
- var node = element;
- // Detach value from defaultValue. We won't do anything if we're working on
- // submit or reset inputs as those values & defaultValues are linked. They
- // are not resetable nodes so this operation doesn't matter and actually
- // removes browser-default values (eg "Submit Query") when no value is
- // provided.
+ focusNode_1(priorFocusedElem);
- switch (props.type) {
- case 'submit':
- case 'reset':
- break;
- case 'color':
- case 'date':
- case 'datetime':
- case 'datetime-local':
- case 'month':
- case 'time':
- case 'week':
- // This fixes the no-show issue on iOS Safari and Android Chrome:
- // https://github.com/facebook/react/issues/7233
- node.value = '';
- node.value = node.defaultValue;
- break;
- default:
- node.value = node.value;
- break;
- }
-
- // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
- // this is needed to work around a chrome bug where setting defaultChecked
- // will sometimes influence the value of checked (even after detachment).
- // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
- // We need to temporarily unset name to avoid disrupting radio button groups.
- var name = node.name;
- if (name !== '') {
- node.name = '';
- }
- node.defaultChecked = !node.defaultChecked;
- node.defaultChecked = !node.defaultChecked;
- if (name !== '') {
- node.name = name;
- }
- },
-
- restoreControlledState: function (element, props) {
- var node = element;
- ReactDOMInput.updateWrapper(node, props);
- updateNamedCousins(node, props);
- }
-};
-
-function updateNamedCousins(rootNode, props) {
- var name = props.name;
- if (props.type === 'radio' && name != null) {
- var queryRoot = rootNode;
-
- while (queryRoot.parentNode) {
- queryRoot = queryRoot.parentNode;
- }
-
- // If `rootNode.form` was non-null, then we could try `form.elements`,
- // but that sometimes behaves strangely in IE8. We could also try using
- // `form.getElementsByName`, but that will only return direct children
- // and won't include inputs that use the HTML5 `form=` attribute. Since
- // the input might not even be in a form. It might not even be in the
- // document. Let's just use the local `querySelectorAll` to ensure we don't
- // miss anything.
- var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
-
- for (var i = 0; i < group.length; i++) {
- var otherNode = group[i];
- if (otherNode === rootNode || otherNode.form !== rootNode.form) {
- continue;
- }
- // This will throw if radio buttons rendered by different copies of React
- // and the same name are rendered into the same form (same as #1939).
- // That's probably okay; we don't support it just as we don't support
- // mixing React radio buttons with non-React ones.
- var otherProps = ReactDOMComponentTree_1.getFiberCurrentPropsFromNode(otherNode);
- !otherProps ? invariant_1(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : void 0;
- // If this is a controlled radio button group, forcing the input that
- // was previously checked to update will cause it to be come re-checked
- // as appropriate.
- ReactDOMInput.updateWrapper(otherNode, otherProps);
+ for (var i = 0; i < ancestors.length; i++) {
+ var info = ancestors[i];
+ info.element.scrollLeft = info.left;
+ info.element.scrollTop = info.top;
}
}
}
-var ReactDOMFiberInput = ReactDOMInput;
-
-{
- var warning$12 = warning_1;
-}
-
-function flattenChildren(children) {
- var content = '';
-
- // Flatten children and warn if they aren't strings or numbers;
- // invalid types are ignored.
- // We can silently skip them because invalid DOM nesting warning
- // catches these cases in Fiber.
- require$$0.Children.forEach(children, function (child) {
- if (child == null) {
- return;
- }
- if (typeof child === 'string' || typeof child === 'number') {
- content += child;
- }
- });
-
- return content;
-}
-
/**
- * Implements an <option> host component that warns when `selected` is set.
+ * @getSelection: Gets the selection bounds of a focused textarea, input or
+ * contentEditable node.
+ * -@input: Look up selection bounds of this input
+ * -@return {start: selectionStart, end: selectionEnd}
*/
-var ReactDOMOption = {
- validateProps: function (element, props) {
- // TODO (yungsters): Remove support for `selected` in <option>.
- {
- warning$12(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.');
- }
- },
-
- postMountWrapper: function (element, props) {
- // value="" should make a value attribute (#6219)
- if (props.value != null) {
- element.setAttribute('value', props.value);
- }
- },
-
- getHostProps: function (element, props) {
- var hostProps = assign({ children: undefined }, props);
-
- var content = flattenChildren(props.children);
-
- if (content) {
- hostProps.children = content;
- }
+function getSelection$1(input) {
+ var selection = void 0;
- return hostProps;
+ if ('selectionStart' in input) {
+ // Modern browser with input or textarea.
+ selection = {
+ start: input.selectionStart,
+ end: input.selectionEnd
+ };
+ } else {
+ // Content editable or old IE textarea.
+ selection = getOffsets(input);
}
-};
-
-var ReactDOMFiberOption = ReactDOMOption;
-
-var getCurrentFiberOwnerName$4 = ReactDebugCurrentFiber_1.getCurrentFiberOwnerName;
-
-{
- var didWarnValueDefaultValue$1 = false;
- var warning$13 = warning_1;
-
- var _require2$4 = ReactDebugCurrentFiber_1,
- getCurrentFiberStackAddendum$3 = _require2$4.getCurrentFiberStackAddendum;
-}
-function getDeclarationErrorAddendum() {
- var ownerName = getCurrentFiberOwnerName$4();
- if (ownerName) {
- return '\n\nCheck the render method of `' + ownerName + '`.';
- }
- return '';
+ return selection || { start: 0, end: 0 };
}
-var valuePropNames = ['value', 'defaultValue'];
-
/**
- * Validation function for `value` and `defaultValue`.
+ * @setSelection: Sets the selection bounds of a textarea or input and focuses
+ * the input.
+ * -@input Set selection bounds of this input or textarea
+ * -@offsets Object of same form that is returned from get*
*/
-function checkSelectPropTypes(props) {
- ReactControlledValuePropTypes_1.checkPropTypes('select', props, getCurrentFiberStackAddendum$3);
+function setSelection(input, offsets) {
+ var start = offsets.start,
+ end = offsets.end;
- for (var i = 0; i < valuePropNames.length; i++) {
- var propName = valuePropNames[i];
- if (props[propName] == null) {
- continue;
- }
- var isArray = Array.isArray(props[propName]);
- if (props.multiple && !isArray) {
- warning$13(false, 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum());
- } else if (!props.multiple && isArray) {
- warning$13(false, 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum());
- }
+ if (end === undefined) {
+ end = start;
}
-}
-function updateOptions(node, multiple, propValue) {
- var options = node.options;
-
- if (multiple) {
- var selectedValues = propValue;
- var selectedValue = {};
- for (var i = 0; i < selectedValues.length; i++) {
- // Prefix to avoid chaos with special keys.
- selectedValue['$' + selectedValues[i]] = true;
- }
- for (var _i = 0; _i < options.length; _i++) {
- var selected = selectedValue.hasOwnProperty('$' + options[_i].value);
- if (options[_i].selected !== selected) {
- options[_i].selected = selected;
- }
- }
+ if ('selectionStart' in input) {
+ input.selectionStart = start;
+ input.selectionEnd = Math.min(end, input.value.length);
} else {
- // Do not set `select.value` as exact behavior isn't consistent across all
- // browsers for all cases.
- var _selectedValue = '' + propValue;
- var defaultSelected = null;
- for (var _i2 = 0; _i2 < options.length; _i2++) {
- if (options[_i2].value === _selectedValue) {
- options[_i2].selected = true;
- return;
- }
- if (defaultSelected === null && !options[_i2].disabled) {
- defaultSelected = options[_i2];
- }
- }
- if (defaultSelected !== null) {
- defaultSelected.selected = true;
- }
+ setOffsets(input, offsets);
}
}
-/**
- * Implements a <select> host component that allows optionally setting the
- * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
- * stringable. If `multiple` is true, the prop must be an array of stringables.
- *
- * If `value` is not supplied (or null/undefined), user actions that change the
- * selected option will trigger updates to the rendered options.
- *
- * If it is supplied (and not null/undefined), the rendered options will not
- * update in response to user actions. Instead, the `value` prop must change in
- * order for the rendered options to update.
- *
- * If `defaultValue` is provided, any options with the supplied values will be
- * selected.
- */
-var ReactDOMSelect = {
- getHostProps: function (element, props) {
- return assign({}, props, {
- value: undefined
- });
- },
-
- initWrapperState: function (element, props) {
- var node = element;
- {
- checkSelectPropTypes(props);
- }
-
- var value = props.value;
- node._wrapperState = {
- initialValue: value != null ? value : props.defaultValue,
- wasMultiple: !!props.multiple
- };
-
- {
- if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) {
- warning$13(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components');
- didWarnValueDefaultValue$1 = true;
- }
- }
- },
-
- postMountWrapper: function (element, props) {
- var node = element;
- node.multiple = !!props.multiple;
- var value = props.value;
- if (value != null) {
- updateOptions(node, !!props.multiple, value);
- } else if (props.defaultValue != null) {
- updateOptions(node, !!props.multiple, props.defaultValue);
- }
- },
-
- postUpdateWrapper: function (element, props) {
- var node = element;
- // After the initial mount, we control selected-ness manually so don't pass
- // this value down
- node._wrapperState.initialValue = undefined;
-
- var wasMultiple = node._wrapperState.wasMultiple;
- node._wrapperState.wasMultiple = !!props.multiple;
-
- var value = props.value;
- if (value != null) {
- updateOptions(node, !!props.multiple, value);
- } else if (wasMultiple !== !!props.multiple) {
- // For simplicity, reapply `defaultValue` if `multiple` is toggled.
- if (props.defaultValue != null) {
- updateOptions(node, !!props.multiple, props.defaultValue);
- } else {
- // Revert the select back to its default unselected state.
- updateOptions(node, !!props.multiple, props.multiple ? [] : '');
- }
- }
- },
-
- restoreControlledState: function (element, props) {
- var node = element;
- var value = props.value;
+var skipSelectionChangeEvent = ExecutionEnvironment_1.canUseDOM && 'documentMode' in document && document.documentMode <= 11;
- if (value != null) {
- updateOptions(node, !!props.multiple, value);
- }
+var eventTypes$3 = {
+ select: {
+ phasedRegistrationNames: {
+ bubbled: 'onSelect',
+ captured: 'onSelectCapture'
+ },
+ dependencies: ['topBlur', 'topContextMenu', 'topFocus', 'topKeyDown', 'topKeyUp', 'topMouseDown', 'topMouseUp', 'topSelectionChange']
}
};
-var ReactDOMFiberSelect = ReactDOMSelect;
-
-{
- var warning$14 = warning_1;
-
- var _require$4 = ReactDebugCurrentFiber_1,
- getCurrentFiberStackAddendum$4 = _require$4.getCurrentFiberStackAddendum;
-}
-
-var didWarnValDefaultVal = false;
+var activeElement$1 = null;
+var activeElementInst$1 = null;
+var lastSelection = null;
+var mouseDown = false;
/**
- * Implements a <textarea> host component that allows setting `value`, and
- * `defaultValue`. This differs from the traditional DOM API because value is
- * usually set as PCDATA children.
- *
- * If `value` is not supplied (or null/undefined), user actions that affect the
- * value will trigger updates to the element.
+ * Get an object which is a unique representation of the current selection.
*
- * If `value` is supplied (and not null/undefined), the rendered element will
- * not trigger updates to the element. Instead, the `value` prop must change in
- * order for the rendered element to be updated.
+ * The return value will not be consistent across nodes or browsers, but
+ * two identical selections on the same node will return identical objects.
*
- * The rendered element will be initialized with an empty value, the prop
- * `defaultValue` if specified, or the children content (deprecated).
+ * @param {DOMElement} node
+ * @return {object}
*/
-var ReactDOMTextarea = {
- getHostProps: function (element, props) {
- var node = element;
- !(props.dangerouslySetInnerHTML == null) ? invariant_1(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : void 0;
-
- // Always set children to the same thing. In IE9, the selection range will
- // get reset if `textContent` is mutated. We could add a check in setTextContent
- // to only set the value if/when the value differs from the node value (which would
- // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this
- // solution. The value can be a boolean or object so that's why it's forced
- // to be a string.
- var hostProps = assign({}, props, {
- value: undefined,
- defaultValue: undefined,
- children: '' + node._wrapperState.initialValue
- });
-
- return hostProps;
- },
-
- initWrapperState: function (element, props) {
- var node = element;
- {
- ReactControlledValuePropTypes_1.checkPropTypes('textarea', props, getCurrentFiberStackAddendum$4);
- if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
- warning$14(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components');
- didWarnValDefaultVal = true;
- }
- }
-
- var value = props.value;
- var initialValue = value;
-
- // Only bother fetching default value if we're going to use it
- if (value == null) {
- var defaultValue = props.defaultValue;
- // TODO (yungsters): Remove support for children content in <textarea>.
- var children = props.children;
- if (children != null) {
- {
- warning$14(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.');
- }
- !(defaultValue == null) ? invariant_1(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : void 0;
- if (Array.isArray(children)) {
- !(children.length <= 1) ? invariant_1(false, '<textarea> can only have at most one child.') : void 0;
- children = children[0];
- }
-
- defaultValue = '' + children;
- }
- if (defaultValue == null) {
- defaultValue = '';
- }
- initialValue = defaultValue;
- }
-
- node._wrapperState = {
- initialValue: '' + initialValue
+function getSelection(node) {
+ if ('selectionStart' in node && hasSelectionCapabilities(node)) {
+ return {
+ start: node.selectionStart,
+ end: node.selectionEnd
+ };
+ } else if (window.getSelection) {
+ var selection = window.getSelection();
+ return {
+ anchorNode: selection.anchorNode,
+ anchorOffset: selection.anchorOffset,
+ focusNode: selection.focusNode,
+ focusOffset: selection.focusOffset
};
- },
-
- updateWrapper: function (element, props) {
- var node = element;
- var value = props.value;
- if (value != null) {
- // Cast `value` to a string to ensure the value is set correctly. While
- // browsers typically do this as necessary, jsdom doesn't.
- var newValue = '' + value;
-
- // To avoid side effects (such as losing text selection), only set value if changed
- if (newValue !== node.value) {
- node.value = newValue;
- }
- if (props.defaultValue == null) {
- node.defaultValue = newValue;
- }
- }
- if (props.defaultValue != null) {
- node.defaultValue = props.defaultValue;
- }
- },
-
- postMountWrapper: function (element, props) {
- var node = element;
- // This is in postMount because we need access to the DOM node, which is not
- // available until after the component has mounted.
- var textContent = node.textContent;
-
- // Only set node.value if textContent is equal to the expected
- // initial value. In IE10/IE11 there is a bug where the placeholder attribute
- // will populate textContent as well.
- // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
- if (textContent === node._wrapperState.initialValue) {
- node.value = textContent;
- }
- },
-
- restoreControlledState: function (element, props) {
- // DOM component is still mounted; update
- ReactDOMTextarea.updateWrapper(element, props);
}
-};
-
-var ReactDOMFiberTextarea = ReactDOMTextarea;
+}
/**
- * 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.
+ * Poll selection to see whether it's changed.
*
- * @providesModule omittedCloseTags
+ * @param {object} nativeEvent
+ * @return {?SyntheticEvent}
*/
+function constructSelectEvent(nativeEvent, nativeEventTarget) {
+ // Ensure we have the right element, and that the user is not dragging a
+ // selection (this matches native `select` event behavior). In HTML5, select
+ // fires only on input and textarea thus if there's no focused element we
+ // won't dispatch.
+ if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement_1()) {
+ return null;
+ }
-// For HTML, certain tags should omit their close tag. We keep a whitelist for
-// those special-case tags.
-
-var omittedCloseTags = {
- area: true,
- base: true,
- br: true,
- col: true,
- embed: true,
- hr: true,
- img: true,
- input: true,
- keygen: true,
- link: true,
- meta: true,
- param: true,
- source: true,
- track: true,
- wbr: true
-};
-
-var omittedCloseTags_1 = omittedCloseTags;
-
-// For HTML, certain tags cannot have children. This has the same purpose as
-// `omittedCloseTags` except that `menuitem` should still have its closing tag.
-
-var voidElementTags = assign({
- menuitem: true
-}, omittedCloseTags_1);
+ // Only fire when selection has actually changed.
+ var currentSelection = getSelection(activeElement$1);
+ if (!lastSelection || !shallowEqual_1(lastSelection, currentSelection)) {
+ lastSelection = currentSelection;
-var voidElementTags_1 = voidElementTags;
+ var syntheticEvent = SyntheticEvent$1.getPooled(eventTypes$3.select, activeElementInst$1, nativeEvent, nativeEventTarget);
-{
- var warning$15 = warning_1;
-}
+ syntheticEvent.type = 'select';
+ syntheticEvent.target = activeElement$1;
-var HTML$1 = '__html';
+ accumulateTwoPhaseDispatches(syntheticEvent);
-function getDeclarationErrorAddendum$1(getCurrentOwnerName) {
- {
- var ownerName = getCurrentOwnerName();
- if (ownerName) {
- // TODO: also report the stack.
- return '\n\nThis DOM node was rendered by `' + ownerName + '`.';
- }
+ return syntheticEvent;
}
- return '';
-}
-function assertValidProps(tag, props, getCurrentOwnerName) {
- if (!props) {
- return;
- }
- // Note the use of `==` which checks for null or undefined.
- if (voidElementTags_1[tag]) {
- !(props.children == null && props.dangerouslySetInnerHTML == null) ? invariant_1(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', tag, getDeclarationErrorAddendum$1(getCurrentOwnerName)) : void 0;
- }
- if (props.dangerouslySetInnerHTML != null) {
- !(props.children == null) ? invariant_1(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : void 0;
- !(typeof props.dangerouslySetInnerHTML === 'object' && HTML$1 in props.dangerouslySetInnerHTML) ? invariant_1(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.') : void 0;
- }
- {
- warning$15(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.');
- }
- !(props.style == null || typeof props.style === 'object') ? invariant_1(false, 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \'em\'}} when using JSX.%s', getDeclarationErrorAddendum$1(getCurrentOwnerName)) : void 0;
+ return null;
}
-var assertValidProps_1 = assertValidProps;
-
/**
- * Copyright (c) 2013-present, Facebook, Inc.
+ * This plugin creates an `onSelect` event that normalizes select events
+ * across form elements.
*
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
+ * Supported elements are:
+ * - input (see `isTextInputElement`)
+ * - textarea
+ * - contentEditable
*
- * @providesModule inputValueTracking
- *
+ * This differs from native browser implementations in the following ways:
+ * - Fires on contentEditable fields as well as inputs.
+ * - Fires for collapsed selection.
+ * - Fires after user input.
*/
+var SelectEventPlugin = {
+ eventTypes: eventTypes$3,
-function isCheckable(elem) {
- var type = elem.type;
- var nodeName = elem.nodeName;
- return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
-}
-
-function getTracker(node) {
- return node._valueTracker;
-}
-
-function detachTracker(node) {
- node._valueTracker = null;
-}
-
-function getValueFromNode(node) {
- var value = '';
- if (!node) {
- return value;
- }
-
- if (isCheckable(node)) {
- value = node.checked ? 'true' : 'false';
- } else {
- value = node.value;
- }
-
- return value;
-}
-
-function trackValueOnNode(node) {
- var valueField = isCheckable(node) ? 'checked' : 'value';
- var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);
-
- var currentValue = '' + node[valueField];
-
- // if someone has already defined a value or Safari, then bail
- // and don't track value will cause over reporting of changes,
- // but it's better then a hard failure
- // (needed for certain tests that spyOn input values and Safari)
- if (node.hasOwnProperty(valueField) || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
- return;
- }
-
- Object.defineProperty(node, valueField, {
- enumerable: descriptor.enumerable,
- configurable: true,
- get: function () {
- return descriptor.get.call(this);
- },
- set: function (value) {
- currentValue = '' + value;
- descriptor.set.call(this, value);
- }
- });
-
- var tracker = {
- getValue: function () {
- return currentValue;
- },
- setValue: function (value) {
- currentValue = '' + value;
- },
- stopTracking: function () {
- detachTracker(node);
- delete node[valueField];
- }
- };
- return tracker;
-}
-
-var inputValueTracking = {
- // exposed for testing
- _getTrackerFromNode: getTracker,
-
- track: function (node) {
- if (getTracker(node)) {
- return;
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var doc = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget.document : nativeEventTarget.nodeType === DOCUMENT_NODE ? nativeEventTarget : nativeEventTarget.ownerDocument;
+ // Track whether all listeners exists for this plugin. If none exist, we do
+ // not extract events. See #3639.
+ if (!doc || !isListeningToAllDependencies('onSelect', doc)) {
+ return null;
}
- // TODO: Once it's just Fiber we can move this to node._wrapperState
- node._valueTracker = trackValueOnNode(node);
- },
- updateValueIfChanged: function (node) {
- if (!node) {
- return false;
- }
+ var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
- var tracker = getTracker(node);
- // if there is no tracker at this point it's unlikely
- // that trying again will succeed
- if (!tracker) {
- return true;
+ switch (topLevelType) {
+ // Track the input node that has focus.
+ case 'topFocus':
+ if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {
+ activeElement$1 = targetNode;
+ activeElementInst$1 = targetInst;
+ lastSelection = null;
+ }
+ break;
+ case 'topBlur':
+ activeElement$1 = null;
+ activeElementInst$1 = null;
+ lastSelection = null;
+ break;
+ // Don't fire the event while the user is dragging. This matches the
+ // semantics of the native select event.
+ case 'topMouseDown':
+ mouseDown = true;
+ break;
+ case 'topContextMenu':
+ case 'topMouseUp':
+ mouseDown = false;
+ return constructSelectEvent(nativeEvent, nativeEventTarget);
+ // Chrome and IE fire non-standard event when selection is changed (and
+ // sometimes when it hasn't). IE's event fires out of order with respect
+ // to key and input events on deletion, so we discard it.
+ //
+ // Firefox doesn't support selectionchange, so check selection status
+ // after each key entry. The selection changes after keydown and before
+ // keyup, but we check on keydown as well in the case of holding down a
+ // key, when multiple keydown events are fired but only one keyup is.
+ // This is also our approach for IE handling, for the reason above.
+ case 'topSelectionChange':
+ if (skipSelectionChangeEvent) {
+ break;
+ }
+ // falls through
+ case 'topKeyDown':
+ case 'topKeyUp':
+ return constructSelectEvent(nativeEvent, nativeEventTarget);
}
- var lastValue = tracker.getValue();
- var nextValue = getValueFromNode(node);
- if (nextValue !== lastValue) {
- tracker.setValue(nextValue);
- return true;
- }
- return false;
- },
- stopTracking: function (node) {
- var tracker = getTracker(node);
- if (tracker) {
- tracker.stopTracking();
- }
+ return null;
}
};
-var inputValueTracking_1 = inputValueTracking;
-
/**
- * 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.
- *
- * @providesModule isCustomComponent
- *
+ * @interface Event
+ * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
*/
-
-function isCustomComponent(tagName, props) {
- if (tagName.indexOf('-') === -1) {
- return typeof props.is === 'string';
- }
- switch (tagName) {
- // These are reserved SVG and MathML elements.
- // We don't mind this whitelist too much because we expect it to never grow.
- // The alternative is to track the namespace in a few places which is convoluted.
- // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
- case 'annotation-xml':
- case 'color-profile':
- case 'font-face':
- case 'font-face-src':
- case 'font-face-uri':
- case 'font-face-format':
- case 'font-face-name':
- case 'missing-glyph':
- return false;
- default:
- return true;
- }
-}
-
-var isCustomComponent_1 = isCustomComponent;
+var AnimationEventInterface = {
+ animationName: null,
+ elapsedTime: null,
+ pseudoElement: null
+};
/**
- * 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.
- *
- * @providesModule createMicrosoftUnsafeLocalFunction
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticEvent}
*/
+function SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+}
-/* globals MSApp */
+SyntheticEvent$1.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);
/**
- * Create a function which has 'unsafe' privileges (required by windows8 apps)
+ * @interface Event
+ * @see http://www.w3.org/TR/clipboard-apis/
*/
-
-var createMicrosoftUnsafeLocalFunction = function (func) {
- if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
- return function (arg0, arg1, arg2, arg3) {
- MSApp.execUnsafeLocalFunction(function () {
- return func(arg0, arg1, arg2, arg3);
- });
- };
- } else {
- return func;
+var ClipboardEventInterface = {
+ clipboardData: function (event) {
+ return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
}
};
-var createMicrosoftUnsafeLocalFunction_1 = createMicrosoftUnsafeLocalFunction;
-
-var Namespaces$1 = DOMNamespaces.Namespaces;
-
-
-// SVG temp container for IE lacking innerHTML
-var reusableSVGContainer;
-
/**
- * Set the innerHTML property of a node
- *
- * @param {DOMElement} node
- * @param {string} html
- * @internal
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticEvent}
*/
-var setInnerHTML = createMicrosoftUnsafeLocalFunction_1(function (node, html) {
- // IE does not have innerHTML for SVG nodes, so instead we inject the
- // new markup in a temp node and then move the child nodes across into
- // the target node
- if (node.namespaceURI === Namespaces$1.svg && !('innerHTML' in node)) {
- reusableSVGContainer = reusableSVGContainer || document.createElement('div');
- reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
- var svgNode = reusableSVGContainer.firstChild;
- while (svgNode.firstChild) {
- node.appendChild(svgNode.firstChild);
- }
- } else {
- node.innerHTML = html;
- }
-});
+function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+}
-var setInnerHTML_1 = setInnerHTML;
+SyntheticEvent$1.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);
/**
- * Copyright (c) 2016-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.
- *
- * Based on the escape-html library, which is used under the MIT License below:
- *
- * Copyright (c) 2012-2013 TJ Holowaychuk
- * Copyright (c) 2015 Andreas Lubbe
- * Copyright (c) 2015 Tiancheng "Timothy" Gu
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * 'Software'), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * @providesModule escapeTextContentForBrowser
+ * @interface FocusEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
*/
+var FocusEventInterface = {
+ relatedTarget: null
+};
-// code copied and modified from escape-html
/**
- * Module variables.
- * @private
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticUIEvent}
*/
+function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+}
-var matchHtmlRegExp = /["'&<>]/;
+SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);
/**
- * Escape special characters in the given string of html.
+ * `charCode` represents the actual "character code" and is safe to use with
+ * `String.fromCharCode`. As such, only keys that correspond to printable
+ * characters produce a valid `charCode`, the only exception to this is Enter.
+ * The Tab-key is considered non-printable and does not have a `charCode`,
+ * presumably because it does not produce a tab-character in browsers.
*
- * @param {string} string The string to escape for inserting into HTML
- * @return {string}
- * @public
+ * @param {object} nativeEvent Native browser event.
+ * @return {number} Normalized `charCode` property.
*/
+function getEventCharCode(nativeEvent) {
+ var charCode;
+ var keyCode = nativeEvent.keyCode;
-function escapeHtml(string) {
- var str = '' + string;
- var match = matchHtmlRegExp.exec(str);
-
- if (!match) {
- return str;
- }
-
- var escape;
- var html = '';
- var index = 0;
- var lastIndex = 0;
-
- for (index = match.index; index < str.length; index++) {
- switch (str.charCodeAt(index)) {
- case 34:
- // "
- escape = '&quot;';
- break;
- case 38:
- // &
- escape = '&amp;';
- break;
- case 39:
- // '
- escape = '&#x27;'; // modified from escape-html; used to be '&#39'
- break;
- case 60:
- // <
- escape = '&lt;';
- break;
- case 62:
- // >
- escape = '&gt;';
- break;
- default:
- continue;
- }
+ if ('charCode' in nativeEvent) {
+ charCode = nativeEvent.charCode;
- if (lastIndex !== index) {
- html += str.substring(lastIndex, index);
+ // FF does not set `charCode` for the Enter-key, check against `keyCode`.
+ if (charCode === 0 && keyCode === 13) {
+ charCode = 13;
}
+ } else {
+ // IE8 does not implement `charCode`, but `keyCode` has the correct value.
+ charCode = keyCode;
+ }
- lastIndex = index + 1;
- html += escape;
+ // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
+ // Must not discard the (non-)printable Enter-key.
+ if (charCode >= 32 || charCode === 13) {
+ return charCode;
}
- return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
+ return 0;
}
-// end code copied and modified from escape-html
/**
- * Escapes text to prevent scripting attacks.
- *
- * @param {*} text Text value to escape.
- * @return {string} An escaped string.
+ * Normalization of deprecated HTML5 `key` values
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
*/
-function escapeTextContentForBrowser(text) {
- if (typeof text === 'boolean' || typeof text === 'number') {
- // this shortcircuit helps perf for types that we know will never have
- // special characters, especially given that this function is used often
- // for numeric dom ids.
- return '' + text;
- }
- return escapeHtml(text);
-}
-
-var escapeTextContentForBrowser_1 = escapeTextContentForBrowser;
-
-var TEXT_NODE$2 = HTMLNodeType_1.TEXT_NODE;
+var normalizeKey = {
+ Esc: 'Escape',
+ Spacebar: ' ',
+ Left: 'ArrowLeft',
+ Up: 'ArrowUp',
+ Right: 'ArrowRight',
+ Down: 'ArrowDown',
+ Del: 'Delete',
+ Win: 'OS',
+ Menu: 'ContextMenu',
+ Apps: 'ContextMenu',
+ Scroll: 'ScrollLock',
+ MozPrintableKey: 'Unidentified'
+};
/**
- * Set the textContent property of a node, ensuring that whitespace is preserved
- * even in IE8. innerText is a poor substitute for textContent and, among many
- * issues, inserts <br> instead of the literal newline chars. innerHTML behaves
- * as it should.
- *
- * @param {DOMElement} node
- * @param {string} text
- * @internal
+ * Translation from legacy `keyCode` to HTML5 `key`
+ * Only special keys supported, all others depend on keyboard layout or browser
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
*/
-
-
-var setTextContent = function (node, text) {
- if (text) {
- var firstChild = node.firstChild;
-
- if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE$2) {
- firstChild.nodeValue = text;
- return;
- }
- }
- node.textContent = text;
+var translateToKey = {
+ '8': 'Backspace',
+ '9': 'Tab',
+ '12': 'Clear',
+ '13': 'Enter',
+ '16': 'Shift',
+ '17': 'Control',
+ '18': 'Alt',
+ '19': 'Pause',
+ '20': 'CapsLock',
+ '27': 'Escape',
+ '32': ' ',
+ '33': 'PageUp',
+ '34': 'PageDown',
+ '35': 'End',
+ '36': 'Home',
+ '37': 'ArrowLeft',
+ '38': 'ArrowUp',
+ '39': 'ArrowRight',
+ '40': 'ArrowDown',
+ '45': 'Insert',
+ '46': 'Delete',
+ '112': 'F1',
+ '113': 'F2',
+ '114': 'F3',
+ '115': 'F4',
+ '116': 'F5',
+ '117': 'F6',
+ '118': 'F7',
+ '119': 'F8',
+ '120': 'F9',
+ '121': 'F10',
+ '122': 'F11',
+ '123': 'F12',
+ '144': 'NumLock',
+ '145': 'ScrollLock',
+ '224': 'Meta'
};
-if (ExecutionEnvironment_1.canUseDOM) {
- if (!('textContent' in document.documentElement)) {
- setTextContent = function (node, text) {
- if (node.nodeType === TEXT_NODE$2) {
- node.nodeValue = text;
- return;
- }
- setInnerHTML_1(node, escapeTextContentForBrowser_1(text));
- };
- }
-}
-
-var setTextContent_1 = setTextContent;
-
/**
- * 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.
- *
- * @providesModule validAriaProperties
+ * @param {object} nativeEvent Native browser event.
+ * @return {string} Normalized `key` property.
*/
+function getEventKey(nativeEvent) {
+ if (nativeEvent.key) {
+ // Normalize inconsistent values reported by browsers due to
+ // implementations of a working draft specification.
-var ariaProperties = {
- 'aria-current': 0, // state
- 'aria-details': 0,
- 'aria-disabled': 0, // state
- 'aria-hidden': 0, // state
- 'aria-invalid': 0, // state
- 'aria-keyshortcuts': 0,
- 'aria-label': 0,
- 'aria-roledescription': 0,
- // Widget Attributes
- 'aria-autocomplete': 0,
- 'aria-checked': 0,
- 'aria-expanded': 0,
- 'aria-haspopup': 0,
- 'aria-level': 0,
- 'aria-modal': 0,
- 'aria-multiline': 0,
- 'aria-multiselectable': 0,
- 'aria-orientation': 0,
- 'aria-placeholder': 0,
- 'aria-pressed': 0,
- 'aria-readonly': 0,
- 'aria-required': 0,
- 'aria-selected': 0,
- 'aria-sort': 0,
- 'aria-valuemax': 0,
- 'aria-valuemin': 0,
- 'aria-valuenow': 0,
- 'aria-valuetext': 0,
- // Live Region Attributes
- 'aria-atomic': 0,
- 'aria-busy': 0,
- 'aria-live': 0,
- 'aria-relevant': 0,
- // Drag-and-Drop Attributes
- 'aria-dropeffect': 0,
- 'aria-grabbed': 0,
- // Relationship Attributes
- 'aria-activedescendant': 0,
- 'aria-colcount': 0,
- 'aria-colindex': 0,
- 'aria-colspan': 0,
- 'aria-controls': 0,
- 'aria-describedby': 0,
- 'aria-errormessage': 0,
- 'aria-flowto': 0,
- 'aria-labelledby': 0,
- 'aria-owns': 0,
- 'aria-posinset': 0,
- 'aria-rowcount': 0,
- 'aria-rowindex': 0,
- 'aria-rowspan': 0,
- 'aria-setsize': 0
-};
-
-var validAriaProperties$1 = ariaProperties;
-
-var warnedProperties = {};
-var rARIA = new RegExp('^(aria)-[' + DOMProperty_1.ATTRIBUTE_NAME_CHAR + ']*$');
-var rARIACamel = new RegExp('^(aria)[A-Z][' + DOMProperty_1.ATTRIBUTE_NAME_CHAR + ']*$');
-
-var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-{
- var warning$16 = warning_1;
-
- var _require$5 = ReactGlobalSharedState_1,
- ReactComponentTreeHook$1 = _require$5.ReactComponentTreeHook,
- ReactDebugCurrentFrame$1 = _require$5.ReactDebugCurrentFrame;
-
- var getStackAddendumByID = ReactComponentTreeHook$1.getStackAddendumByID;
-
-
- var validAriaProperties = validAriaProperties$1;
-}
-
-function getStackAddendum(debugID) {
- if (debugID != null) {
- // This can only happen on Stack
- return getStackAddendumByID(debugID);
- } else {
- // This can only happen on Fiber / Server
- var stack = ReactDebugCurrentFrame$1.getStackAddendum();
- return stack != null ? stack : '';
- }
-}
-
-function validateProperty(tagName, name, debugID) {
- if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {
- return true;
- }
-
- if (rARIACamel.test(name)) {
- var ariaName = 'aria-' + name.slice(4).toLowerCase();
- var correctName = validAriaProperties.hasOwnProperty(ariaName) ? ariaName : null;
-
- // If this is an aria-* attribute, but is not listed in the known DOM
- // DOM properties, then it is an invalid aria-* attribute.
- if (correctName == null) {
- warning$16(false, 'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.%s', name, getStackAddendum(debugID));
- warnedProperties[name] = true;
- return true;
- }
- // aria-* attributes should be lowercase; suggest the lowercase version.
- if (name !== correctName) {
- warning$16(false, 'Invalid ARIA attribute `%s`. Did you mean `%s`?%s', name, correctName, getStackAddendum(debugID));
- warnedProperties[name] = true;
- return true;
- }
- }
-
- if (rARIA.test(name)) {
- var lowerCasedName = name.toLowerCase();
- var standardName = validAriaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null;
-
- // If this is an aria-* attribute, but is not listed in the known DOM
- // DOM properties, then it is an invalid aria-* attribute.
- if (standardName == null) {
- warnedProperties[name] = true;
- return false;
- }
- // aria-* attributes should be lowercase; suggest the lowercase version.
- if (name !== standardName) {
- warning$16(false, 'Unknown ARIA attribute `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum(debugID));
- warnedProperties[name] = true;
- return true;
+ // FireFox implements `key` but returns `MozPrintableKey` for all
+ // printable characters (normalized to `Unidentified`), ignore it.
+ var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
+ if (key !== 'Unidentified') {
+ return key;
}
}
- return true;
-}
-
-function warnInvalidARIAProps(type, props, debugID) {
- var invalidProps = [];
+ // Browser does not implement `key`, polyfill as much of it as we can.
+ if (nativeEvent.type === 'keypress') {
+ var charCode = getEventCharCode(nativeEvent);
- for (var key in props) {
- var isValid = validateProperty(type, key, debugID);
- if (!isValid) {
- invalidProps.push(key);
- }
+ // The enter-key is technically both printable and non-printable and can
+ // thus be captured by `keypress`, no other non-printable key should.
+ return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
}
-
- var unknownPropString = invalidProps.map(function (prop) {
- return '`' + prop + '`';
- }).join(', ');
-
- if (invalidProps.length === 1) {
- warning$16(false, 'Invalid aria prop %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum(debugID));
- } else if (invalidProps.length > 1) {
- warning$16(false, 'Invalid aria props %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum(debugID));
+ if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
+ // While user keyboard layout determines the actual meaning of each
+ // `keyCode` value, almost all function keys have a universal value.
+ return translateToKey[nativeEvent.keyCode] || 'Unidentified';
}
+ return '';
}
-function validateProperties(type, props, debugID /* Stack only */) {
- if (isCustomComponent_1(type, props)) {
- return;
- }
- warnInvalidARIAProps(type, props, debugID);
-}
+/**
+ * @interface KeyboardEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var KeyboardEventInterface = {
+ key: getEventKey,
+ location: null,
+ ctrlKey: null,
+ shiftKey: null,
+ altKey: null,
+ metaKey: null,
+ repeat: null,
+ locale: null,
+ getModifierState: getEventModifierState,
+ // Legacy Interface
+ charCode: function (event) {
+ // `charCode` is the result of a KeyPress event and represents the value of
+ // the actual printable character.
-var ReactDOMInvalidARIAHook$1 = {
- // Fiber
- validateProperties: validateProperties,
- // Stack
- onBeforeMountComponent: function (debugID, element) {
- if (true && element != null && typeof element.type === 'string') {
- validateProperties(element.type, element.props, debugID);
+ // KeyPress is deprecated, but its replacement is not yet final and not
+ // implemented in any major browser. Only KeyPress has charCode.
+ if (event.type === 'keypress') {
+ return getEventCharCode(event);
}
+ return 0;
},
- onBeforeUpdateComponent: function (debugID, element) {
- if (true && element != null && typeof element.type === 'string') {
- validateProperties(element.type, element.props, debugID);
- }
- }
-};
-
-var ReactDOMInvalidARIAHook_1 = ReactDOMInvalidARIAHook$1;
-
-{
- var warning$17 = warning_1;
-
- var _require$6 = ReactGlobalSharedState_1,
- ReactComponentTreeHook$2 = _require$6.ReactComponentTreeHook,
- ReactDebugCurrentFrame$2 = _require$6.ReactDebugCurrentFrame;
-
- var getStackAddendumByID$1 = ReactComponentTreeHook$2.getStackAddendumByID;
-}
-
-var didWarnValueNull = false;
-
-function getStackAddendum$1(debugID) {
- if (debugID != null) {
- // This can only happen on Stack
- return getStackAddendumByID$1(debugID);
- } else {
- // This can only happen on Fiber / Server
- var stack = ReactDebugCurrentFrame$2.getStackAddendum();
- return stack != null ? stack : '';
- }
-}
-
-function validateProperties$1(type, props, debugID /* Stack only */) {
- if (type !== 'input' && type !== 'textarea' && type !== 'select') {
- return;
- }
- if (props != null && props.value === null && !didWarnValueNull) {
- warning$17(false, '`value` prop on `%s` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s', type, getStackAddendum$1(debugID));
-
- didWarnValueNull = true;
- }
-}
+ keyCode: function (event) {
+ // `keyCode` is the result of a KeyDown/Up event and represents the value of
+ // physical keyboard key.
-var ReactDOMNullInputValuePropHook$1 = {
- // Fiber
- validateProperties: validateProperties$1,
- // Stack
- onBeforeMountComponent: function (debugID, element) {
- if (true && element != null && typeof element.type === 'string') {
- validateProperties$1(element.type, element.props, debugID);
+ // The actual meaning of the value depends on the users' keyboard layout
+ // which cannot be detected. Assuming that it is a US keyboard layout
+ // provides a surprisingly accurate mapping for US and European users.
+ // Due to this, it is left to the user to implement at this time.
+ if (event.type === 'keydown' || event.type === 'keyup') {
+ return event.keyCode;
}
+ return 0;
},
- onBeforeUpdateComponent: function (debugID, element) {
- if (true && element != null && typeof element.type === 'string') {
- validateProperties$1(element.type, element.props, debugID);
+ which: function (event) {
+ // `which` is an alias for either `keyCode` or `charCode` depending on the
+ // type of the event.
+ if (event.type === 'keypress') {
+ return getEventCharCode(event);
+ }
+ if (event.type === 'keydown' || event.type === 'keyup') {
+ return event.keyCode;
}
+ return 0;
}
};
-var ReactDOMNullInputValuePropHook_1 = ReactDOMNullInputValuePropHook$1;
-
/**
- * 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.
- *
- * @providesModule possibleStandardNames
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticUIEvent}
*/
-
-// When adding attributes to the HTML or SVG whitelist, be sure to
-// also add them to this module to ensure casing and incorrect name
-// warnings.
-var possibleStandardNames$1 = {
- // HTML
- accept: 'accept',
- acceptcharset: 'acceptCharset',
- 'accept-charset': 'acceptCharset',
- accesskey: 'accessKey',
- action: 'action',
- allowfullscreen: 'allowFullScreen',
- allowtransparency: 'allowTransparency',
- alt: 'alt',
- as: 'as',
- async: 'async',
- autocapitalize: 'autoCapitalize',
- autocomplete: 'autoComplete',
- autocorrect: 'autoCorrect',
- autofocus: 'autoFocus',
- autoplay: 'autoPlay',
- autosave: 'autoSave',
- capture: 'capture',
- cellpadding: 'cellPadding',
- cellspacing: 'cellSpacing',
- challenge: 'challenge',
- charset: 'charSet',
- checked: 'checked',
- children: 'children',
- cite: 'cite',
- 'class': 'className',
- classid: 'classID',
- classname: 'className',
- cols: 'cols',
- colspan: 'colSpan',
- content: 'content',
- contenteditable: 'contentEditable',
- contextmenu: 'contextMenu',
- controls: 'controls',
- controlslist: 'controlsList',
- coords: 'coords',
- crossorigin: 'crossOrigin',
- dangerouslysetinnerhtml: 'dangerouslySetInnerHTML',
- data: 'data',
- datetime: 'dateTime',
- 'default': 'default',
- defaultchecked: 'defaultChecked',
- defaultvalue: 'defaultValue',
- defer: 'defer',
- dir: 'dir',
- disabled: 'disabled',
- download: 'download',
- draggable: 'draggable',
- enctype: 'encType',
- 'for': 'htmlFor',
- form: 'form',
- formmethod: 'formMethod',
- formaction: 'formAction',
- formenctype: 'formEncType',
- formnovalidate: 'formNoValidate',
- formtarget: 'formTarget',
- frameborder: 'frameBorder',
- headers: 'headers',
- height: 'height',
- hidden: 'hidden',
- high: 'high',
- href: 'href',
- hreflang: 'hrefLang',
- htmlfor: 'htmlFor',
- httpequiv: 'httpEquiv',
- 'http-equiv': 'httpEquiv',
- icon: 'icon',
- id: 'id',
- innerhtml: 'innerHTML',
- inputmode: 'inputMode',
- integrity: 'integrity',
- is: 'is',
- itemid: 'itemID',
- itemprop: 'itemProp',
- itemref: 'itemRef',
- itemscope: 'itemScope',
- itemtype: 'itemType',
- keyparams: 'keyParams',
- keytype: 'keyType',
- kind: 'kind',
- label: 'label',
- lang: 'lang',
- list: 'list',
- loop: 'loop',
- low: 'low',
- manifest: 'manifest',
- marginwidth: 'marginWidth',
- marginheight: 'marginHeight',
- max: 'max',
- maxlength: 'maxLength',
- media: 'media',
- mediagroup: 'mediaGroup',
- method: 'method',
- min: 'min',
- minlength: 'minLength',
- multiple: 'multiple',
- muted: 'muted',
- name: 'name',
- nonce: 'nonce',
- novalidate: 'noValidate',
- open: 'open',
- optimum: 'optimum',
- pattern: 'pattern',
- placeholder: 'placeholder',
- playsinline: 'playsInline',
- poster: 'poster',
- preload: 'preload',
- profile: 'profile',
- radiogroup: 'radioGroup',
- readonly: 'readOnly',
- referrerpolicy: 'referrerPolicy',
- rel: 'rel',
- required: 'required',
- reversed: 'reversed',
- role: 'role',
- rows: 'rows',
- rowspan: 'rowSpan',
- sandbox: 'sandbox',
- scope: 'scope',
- scoped: 'scoped',
- scrolling: 'scrolling',
- seamless: 'seamless',
- selected: 'selected',
- shape: 'shape',
- size: 'size',
- sizes: 'sizes',
- span: 'span',
- spellcheck: 'spellCheck',
- src: 'src',
- srcdoc: 'srcDoc',
- srclang: 'srcLang',
- srcset: 'srcSet',
- start: 'start',
- step: 'step',
- style: 'style',
- summary: 'summary',
- tabindex: 'tabIndex',
- target: 'target',
- title: 'title',
- type: 'type',
- usemap: 'useMap',
- value: 'value',
- width: 'width',
- wmode: 'wmode',
- wrap: 'wrap',
-
- // SVG
- about: 'about',
- accentheight: 'accentHeight',
- 'accent-height': 'accentHeight',
- accumulate: 'accumulate',
- additive: 'additive',
- alignmentbaseline: 'alignmentBaseline',
- 'alignment-baseline': 'alignmentBaseline',
- allowreorder: 'allowReorder',
- alphabetic: 'alphabetic',
- amplitude: 'amplitude',
- arabicform: 'arabicForm',
- 'arabic-form': 'arabicForm',
- ascent: 'ascent',
- attributename: 'attributeName',
- attributetype: 'attributeType',
- autoreverse: 'autoReverse',
- azimuth: 'azimuth',
- basefrequency: 'baseFrequency',
- baselineshift: 'baselineShift',
- 'baseline-shift': 'baselineShift',
- baseprofile: 'baseProfile',
- bbox: 'bbox',
- begin: 'begin',
- bias: 'bias',
- by: 'by',
- calcmode: 'calcMode',
- capheight: 'capHeight',
- 'cap-height': 'capHeight',
- clip: 'clip',
- clippath: 'clipPath',
- 'clip-path': 'clipPath',
- clippathunits: 'clipPathUnits',
- cliprule: 'clipRule',
- 'clip-rule': 'clipRule',
- color: 'color',
- colorinterpolation: 'colorInterpolation',
- 'color-interpolation': 'colorInterpolation',
- colorinterpolationfilters: 'colorInterpolationFilters',
- 'color-interpolation-filters': 'colorInterpolationFilters',
- colorprofile: 'colorProfile',
- 'color-profile': 'colorProfile',
- colorrendering: 'colorRendering',
- 'color-rendering': 'colorRendering',
- contentscripttype: 'contentScriptType',
- contentstyletype: 'contentStyleType',
- cursor: 'cursor',
- cx: 'cx',
- cy: 'cy',
- d: 'd',
- datatype: 'datatype',
- decelerate: 'decelerate',
- descent: 'descent',
- diffuseconstant: 'diffuseConstant',
- direction: 'direction',
- display: 'display',
- divisor: 'divisor',
- dominantbaseline: 'dominantBaseline',
- 'dominant-baseline': 'dominantBaseline',
- dur: 'dur',
- dx: 'dx',
- dy: 'dy',
- edgemode: 'edgeMode',
- elevation: 'elevation',
- enablebackground: 'enableBackground',
- 'enable-background': 'enableBackground',
- end: 'end',
- exponent: 'exponent',
- externalresourcesrequired: 'externalResourcesRequired',
- fill: 'fill',
- fillopacity: 'fillOpacity',
- 'fill-opacity': 'fillOpacity',
- fillrule: 'fillRule',
- 'fill-rule': 'fillRule',
- filter: 'filter',
- filterres: 'filterRes',
- filterunits: 'filterUnits',
- floodopacity: 'floodOpacity',
- 'flood-opacity': 'floodOpacity',
- floodcolor: 'floodColor',
- 'flood-color': 'floodColor',
- focusable: 'focusable',
- fontfamily: 'fontFamily',
- 'font-family': 'fontFamily',
- fontsize: 'fontSize',
- 'font-size': 'fontSize',
- fontsizeadjust: 'fontSizeAdjust',
- 'font-size-adjust': 'fontSizeAdjust',
- fontstretch: 'fontStretch',
- 'font-stretch': 'fontStretch',
- fontstyle: 'fontStyle',
- 'font-style': 'fontStyle',
- fontvariant: 'fontVariant',
- 'font-variant': 'fontVariant',
- fontweight: 'fontWeight',
- 'font-weight': 'fontWeight',
- format: 'format',
- from: 'from',
- fx: 'fx',
- fy: 'fy',
- g1: 'g1',
- g2: 'g2',
- glyphname: 'glyphName',
- 'glyph-name': 'glyphName',
- glyphorientationhorizontal: 'glyphOrientationHorizontal',
- 'glyph-orientation-horizontal': 'glyphOrientationHorizontal',
- glyphorientationvertical: 'glyphOrientationVertical',
- 'glyph-orientation-vertical': 'glyphOrientationVertical',
- glyphref: 'glyphRef',
- gradienttransform: 'gradientTransform',
- gradientunits: 'gradientUnits',
- hanging: 'hanging',
- horizadvx: 'horizAdvX',
- 'horiz-adv-x': 'horizAdvX',
- horizoriginx: 'horizOriginX',
- 'horiz-origin-x': 'horizOriginX',
- ideographic: 'ideographic',
- imagerendering: 'imageRendering',
- 'image-rendering': 'imageRendering',
- in2: 'in2',
- 'in': 'in',
- inlist: 'inlist',
- intercept: 'intercept',
- k1: 'k1',
- k2: 'k2',
- k3: 'k3',
- k4: 'k4',
- k: 'k',
- kernelmatrix: 'kernelMatrix',
- kernelunitlength: 'kernelUnitLength',
- kerning: 'kerning',
- keypoints: 'keyPoints',
- keysplines: 'keySplines',
- keytimes: 'keyTimes',
- lengthadjust: 'lengthAdjust',
- letterspacing: 'letterSpacing',
- 'letter-spacing': 'letterSpacing',
- lightingcolor: 'lightingColor',
- 'lighting-color': 'lightingColor',
- limitingconeangle: 'limitingConeAngle',
- local: 'local',
- markerend: 'markerEnd',
- 'marker-end': 'markerEnd',
- markerheight: 'markerHeight',
- markermid: 'markerMid',
- 'marker-mid': 'markerMid',
- markerstart: 'markerStart',
- 'marker-start': 'markerStart',
- markerunits: 'markerUnits',
- markerwidth: 'markerWidth',
- mask: 'mask',
- maskcontentunits: 'maskContentUnits',
- maskunits: 'maskUnits',
- mathematical: 'mathematical',
- mode: 'mode',
- numoctaves: 'numOctaves',
- offset: 'offset',
- opacity: 'opacity',
- operator: 'operator',
- order: 'order',
- orient: 'orient',
- orientation: 'orientation',
- origin: 'origin',
- overflow: 'overflow',
- overlineposition: 'overlinePosition',
- 'overline-position': 'overlinePosition',
- overlinethickness: 'overlineThickness',
- 'overline-thickness': 'overlineThickness',
- paintorder: 'paintOrder',
- 'paint-order': 'paintOrder',
- panose1: 'panose1',
- 'panose-1': 'panose1',
- pathlength: 'pathLength',
- patterncontentunits: 'patternContentUnits',
- patterntransform: 'patternTransform',
- patternunits: 'patternUnits',
- pointerevents: 'pointerEvents',
- 'pointer-events': 'pointerEvents',
- points: 'points',
- pointsatx: 'pointsAtX',
- pointsaty: 'pointsAtY',
- pointsatz: 'pointsAtZ',
- prefix: 'prefix',
- preservealpha: 'preserveAlpha',
- preserveaspectratio: 'preserveAspectRatio',
- primitiveunits: 'primitiveUnits',
- property: 'property',
- r: 'r',
- radius: 'radius',
- refx: 'refX',
- refy: 'refY',
- renderingintent: 'renderingIntent',
- 'rendering-intent': 'renderingIntent',
- repeatcount: 'repeatCount',
- repeatdur: 'repeatDur',
- requiredextensions: 'requiredExtensions',
- requiredfeatures: 'requiredFeatures',
- resource: 'resource',
- restart: 'restart',
- result: 'result',
- results: 'results',
- rotate: 'rotate',
- rx: 'rx',
- ry: 'ry',
- scale: 'scale',
- security: 'security',
- seed: 'seed',
- shaperendering: 'shapeRendering',
- 'shape-rendering': 'shapeRendering',
- slope: 'slope',
- spacing: 'spacing',
- specularconstant: 'specularConstant',
- specularexponent: 'specularExponent',
- speed: 'speed',
- spreadmethod: 'spreadMethod',
- startoffset: 'startOffset',
- stddeviation: 'stdDeviation',
- stemh: 'stemh',
- stemv: 'stemv',
- stitchtiles: 'stitchTiles',
- stopcolor: 'stopColor',
- 'stop-color': 'stopColor',
- stopopacity: 'stopOpacity',
- 'stop-opacity': 'stopOpacity',
- strikethroughposition: 'strikethroughPosition',
- 'strikethrough-position': 'strikethroughPosition',
- strikethroughthickness: 'strikethroughThickness',
- 'strikethrough-thickness': 'strikethroughThickness',
- string: 'string',
- stroke: 'stroke',
- strokedasharray: 'strokeDasharray',
- 'stroke-dasharray': 'strokeDasharray',
- strokedashoffset: 'strokeDashoffset',
- 'stroke-dashoffset': 'strokeDashoffset',
- strokelinecap: 'strokeLinecap',
- 'stroke-linecap': 'strokeLinecap',
- strokelinejoin: 'strokeLinejoin',
- 'stroke-linejoin': 'strokeLinejoin',
- strokemiterlimit: 'strokeMiterlimit',
- 'stroke-miterlimit': 'strokeMiterlimit',
- strokewidth: 'strokeWidth',
- 'stroke-width': 'strokeWidth',
- strokeopacity: 'strokeOpacity',
- 'stroke-opacity': 'strokeOpacity',
- suppresscontenteditablewarning: 'suppressContentEditableWarning',
- surfacescale: 'surfaceScale',
- systemlanguage: 'systemLanguage',
- tablevalues: 'tableValues',
- targetx: 'targetX',
- targety: 'targetY',
- textanchor: 'textAnchor',
- 'text-anchor': 'textAnchor',
- textdecoration: 'textDecoration',
- 'text-decoration': 'textDecoration',
- textlength: 'textLength',
- textrendering: 'textRendering',
- 'text-rendering': 'textRendering',
- to: 'to',
- transform: 'transform',
- 'typeof': 'typeof',
- u1: 'u1',
- u2: 'u2',
- underlineposition: 'underlinePosition',
- 'underline-position': 'underlinePosition',
- underlinethickness: 'underlineThickness',
- 'underline-thickness': 'underlineThickness',
- unicode: 'unicode',
- unicodebidi: 'unicodeBidi',
- 'unicode-bidi': 'unicodeBidi',
- unicoderange: 'unicodeRange',
- 'unicode-range': 'unicodeRange',
- unitsperem: 'unitsPerEm',
- 'units-per-em': 'unitsPerEm',
- unselectable: 'unselectable',
- valphabetic: 'vAlphabetic',
- 'v-alphabetic': 'vAlphabetic',
- values: 'values',
- vectoreffect: 'vectorEffect',
- 'vector-effect': 'vectorEffect',
- version: 'version',
- vertadvy: 'vertAdvY',
- 'vert-adv-y': 'vertAdvY',
- vertoriginx: 'vertOriginX',
- 'vert-origin-x': 'vertOriginX',
- vertoriginy: 'vertOriginY',
- 'vert-origin-y': 'vertOriginY',
- vhanging: 'vHanging',
- 'v-hanging': 'vHanging',
- videographic: 'vIdeographic',
- 'v-ideographic': 'vIdeographic',
- viewbox: 'viewBox',
- viewtarget: 'viewTarget',
- visibility: 'visibility',
- vmathematical: 'vMathematical',
- 'v-mathematical': 'vMathematical',
- vocab: 'vocab',
- widths: 'widths',
- wordspacing: 'wordSpacing',
- 'word-spacing': 'wordSpacing',
- writingmode: 'writingMode',
- 'writing-mode': 'writingMode',
- x1: 'x1',
- x2: 'x2',
- x: 'x',
- xchannelselector: 'xChannelSelector',
- xheight: 'xHeight',
- 'x-height': 'xHeight',
- xlinkactuate: 'xlinkActuate',
- 'xlink:actuate': 'xlinkActuate',
- xlinkarcrole: 'xlinkArcrole',
- 'xlink:arcrole': 'xlinkArcrole',
- xlinkhref: 'xlinkHref',
- 'xlink:href': 'xlinkHref',
- xlinkrole: 'xlinkRole',
- 'xlink:role': 'xlinkRole',
- xlinkshow: 'xlinkShow',
- 'xlink:show': 'xlinkShow',
- xlinktitle: 'xlinkTitle',
- 'xlink:title': 'xlinkTitle',
- xlinktype: 'xlinkType',
- 'xlink:type': 'xlinkType',
- xmlbase: 'xmlBase',
- 'xml:base': 'xmlBase',
- xmllang: 'xmlLang',
- 'xml:lang': 'xmlLang',
- xmlns: 'xmlns',
- 'xml:space': 'xmlSpace',
- xmlnsxlink: 'xmlnsXlink',
- 'xmlns:xlink': 'xmlnsXlink',
- xmlspace: 'xmlSpace',
- y1: 'y1',
- y2: 'y2',
- y: 'y',
- ychannelselector: 'yChannelSelector',
- z: 'z',
- zoomandpan: 'zoomAndPan'
-};
-
-var possibleStandardNames_1 = possibleStandardNames$1;
-
-{
- var warning$18 = warning_1;
-
- var _require$7 = ReactGlobalSharedState_1,
- ReactComponentTreeHook$3 = _require$7.ReactComponentTreeHook,
- ReactDebugCurrentFrame$3 = _require$7.ReactDebugCurrentFrame;
-
- var getStackAddendumByID$2 = ReactComponentTreeHook$3.getStackAddendumByID;
-}
-
-function getStackAddendum$2(debugID) {
- if (debugID != null) {
- // This can only happen on Stack
- return getStackAddendumByID$2(debugID);
- } else {
- // This can only happen on Fiber / Server
- var stack = ReactDebugCurrentFrame$3.getStackAddendum();
- return stack != null ? stack : '';
- }
-}
-
-{
- var warnedProperties$1 = {};
- var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
- var EVENT_NAME_REGEX = /^on[A-Z]/;
- var rARIA$1 = new RegExp('^(aria)-[' + DOMProperty_1.ATTRIBUTE_NAME_CHAR + ']*$');
- var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + DOMProperty_1.ATTRIBUTE_NAME_CHAR + ']*$');
- var possibleStandardNames = possibleStandardNames_1;
-
- var validateProperty$1 = function (tagName, name, value, debugID) {
- if (hasOwnProperty$1.call(warnedProperties$1, name) && warnedProperties$1[name]) {
- return true;
- }
-
- if (EventPluginRegistry_1.registrationNameModules.hasOwnProperty(name)) {
- return true;
- }
-
- if (EventPluginRegistry_1.plugins.length === 0 && EVENT_NAME_REGEX.test(name)) {
- // If no event plugins have been injected, we might be in a server environment.
- // Don't check events in this case.
- return true;
- }
-
- var lowerCasedName = name.toLowerCase();
- var registrationName = EventPluginRegistry_1.possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? EventPluginRegistry_1.possibleRegistrationNames[lowerCasedName] : null;
-
- if (registrationName != null) {
- warning$18(false, 'Invalid event handler property `%s`. Did you mean `%s`?%s', name, registrationName, getStackAddendum$2(debugID));
- warnedProperties$1[name] = true;
- return true;
- }
-
- if (lowerCasedName.indexOf('on') === 0) {
- warning$18(false, 'Unknown event handler property `%s`. It will be ignored.%s', name, getStackAddendum$2(debugID));
- warnedProperties$1[name] = true;
- return true;
- }
-
- // Let the ARIA attribute hook validate ARIA attributes
- if (rARIA$1.test(name) || rARIACamel$1.test(name)) {
- return true;
- }
-
- if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') {
- warning$18(false, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.');
- warnedProperties$1[name] = true;
- return true;
- }
-
- if (lowerCasedName === 'innerhtml') {
- warning$18(false, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.');
- warnedProperties$1[name] = true;
- return true;
- }
-
- if (lowerCasedName === 'aria') {
- warning$18(false, 'The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.');
- warnedProperties$1[name] = true;
- return true;
- }
-
- if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') {
- warning$18(false, 'Received a `%s` for string attribute `is`. If this is expected, cast ' + 'the value to a string.%s', typeof value, getStackAddendum$2(debugID));
- warnedProperties$1[name] = true;
- return true;
- }
-
- if (typeof value === 'number' && isNaN(value)) {
- warning$18(false, 'Received NaN for numeric attribute `%s`. If this is expected, cast ' + 'the value to a string.%s', name, getStackAddendum$2(debugID));
- warnedProperties$1[name] = true;
- return true;
- }
-
- var isReserved = DOMProperty_1.isReservedProp(name);
-
- // Known attributes should match the casing specified in the property config.
- if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
- var standardName = possibleStandardNames[lowerCasedName];
- if (standardName !== name) {
- warning$18(false, 'Invalid DOM property `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum$2(debugID));
- warnedProperties$1[name] = true;
- return true;
- }
- } else if (!isReserved && name !== lowerCasedName) {
- // Unknown attributes should have lowercase casing since that's how they
- // will be cased anyway with server rendering.
- warning$18(false, 'React does not recognize the `%s` prop on a DOM element. If you ' + 'intentionally want it to appear in the DOM as a custom ' + 'attribute, spell it as lowercase `%s` instead. ' + 'If you accidentally passed it from a parent component, remove ' + 'it from the DOM element.%s', name, lowerCasedName, getStackAddendum$2(debugID));
- warnedProperties$1[name] = true;
- return true;
- }
-
- if (typeof value === 'boolean') {
- warning$18(DOMProperty_1.shouldAttributeAcceptBooleanValue(name), 'Received `%s` for non-boolean attribute `%s`. If this is expected, cast ' + 'the value to a string.%s', value, name, getStackAddendum$2(debugID));
- warnedProperties$1[name] = true;
- return true;
- }
-
- // Now that we've validated casing, do not validate
- // data types for reserved props
- if (isReserved) {
- return true;
- }
-
- // Warn when a known attribute is a bad type
- if (!DOMProperty_1.shouldSetAttribute(name, value)) {
- warnedProperties$1[name] = true;
- return false;
- }
-
- return true;
- };
+function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}
-var warnUnknownProperties = function (type, props, debugID) {
- var unknownProps = [];
- for (var key in props) {
- var isValid = validateProperty$1(type, key, props[key], debugID);
- if (!isValid) {
- unknownProps.push(key);
- }
- }
+SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);
- var unknownPropString = unknownProps.map(function (prop) {
- return '`' + prop + '`';
- }).join(', ');
- if (unknownProps.length === 1) {
- warning$18(false, 'Invalid value for prop %s on <%s> tag. Either remove it from the element, ' + 'or pass a string or number value to keep it in the DOM. ' + 'For details, see https://fb.me/react-attribute-behavior%s', unknownPropString, type, getStackAddendum$2(debugID));
- } else if (unknownProps.length > 1) {
- warning$18(false, 'Invalid values for props %s on <%s> tag. Either remove them from the element, ' + 'or pass a string or number value to keep them in the DOM. ' + 'For details, see https://fb.me/react-attribute-behavior%s', unknownPropString, type, getStackAddendum$2(debugID));
- }
-};
-
-function validateProperties$2(type, props, debugID /* Stack only */) {
- if (isCustomComponent_1(type, props)) {
- return;
- }
- warnUnknownProperties(type, props, debugID);
-}
-
-var ReactDOMUnknownPropertyHook$1 = {
- // Fiber
- validateProperties: validateProperties$2,
- // Stack
- onBeforeMountComponent: function (debugID, element) {
- if (true && element != null && typeof element.type === 'string') {
- validateProperties$2(element.type, element.props, debugID);
- }
- },
- onBeforeUpdateComponent: function (debugID, element) {
- if (true && element != null && typeof element.type === 'string') {
- validateProperties$2(element.type, element.props, debugID);
- }
- }
+/**
+ * @interface DragEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var DragEventInterface = {
+ dataTransfer: null
};
-var ReactDOMUnknownPropertyHook_1 = ReactDOMUnknownPropertyHook$1;
-
-var getCurrentFiberOwnerName = ReactDebugCurrentFiber_1.getCurrentFiberOwnerName;
-
-var DOCUMENT_NODE$1 = HTMLNodeType_1.DOCUMENT_NODE;
-var DOCUMENT_FRAGMENT_NODE$1 = HTMLNodeType_1.DOCUMENT_FRAGMENT_NODE;
-
-
-
-
-
-
-
-
-{
- var warning$4 = warning_1;
-
- var _require3$1 = ReactDebugCurrentFiber_1,
- getCurrentFiberStackAddendum = _require3$1.getCurrentFiberStackAddendum;
-
- var ReactDOMInvalidARIAHook = ReactDOMInvalidARIAHook_1;
- var ReactDOMNullInputValuePropHook = ReactDOMNullInputValuePropHook_1;
- var ReactDOMUnknownPropertyHook = ReactDOMUnknownPropertyHook_1;
- var validateARIAProperties = ReactDOMInvalidARIAHook.validateProperties;
- var validateInputProperties = ReactDOMNullInputValuePropHook.validateProperties;
- var validateUnknownProperties = ReactDOMUnknownPropertyHook.validateProperties;
+/**
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticMouseEvent}
+ */
+function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}
-var didWarnInvalidHydration = false;
-var didWarnShadyDOM = false;
+SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);
-var listenTo = ReactBrowserEventEmitter_1.listenTo;
-var registrationNameModules = EventPluginRegistry_1.registrationNameModules;
-
-var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
-var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
-var CHILDREN = 'children';
-var STYLE = 'style';
-var HTML = '__html';
-
-var HTML_NAMESPACE$1 = DOMNamespaces.Namespaces.html;
-var getIntrinsicNamespace$1 = DOMNamespaces.getIntrinsicNamespace;
-
-
-{
- var warnedUnknownTags = {
- // Chrome is the only major browser not shipping <time>. But as of July
- // 2017 it intends to ship it due to widespread usage. We intentionally
- // *don't* warn for <time> even if it's unrecognized by Chrome because
- // it soon will be, and many apps have been using it anyway.
- time: true
- };
-
- var validatePropertiesInDevelopment = function (type, props) {
- validateARIAProperties(type, props);
- validateInputProperties(type, props);
- validateUnknownProperties(type, props);
- };
-
- var warnForTextDifference = function (serverText, clientText) {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- warning$4(false, 'Text content did not match. Server: "%s" Client: "%s"', serverText, clientText);
- };
-
- var warnForPropDifference = function (propName, serverValue, clientValue) {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- warning$4(false, 'Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(serverValue), JSON.stringify(clientValue));
- };
-
- var warnForExtraAttributes = function (attributeNames) {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- var names = [];
- attributeNames.forEach(function (name) {
- names.push(name);
- });
- warning$4(false, 'Extra attributes from the server: %s', names);
- };
-
- var warnForInvalidEventListener = function (registrationName, listener) {
- warning$4(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.%s', registrationName, typeof listener, getCurrentFiberStackAddendum());
- };
-
- var testDocument;
- // Parse the HTML and read it back to normalize the HTML string so that it
- // can be used for comparison.
- var normalizeHTML = function (parent, html) {
- if (!testDocument) {
- testDocument = document.implementation.createHTMLDocument();
- }
- var testElement = parent.namespaceURI === HTML_NAMESPACE$1 ? testDocument.createElement(parent.tagName) : testDocument.createElementNS(parent.namespaceURI, parent.tagName);
- testElement.innerHTML = html;
- return testElement.innerHTML;
- };
-}
+/**
+ * @interface TouchEvent
+ * @see http://www.w3.org/TR/touch-events/
+ */
+var TouchEventInterface = {
+ touches: null,
+ targetTouches: null,
+ changedTouches: null,
+ altKey: null,
+ metaKey: null,
+ ctrlKey: null,
+ shiftKey: null,
+ getModifierState: getEventModifierState
+};
-function ensureListeningTo(rootContainerElement, registrationName) {
- var isDocumentOrFragment = rootContainerElement.nodeType === DOCUMENT_NODE$1 || rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE$1;
- var doc = isDocumentOrFragment ? rootContainerElement : rootContainerElement.ownerDocument;
- listenTo(registrationName, doc);
+/**
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticUIEvent}
+ */
+function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}
-function getOwnerDocumentFromRootContainer(rootContainerElement) {
- return rootContainerElement.nodeType === DOCUMENT_NODE$1 ? rootContainerElement : rootContainerElement.ownerDocument;
-}
+SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);
-// There are so many media events, it makes sense to just
-// maintain a list rather than create a `trapBubbledEvent` for each
-var mediaEvents = {
- topAbort: 'abort',
- topCanPlay: 'canplay',
- topCanPlayThrough: 'canplaythrough',
- topDurationChange: 'durationchange',
- topEmptied: 'emptied',
- topEncrypted: 'encrypted',
- topEnded: 'ended',
- topError: 'error',
- topLoadedData: 'loadeddata',
- topLoadedMetadata: 'loadedmetadata',
- topLoadStart: 'loadstart',
- topPause: 'pause',
- topPlay: 'play',
- topPlaying: 'playing',
- topProgress: 'progress',
- topRateChange: 'ratechange',
- topSeeked: 'seeked',
- topSeeking: 'seeking',
- topStalled: 'stalled',
- topSuspend: 'suspend',
- topTimeUpdate: 'timeupdate',
- topVolumeChange: 'volumechange',
- topWaiting: 'waiting'
+/**
+ * @interface Event
+ * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
+ */
+var TransitionEventInterface = {
+ propertyName: null,
+ elapsedTime: null,
+ pseudoElement: null
};
-function trapClickOnNonInteractiveElement(node) {
- // Mobile Safari does not fire properly bubble click events on
- // non-interactive elements, which means delegated click listeners do not
- // fire. The workaround for this bug involves attaching an empty click
- // listener on the target node.
- // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
- // Just set it using the onclick property so that we don't have to manage any
- // bookkeeping for it. Not sure if we need to clear it when the listener is
- // removed.
- // TODO: Only do this for the relevant Safaris maybe?
- node.onclick = emptyFunction_1;
-}
-
-function setInitialDOMProperties(domElement, rootContainerElement, nextProps, isCustomComponentTag) {
- for (var propKey in nextProps) {
- if (!nextProps.hasOwnProperty(propKey)) {
- continue;
- }
- var nextProp = nextProps[propKey];
- if (propKey === STYLE) {
- {
- if (nextProp) {
- // Freeze the next style object so that we can assume it won't be
- // mutated. We have already warned for this in the past.
- Object.freeze(nextProp);
- }
- }
- // Relies on `updateStylesByID` not mutating `styleUpdates`.
- CSSPropertyOperations_1.setValueForStyles(domElement, nextProp);
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- var nextHtml = nextProp ? nextProp[HTML] : undefined;
- if (nextHtml != null) {
- setInnerHTML_1(domElement, nextHtml);
- }
- } else if (propKey === CHILDREN) {
- if (typeof nextProp === 'string') {
- setTextContent_1(domElement, nextProp);
- } else if (typeof nextProp === 'number') {
- setTextContent_1(domElement, '' + nextProp);
- }
- } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING) {
- // Noop
- } else if (registrationNameModules.hasOwnProperty(propKey)) {
- if (nextProp != null) {
- if (true && typeof nextProp !== 'function') {
- warnForInvalidEventListener(propKey, nextProp);
- }
- ensureListeningTo(rootContainerElement, propKey);
- }
- } else if (isCustomComponentTag) {
- DOMPropertyOperations_1.setValueForAttribute(domElement, propKey, nextProp);
- } else if (nextProp != null) {
- // If we're updating to null or undefined, we should remove the property
- // from the DOM node instead of inadvertently setting to a string. This
- // brings us in line with the same behavior we have on initial render.
- DOMPropertyOperations_1.setValueForProperty(domElement, propKey, nextProp);
- }
- }
-}
-
-function updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag) {
- // TODO: Handle wasCustomComponentTag
- for (var i = 0; i < updatePayload.length; i += 2) {
- var propKey = updatePayload[i];
- var propValue = updatePayload[i + 1];
- if (propKey === STYLE) {
- CSSPropertyOperations_1.setValueForStyles(domElement, propValue);
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- setInnerHTML_1(domElement, propValue);
- } else if (propKey === CHILDREN) {
- setTextContent_1(domElement, propValue);
- } else if (isCustomComponentTag) {
- if (propValue != null) {
- DOMPropertyOperations_1.setValueForAttribute(domElement, propKey, propValue);
- } else {
- DOMPropertyOperations_1.deleteValueForAttribute(domElement, propKey);
- }
- } else if (propValue != null) {
- DOMPropertyOperations_1.setValueForProperty(domElement, propKey, propValue);
- } else {
- // If we're updating to null or undefined, we should remove the property
- // from the DOM node instead of inadvertently setting to a string. This
- // brings us in line with the same behavior we have on initial render.
- DOMPropertyOperations_1.deleteValueForProperty(domElement, propKey);
- }
- }
+/**
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticEvent}
+ */
+function SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticEvent$1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}
-var ReactDOMFiberComponent = {
- createElement: function (type, props, rootContainerElement, parentNamespace) {
- // We create tags in the namespace of their parent container, except HTML
- var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement);
- var domElement;
- var namespaceURI = parentNamespace;
- if (namespaceURI === HTML_NAMESPACE$1) {
- namespaceURI = getIntrinsicNamespace$1(type);
- }
- if (namespaceURI === HTML_NAMESPACE$1) {
- {
- var isCustomComponentTag = isCustomComponent_1(type, props);
- // Should this check be gated by parent namespace? Not sure we want to
- // allow <SVG> or <mATH>.
- warning$4(isCustomComponentTag || type === type.toLowerCase(), '<%s /> is using uppercase HTML. Always use lowercase HTML tags ' + 'in React.', type);
- }
-
- if (type === 'script') {
- // Create the script via .innerHTML so its "parser-inserted" flag is
- // set to true and it does not execute
- var div = ownerDocument.createElement('div');
- div.innerHTML = '<script><' + '/script>'; // eslint-disable-line
- // This is guaranteed to yield a script element.
- var firstChild = div.firstChild;
- domElement = div.removeChild(firstChild);
- } else if (typeof props.is === 'string') {
- // $FlowIssue `createElement` should be updated for Web Components
- domElement = ownerDocument.createElement(type, { is: props.is });
- } else {
- // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
- // See discussion in https://github.com/facebook/react/pull/6896
- // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
- domElement = ownerDocument.createElement(type);
- }
- } else {
- domElement = ownerDocument.createElementNS(namespaceURI, type);
- }
-
- {
- if (namespaceURI === HTML_NAMESPACE$1) {
- if (!isCustomComponentTag && Object.prototype.toString.call(domElement) === '[object HTMLUnknownElement]' && !Object.prototype.hasOwnProperty.call(warnedUnknownTags, type)) {
- warnedUnknownTags[type] = true;
- warning$4(false, 'The tag <%s> is unrecognized in this browser. ' + 'If you meant to render a React component, start its name with ' + 'an uppercase letter.', type);
- }
- }
- }
+SyntheticEvent$1.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);
- return domElement;
+/**
+ * @interface WheelEvent
+ * @see http://www.w3.org/TR/DOM-Level-3-Events/
+ */
+var WheelEventInterface = {
+ deltaX: function (event) {
+ return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
+ 'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
},
- createTextNode: function (text, rootContainerElement) {
- return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(text);
+ deltaY: function (event) {
+ return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
+ 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
+ 'wheelDelta' in event ? -event.wheelDelta : 0;
},
- setInitialProperties: function (domElement, tag, rawProps, rootContainerElement) {
- var isCustomComponentTag = isCustomComponent_1(tag, rawProps);
- {
- validatePropertiesInDevelopment(tag, rawProps);
- if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
- warning$4(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName() || 'A component');
- didWarnShadyDOM = true;
- }
- }
-
- // TODO: Make sure that we check isMounted before firing any of these events.
- var props;
- switch (tag) {
- case 'iframe':
- case 'object':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topLoad', 'load', domElement);
- props = rawProps;
- break;
- case 'video':
- case 'audio':
- // Create listener for each media event
- for (var event in mediaEvents) {
- if (mediaEvents.hasOwnProperty(event)) {
- ReactBrowserEventEmitter_1.trapBubbledEvent(event, mediaEvents[event], domElement);
- }
- }
- props = rawProps;
- break;
- case 'source':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topError', 'error', domElement);
- props = rawProps;
- break;
- case 'img':
- case 'image':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topError', 'error', domElement);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topLoad', 'load', domElement);
- props = rawProps;
- break;
- case 'form':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topReset', 'reset', domElement);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topSubmit', 'submit', domElement);
- props = rawProps;
- break;
- case 'details':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topToggle', 'toggle', domElement);
- props = rawProps;
- break;
- case 'input':
- ReactDOMFiberInput.initWrapperState(domElement, rawProps);
- props = ReactDOMFiberInput.getHostProps(domElement, rawProps);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topInvalid', 'invalid', domElement);
- // For controlled components we always need to ensure we're listening
- // to onChange. Even if there is no listener.
- ensureListeningTo(rootContainerElement, 'onChange');
- break;
- case 'option':
- ReactDOMFiberOption.validateProps(domElement, rawProps);
- props = ReactDOMFiberOption.getHostProps(domElement, rawProps);
- break;
- case 'select':
- ReactDOMFiberSelect.initWrapperState(domElement, rawProps);
- props = ReactDOMFiberSelect.getHostProps(domElement, rawProps);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topInvalid', 'invalid', domElement);
- // For controlled components we always need to ensure we're listening
- // to onChange. Even if there is no listener.
- ensureListeningTo(rootContainerElement, 'onChange');
- break;
- case 'textarea':
- ReactDOMFiberTextarea.initWrapperState(domElement, rawProps);
- props = ReactDOMFiberTextarea.getHostProps(domElement, rawProps);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topInvalid', 'invalid', domElement);
- // For controlled components we always need to ensure we're listening
- // to onChange. Even if there is no listener.
- ensureListeningTo(rootContainerElement, 'onChange');
- break;
- default:
- props = rawProps;
- }
-
- assertValidProps_1(tag, props, getCurrentFiberOwnerName);
+ deltaZ: null,
- setInitialDOMProperties(domElement, rootContainerElement, props, isCustomComponentTag);
+ // Browsers without "deltaMode" is reporting in raw wheel delta where one
+ // notch on the scroll is always +/- 120, roughly equivalent to pixels.
+ // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
+ // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
+ deltaMode: null
+};
- switch (tag) {
- case 'input':
- // TODO: Make sure we check if this is still unmounted or do any clean
- // up necessary since we never stop tracking anymore.
- inputValueTracking_1.track(domElement);
- ReactDOMFiberInput.postMountWrapper(domElement, rawProps);
- break;
- case 'textarea':
- // TODO: Make sure we check if this is still unmounted or do any clean
- // up necessary since we never stop tracking anymore.
- inputValueTracking_1.track(domElement);
- ReactDOMFiberTextarea.postMountWrapper(domElement, rawProps);
- break;
- case 'option':
- ReactDOMFiberOption.postMountWrapper(domElement, rawProps);
- break;
- case 'select':
- ReactDOMFiberSelect.postMountWrapper(domElement, rawProps);
- break;
- default:
- if (typeof props.onClick === 'function') {
- // TODO: This cast may not be sound for SVG, MathML or custom elements.
- trapClickOnNonInteractiveElement(domElement);
- }
- break;
- }
- },
+/**
+ * @param {object} dispatchConfig Configuration used to dispatch this event.
+ * @param {string} dispatchMarker Marker identifying the event target.
+ * @param {object} nativeEvent Native browser event.
+ * @extends {SyntheticMouseEvent}
+ */
+function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
+ return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+}
+SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);
- // Calculate the diff between the two objects.
- diffProperties: function (domElement, tag, lastRawProps, nextRawProps, rootContainerElement) {
- {
- validatePropertiesInDevelopment(tag, nextRawProps);
- }
+/**
+ * Turns
+ * ['abort', ...]
+ * into
+ * eventTypes = {
+ * 'abort': {
+ * phasedRegistrationNames: {
+ * bubbled: 'onAbort',
+ * captured: 'onAbortCapture',
+ * },
+ * dependencies: ['topAbort'],
+ * },
+ * ...
+ * };
+ * topLevelEventsToDispatchConfig = {
+ * 'topAbort': { sameConfig }
+ * };
+ */
+var eventTypes$4 = {};
+var topLevelEventsToDispatchConfig = {};
+['abort', 'animationEnd', 'animationIteration', 'animationStart', 'blur', 'cancel', 'canPlay', 'canPlayThrough', 'click', 'close', 'contextMenu', 'copy', 'cut', 'doubleClick', 'drag', 'dragEnd', 'dragEnter', 'dragExit', 'dragLeave', 'dragOver', 'dragStart', 'drop', 'durationChange', 'emptied', 'encrypted', 'ended', 'error', 'focus', 'input', 'invalid', 'keyDown', 'keyPress', 'keyUp', 'load', 'loadedData', 'loadedMetadata', 'loadStart', 'mouseDown', 'mouseMove', 'mouseOut', 'mouseOver', 'mouseUp', 'paste', 'pause', 'play', 'playing', 'progress', 'rateChange', 'reset', 'scroll', 'seeked', 'seeking', 'stalled', 'submit', 'suspend', 'timeUpdate', 'toggle', 'touchCancel', 'touchEnd', 'touchMove', 'touchStart', 'transitionEnd', 'volumeChange', 'waiting', 'wheel'].forEach(function (event) {
+ var capitalizedEvent = event[0].toUpperCase() + event.slice(1);
+ var onEvent = 'on' + capitalizedEvent;
+ var topEvent = 'top' + capitalizedEvent;
- var updatePayload = null;
+ var type = {
+ phasedRegistrationNames: {
+ bubbled: onEvent,
+ captured: onEvent + 'Capture'
+ },
+ dependencies: [topEvent]
+ };
+ eventTypes$4[event] = type;
+ topLevelEventsToDispatchConfig[topEvent] = type;
+});
- var lastProps;
- var nextProps;
- switch (tag) {
- case 'input':
- lastProps = ReactDOMFiberInput.getHostProps(domElement, lastRawProps);
- nextProps = ReactDOMFiberInput.getHostProps(domElement, nextRawProps);
- updatePayload = [];
- break;
- case 'option':
- lastProps = ReactDOMFiberOption.getHostProps(domElement, lastRawProps);
- nextProps = ReactDOMFiberOption.getHostProps(domElement, nextRawProps);
- updatePayload = [];
- break;
- case 'select':
- lastProps = ReactDOMFiberSelect.getHostProps(domElement, lastRawProps);
- nextProps = ReactDOMFiberSelect.getHostProps(domElement, nextRawProps);
- updatePayload = [];
- break;
- case 'textarea':
- lastProps = ReactDOMFiberTextarea.getHostProps(domElement, lastRawProps);
- nextProps = ReactDOMFiberTextarea.getHostProps(domElement, nextRawProps);
- updatePayload = [];
- break;
- default:
- lastProps = lastRawProps;
- nextProps = nextRawProps;
- if (typeof lastProps.onClick !== 'function' && typeof nextProps.onClick === 'function') {
- // TODO: This cast may not be sound for SVG, MathML or custom elements.
- trapClickOnNonInteractiveElement(domElement);
- }
- break;
- }
+// Only used in DEV for exhaustiveness validation.
+var knownHTMLTopLevelTypes = ['topAbort', 'topCancel', 'topCanPlay', 'topCanPlayThrough', 'topClose', 'topDurationChange', 'topEmptied', 'topEncrypted', 'topEnded', 'topError', 'topInput', 'topInvalid', 'topLoad', 'topLoadedData', 'topLoadedMetadata', 'topLoadStart', 'topPause', 'topPlay', 'topPlaying', 'topProgress', 'topRateChange', 'topReset', 'topSeeked', 'topSeeking', 'topStalled', 'topSubmit', 'topSuspend', 'topTimeUpdate', 'topToggle', 'topVolumeChange', 'topWaiting'];
- assertValidProps_1(tag, nextProps, getCurrentFiberOwnerName);
+var SimpleEventPlugin = {
+ eventTypes: eventTypes$4,
- var propKey;
- var styleName;
- var styleUpdates = null;
- for (propKey in lastProps) {
- if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
- continue;
- }
- if (propKey === STYLE) {
- var lastStyle = lastProps[propKey];
- for (styleName in lastStyle) {
- if (lastStyle.hasOwnProperty(styleName)) {
- if (!styleUpdates) {
- styleUpdates = {};
- }
- styleUpdates[styleName] = '';
- }
- }
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN) {
- // Noop. This is handled by the clear text mechanism.
- } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING) {
- // Noop
- } else if (registrationNameModules.hasOwnProperty(propKey)) {
- // This is a special case. If any listener updates we need to ensure
- // that the "current" fiber pointer gets updated so we need a commit
- // to update this element.
- if (!updatePayload) {
- updatePayload = [];
- }
- } else {
- // For all other deleted properties we add it to the queue. We use
- // the whitelist in the commit phase instead.
- (updatePayload = updatePayload || []).push(propKey, null);
- }
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
+ if (!dispatchConfig) {
+ return null;
}
- for (propKey in nextProps) {
- var nextProp = nextProps[propKey];
- var lastProp = lastProps != null ? lastProps[propKey] : undefined;
- if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
- continue;
- }
- if (propKey === STYLE) {
- {
- if (nextProp) {
- // Freeze the next style object so that we can assume it won't be
- // mutated. We have already warned for this in the past.
- Object.freeze(nextProp);
- }
- }
- if (lastProp) {
- // Unset styles on `lastProp` but not on `nextProp`.
- for (styleName in lastProp) {
- if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
- if (!styleUpdates) {
- styleUpdates = {};
- }
- styleUpdates[styleName] = '';
- }
- }
- // Update styles that changed since `lastProp`.
- for (styleName in nextProp) {
- if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
- if (!styleUpdates) {
- styleUpdates = {};
- }
- styleUpdates[styleName] = nextProp[styleName];
- }
- }
- } else {
- // Relies on `updateStylesByID` not mutating `styleUpdates`.
- if (!styleUpdates) {
- if (!updatePayload) {
- updatePayload = [];
- }
- updatePayload.push(propKey, styleUpdates);
- }
- styleUpdates = nextProp;
- }
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- var nextHtml = nextProp ? nextProp[HTML] : undefined;
- var lastHtml = lastProp ? lastProp[HTML] : undefined;
- if (nextHtml != null) {
- if (lastHtml !== nextHtml) {
- (updatePayload = updatePayload || []).push(propKey, '' + nextHtml);
- }
- } else {
- // TODO: It might be too late to clear this if we have children
- // inserted already.
- }
- } else if (propKey === CHILDREN) {
- if (lastProp !== nextProp && (typeof nextProp === 'string' || typeof nextProp === 'number')) {
- (updatePayload = updatePayload || []).push(propKey, '' + nextProp);
- }
- } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING) {
- // Noop
- } else if (registrationNameModules.hasOwnProperty(propKey)) {
- if (nextProp != null) {
- // We eagerly listen to this even though we haven't committed yet.
- if (true && typeof nextProp !== 'function') {
- warnForInvalidEventListener(propKey, nextProp);
- }
- ensureListeningTo(rootContainerElement, propKey);
- }
- if (!updatePayload && lastProp !== nextProp) {
- // This is a special case. If any listener updates we need to ensure
- // that the "current" props pointer gets updated so we need a commit
- // to update this element.
- updatePayload = [];
+ var EventConstructor;
+ switch (topLevelType) {
+ case 'topKeyPress':
+ // Firefox creates a keypress event for function keys too. This removes
+ // the unwanted keypress events. Enter is however both printable and
+ // non-printable. One would expect Tab to be as well (but it isn't).
+ if (getEventCharCode(nativeEvent) === 0) {
+ return null;
}
- } else {
- // For any other property we always add it to the queue and then we
- // filter it out using the whitelist during the commit.
- (updatePayload = updatePayload || []).push(propKey, nextProp);
- }
- }
- if (styleUpdates) {
- (updatePayload = updatePayload || []).push(STYLE, styleUpdates);
- }
- return updatePayload;
- },
-
-
- // Apply the diff.
- updateProperties: function (domElement, updatePayload, tag, lastRawProps, nextRawProps) {
- var wasCustomComponentTag = isCustomComponent_1(tag, lastRawProps);
- var isCustomComponentTag = isCustomComponent_1(tag, nextRawProps);
- // Apply the diff.
- updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag);
-
- // TODO: Ensure that an update gets scheduled if any of the special props
- // changed.
- switch (tag) {
- case 'input':
- // Update the wrapper around inputs *after* updating props. This has to
- // happen after `updateDOMProperties`. Otherwise HTML5 input validations
- // raise warnings and prevent the new value from being assigned.
- ReactDOMFiberInput.updateWrapper(domElement, nextRawProps);
-
- // We also check that we haven't missed a value update, such as a
- // Radio group shifting the checked value to another named radio input.
- inputValueTracking_1.updateValueIfChanged(domElement);
- break;
- case 'textarea':
- ReactDOMFiberTextarea.updateWrapper(domElement, nextRawProps);
- break;
- case 'select':
- // <select> value update needs to occur after <option> children
- // reconciliation
- ReactDOMFiberSelect.postUpdateWrapper(domElement, nextRawProps);
+ /* falls through */
+ case 'topKeyDown':
+ case 'topKeyUp':
+ EventConstructor = SyntheticKeyboardEvent;
break;
- }
- },
- diffHydratedProperties: function (domElement, tag, rawProps, parentNamespace, rootContainerElement) {
- {
- var isCustomComponentTag = isCustomComponent_1(tag, rawProps);
- validatePropertiesInDevelopment(tag, rawProps);
- if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
- warning$4(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName() || 'A component');
- didWarnShadyDOM = true;
- }
- }
-
- // TODO: Make sure that we check isMounted before firing any of these events.
- switch (tag) {
- case 'iframe':
- case 'object':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topLoad', 'load', domElement);
+ case 'topBlur':
+ case 'topFocus':
+ EventConstructor = SyntheticFocusEvent;
break;
- case 'video':
- case 'audio':
- // Create listener for each media event
- for (var event in mediaEvents) {
- if (mediaEvents.hasOwnProperty(event)) {
- ReactBrowserEventEmitter_1.trapBubbledEvent(event, mediaEvents[event], domElement);
- }
+ case 'topClick':
+ // Firefox creates a click event on right mouse clicks. This removes the
+ // unwanted click events.
+ if (nativeEvent.button === 2) {
+ return null;
}
+ /* falls through */
+ case 'topDoubleClick':
+ case 'topMouseDown':
+ case 'topMouseMove':
+ case 'topMouseUp':
+ // TODO: Disabled elements should not respond to mouse events
+ /* falls through */
+ case 'topMouseOut':
+ case 'topMouseOver':
+ case 'topContextMenu':
+ EventConstructor = SyntheticMouseEvent;
break;
- case 'source':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topError', 'error', domElement);
- break;
- case 'img':
- case 'image':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topError', 'error', domElement);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topLoad', 'load', domElement);
- break;
- case 'form':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topReset', 'reset', domElement);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topSubmit', 'submit', domElement);
- break;
- case 'details':
- ReactBrowserEventEmitter_1.trapBubbledEvent('topToggle', 'toggle', domElement);
- break;
- case 'input':
- ReactDOMFiberInput.initWrapperState(domElement, rawProps);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topInvalid', 'invalid', domElement);
- // For controlled components we always need to ensure we're listening
- // to onChange. Even if there is no listener.
- ensureListeningTo(rootContainerElement, 'onChange');
+ case 'topDrag':
+ case 'topDragEnd':
+ case 'topDragEnter':
+ case 'topDragExit':
+ case 'topDragLeave':
+ case 'topDragOver':
+ case 'topDragStart':
+ case 'topDrop':
+ EventConstructor = SyntheticDragEvent;
break;
- case 'option':
- ReactDOMFiberOption.validateProps(domElement, rawProps);
+ case 'topTouchCancel':
+ case 'topTouchEnd':
+ case 'topTouchMove':
+ case 'topTouchStart':
+ EventConstructor = SyntheticTouchEvent;
break;
- case 'select':
- ReactDOMFiberSelect.initWrapperState(domElement, rawProps);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topInvalid', 'invalid', domElement);
- // For controlled components we always need to ensure we're listening
- // to onChange. Even if there is no listener.
- ensureListeningTo(rootContainerElement, 'onChange');
+ case 'topAnimationEnd':
+ case 'topAnimationIteration':
+ case 'topAnimationStart':
+ EventConstructor = SyntheticAnimationEvent;
break;
- case 'textarea':
- ReactDOMFiberTextarea.initWrapperState(domElement, rawProps);
- ReactBrowserEventEmitter_1.trapBubbledEvent('topInvalid', 'invalid', domElement);
- // For controlled components we always need to ensure we're listening
- // to onChange. Even if there is no listener.
- ensureListeningTo(rootContainerElement, 'onChange');
+ case 'topTransitionEnd':
+ EventConstructor = SyntheticTransitionEvent;
break;
- }
-
- assertValidProps_1(tag, rawProps, getCurrentFiberOwnerName);
-
- {
- var extraAttributeNames = new Set();
- var attributes = domElement.attributes;
- for (var i = 0; i < attributes.length; i++) {
- var name = attributes[i].name.toLowerCase();
- switch (name) {
- // Built-in SSR attribute is whitelisted
- case 'data-reactroot':
- break;
- // Controlled attributes are not validated
- // TODO: Only ignore them on controlled tags.
- case 'value':
- break;
- case 'checked':
- break;
- case 'selected':
- break;
- default:
- // Intentionally use the original name.
- // See discussion in https://github.com/facebook/react/pull/10676.
- extraAttributeNames.add(attributes[i].name);
- }
- }
- }
-
- var updatePayload = null;
- for (var propKey in rawProps) {
- if (!rawProps.hasOwnProperty(propKey)) {
- continue;
- }
- var nextProp = rawProps[propKey];
- if (propKey === CHILDREN) {
- // For text content children we compare against textContent. This
- // might match additional HTML that is hidden when we read it using
- // textContent. E.g. "foo" will match "f<span>oo</span>" but that still
- // satisfies our requirement. Our requirement is not to produce perfect
- // HTML and attributes. Ideally we should preserve structure but it's
- // ok not to if the visible content is still enough to indicate what
- // even listeners these nodes might be wired up to.
- // TODO: Warn if there is more than a single textNode as a child.
- // TODO: Should we use domElement.firstChild.nodeValue to compare?
- if (typeof nextProp === 'string') {
- if (domElement.textContent !== nextProp) {
- {
- warnForTextDifference(domElement.textContent, nextProp);
- }
- updatePayload = [CHILDREN, nextProp];
- }
- } else if (typeof nextProp === 'number') {
- if (domElement.textContent !== '' + nextProp) {
- {
- warnForTextDifference(domElement.textContent, nextProp);
- }
- updatePayload = [CHILDREN, '' + nextProp];
- }
- }
- } else if (registrationNameModules.hasOwnProperty(propKey)) {
- if (nextProp != null) {
- if (true && typeof nextProp !== 'function') {
- warnForInvalidEventListener(propKey, nextProp);
- }
- ensureListeningTo(rootContainerElement, propKey);
- }
- } else {
- // Validate that the properties correspond to their expected values.
- var serverValue;
- var propertyInfo;
- if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING ||
- // Controlled attributes are not validated
- // TODO: Only ignore them on controlled tags.
- propKey === 'value' || propKey === 'checked' || propKey === 'selected') {
- // Noop
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- var rawHtml = nextProp ? nextProp[HTML] || '' : '';
- var serverHTML = domElement.innerHTML;
- var expectedHTML = normalizeHTML(domElement, rawHtml);
- if (expectedHTML !== serverHTML) {
- warnForPropDifference(propKey, serverHTML, expectedHTML);
- }
- } else if (propKey === STYLE) {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames['delete'](propKey);
- var expectedStyle = CSSPropertyOperations_1.createDangerousStringForStyles(nextProp);
- serverValue = domElement.getAttribute('style');
- if (expectedStyle !== serverValue) {
- warnForPropDifference(propKey, serverValue, expectedStyle);
- }
- } else if (isCustomComponentTag) {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames['delete'](propKey.toLowerCase());
- serverValue = DOMPropertyOperations_1.getValueForAttribute(domElement, propKey, nextProp);
-
- if (nextProp !== serverValue) {
- warnForPropDifference(propKey, serverValue, nextProp);
- }
- } else if (DOMProperty_1.shouldSetAttribute(propKey, nextProp)) {
- if (propertyInfo = DOMProperty_1.getPropertyInfo(propKey)) {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames['delete'](propertyInfo.attributeName);
- serverValue = DOMPropertyOperations_1.getValueForProperty(domElement, propKey, nextProp);
- } else {
- var ownNamespace = parentNamespace;
- if (ownNamespace === HTML_NAMESPACE$1) {
- ownNamespace = getIntrinsicNamespace$1(tag);
- }
- if (ownNamespace === HTML_NAMESPACE$1) {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames['delete'](propKey.toLowerCase());
- } else {
- // $FlowFixMe - Should be inferred as not undefined.
- extraAttributeNames['delete'](propKey);
- }
- serverValue = DOMPropertyOperations_1.getValueForAttribute(domElement, propKey, nextProp);
- }
-
- if (nextProp !== serverValue) {
- warnForPropDifference(propKey, serverValue, nextProp);
- }
- }
- }
- }
-
- {
- // $FlowFixMe - Should be inferred as not undefined.
- if (extraAttributeNames.size > 0) {
- // $FlowFixMe - Should be inferred as not undefined.
- warnForExtraAttributes(extraAttributeNames);
- }
- }
-
- switch (tag) {
- case 'input':
- // TODO: Make sure we check if this is still unmounted or do any clean
- // up necessary since we never stop tracking anymore.
- inputValueTracking_1.track(domElement);
- ReactDOMFiberInput.postMountWrapper(domElement, rawProps);
+ case 'topScroll':
+ EventConstructor = SyntheticUIEvent;
break;
- case 'textarea':
- // TODO: Make sure we check if this is still unmounted or do any clean
- // up necessary since we never stop tracking anymore.
- inputValueTracking_1.track(domElement);
- ReactDOMFiberTextarea.postMountWrapper(domElement, rawProps);
+ case 'topWheel':
+ EventConstructor = SyntheticWheelEvent;
break;
- case 'select':
- case 'option':
- // For input and textarea we current always set the value property at
- // post mount to force it to diverge from attributes. However, for
- // option and select we don't quite do the same thing and select
- // is not resilient to the DOM state changing so we don't do that here.
- // TODO: Consider not doing this for input and textarea.
+ case 'topCopy':
+ case 'topCut':
+ case 'topPaste':
+ EventConstructor = SyntheticClipboardEvent;
break;
default:
- if (typeof rawProps.onClick === 'function') {
- // TODO: This cast may not be sound for SVG, MathML or custom elements.
- trapClickOnNonInteractiveElement(domElement);
+ {
+ if (knownHTMLTopLevelTypes.indexOf(topLevelType) === -1) {
+ warning_1(false, 'SimpleEventPlugin: Unhandled event type, `%s`. This warning ' + 'is likely caused by a bug in React. Please file an issue.', topLevelType);
+ }
}
+ // HTML Events
+ // @see http://www.w3.org/TR/html5/index.html#events-0
+ EventConstructor = SyntheticEvent$1;
break;
}
-
- return updatePayload;
- },
- diffHydratedText: function (textNode, text) {
- var isDifferent = textNode.nodeValue !== text;
- {
- if (isDifferent) {
- warnForTextDifference(textNode.nodeValue, text);
- }
- }
- return isDifferent;
- },
- warnForDeletedHydratableElement: function (parentNode, child) {
- {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- warning$4(false, 'Did not expect server HTML to contain a <%s> in <%s>.', child.nodeName.toLowerCase(), parentNode.nodeName.toLowerCase());
- }
- },
- warnForDeletedHydratableText: function (parentNode, child) {
- {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- warning$4(false, 'Did not expect server HTML to contain the text node "%s" in <%s>.', child.nodeValue, parentNode.nodeName.toLowerCase());
- }
- },
- warnForInsertedHydratedElement: function (parentNode, tag, props) {
- {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- warning$4(false, 'Expected server HTML to contain a matching <%s> in <%s>.', tag, parentNode.nodeName.toLowerCase());
- }
- },
- warnForInsertedHydratedText: function (parentNode, text) {
- {
- if (text === '') {
- // We expect to insert empty text nodes since they're not represented in
- // the HTML.
- // TODO: Remove this special case if we can just avoid inserting empty
- // text nodes.
- return;
- }
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- warning$4(false, 'Expected server HTML to contain a matching text node for "%s" in <%s>.', text, parentNode.nodeName.toLowerCase());
- }
- },
- restoreControlledState: function (domElement, tag, props) {
- switch (tag) {
- case 'input':
- ReactDOMFiberInput.restoreControlledState(domElement, props);
- return;
- case 'textarea':
- ReactDOMFiberTextarea.restoreControlledState(domElement, props);
- return;
- case 'select':
- ReactDOMFiberSelect.restoreControlledState(domElement, props);
- return;
- }
+ var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
+ accumulateTwoPhaseDispatches(event);
+ return event;
}
};
-var ReactDOMFiberComponent_1 = ReactDOMFiberComponent;
-
-// This is a built-in polyfill for requestIdleCallback. It works by scheduling
-// a requestAnimationFrame, storing the time for the start of the frame, then
-// scheduling a postMessage which gets scheduled after paint. Within the
-// postMessage handler do as much work as possible until time + frame rate.
-// By separating the idle call into a separate event tick we ensure that
-// layout, paint and other browser work is counted against the available time.
-// The frame rate is dynamically adjusted.
-
-
+setHandleTopLevel(handleTopLevel);
-{
- var warning$19 = warning_1;
+/**
+ * Inject modules for resolving DOM hierarchy and plugin ordering.
+ */
+injection$1.injectEventPluginOrder(DOMEventPluginOrder);
+injection$2.injectComponentTree(ReactDOMComponentTree);
- if (ExecutionEnvironment_1.canUseDOM && typeof requestAnimationFrame !== 'function') {
- warning$19(false, 'React depends on requestAnimationFrame. Make sure that you load a ' + 'polyfill in older browsers. http://fb.me/react-polyfills');
- }
-}
+/**
+ * Some important event plugins included by default (without having to require
+ * them).
+ */
+injection$1.injectEventPluginsByName({
+ SimpleEventPlugin: SimpleEventPlugin,
+ EnterLeaveEventPlugin: EnterLeaveEventPlugin,
+ ChangeEventPlugin: ChangeEventPlugin,
+ SelectEventPlugin: SelectEventPlugin,
+ BeforeInputEventPlugin: BeforeInputEventPlugin
+});
-// TODO: There's no way to cancel, because Fiber doesn't atm.
-var rIC = void 0;
+var enableAsyncSubtreeAPI = true;
+var enableAsyncSchedulingByDefaultInReactDOM = false;
+// Exports ReactDOM.createRoot
+var enableCreateRoot = false;
+var enableUserTimingAPI = true;
-if (!ExecutionEnvironment_1.canUseDOM) {
- rIC = function (frameCallback) {
- setTimeout(function () {
- frameCallback({
- timeRemaining: function () {
- return Infinity;
- }
- });
- });
- return 0;
- };
-} else if (typeof requestIdleCallback !== 'function') {
- // Polyfill requestIdleCallback.
+// Mutating mode (React DOM, React ART, React Native):
+var enableMutatingReconciler = true;
+// Experimental noop mode (currently unused):
+var enableNoopReconciler = false;
+// Experimental persistent mode (CS):
+var enablePersistentReconciler = false;
- var scheduledRAFCallback = null;
- var scheduledRICCallback = null;
+// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
+var debugRenderPhaseSideEffects = false;
- var isIdleScheduled = false;
- var isAnimationFrameScheduled = false;
+// Only used in www builds.
- var frameDeadline = 0;
- // We start out assuming that we run at 30fps but then the heuristic tracking
- // will adjust this value to a faster fps if we get more frequent animation
- // frames.
- var previousFrameTime = 33;
- var activeFrameTime = 33;
+/**
+ * Copyright (c) 2013-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
- var frameDeadlineObject = {
- timeRemaining: typeof performance === 'object' && typeof performance.now === 'function' ? function () {
- // We assume that if we have a performance timer that the rAF callback
- // gets a performance timer value. Not sure if this is always true.
- return frameDeadline - performance.now();
- } : function () {
- // As a fallback we use Date.now.
- return frameDeadline - Date.now();
- }
- };
- // We use the postMessage trick to defer idle work until after the repaint.
- var messageKey = '__reactIdleCallback$' + Math.random().toString(36).slice(2);
- var idleTick = function (event) {
- if (event.source !== window || event.data !== messageKey) {
- return;
- }
- isIdleScheduled = false;
- var callback = scheduledRICCallback;
- scheduledRICCallback = null;
- if (callback !== null) {
- callback(frameDeadlineObject);
- }
- };
- // Assumes that we have addEventListener in this environment. Might need
- // something better for old IE.
- window.addEventListener('message', idleTick, false);
- var animationTick = function (rafTime) {
- isAnimationFrameScheduled = false;
- var nextFrameTime = rafTime - frameDeadline + activeFrameTime;
- if (nextFrameTime < activeFrameTime && previousFrameTime < activeFrameTime) {
- if (nextFrameTime < 8) {
- // Defensive coding. We don't support higher frame rates than 120hz.
- // If we get lower than that, it is probably a bug.
- nextFrameTime = 8;
- }
- // If one frame goes long, then the next one can be short to catch up.
- // If two frames are short in a row, then that's an indication that we
- // actually have a higher frame rate than what we're currently optimizing.
- // We adjust our heuristic dynamically accordingly. For example, if we're
- // running on 120hz display or 90hz VR display.
- // Take the max of the two in case one of them was an anomaly due to
- // missed frame deadlines.
- activeFrameTime = nextFrameTime < previousFrameTime ? previousFrameTime : nextFrameTime;
- } else {
- previousFrameTime = nextFrameTime;
- }
- frameDeadline = rafTime + activeFrameTime;
- if (!isIdleScheduled) {
- isIdleScheduled = true;
- window.postMessage(messageKey, '*');
- }
- var callback = scheduledRAFCallback;
- scheduledRAFCallback = null;
- if (callback !== null) {
- callback(rafTime);
- }
- };
+var emptyObject = {};
- rIC = function (callback) {
- // This assumes that we only schedule one callback at a time because that's
- // how Fiber uses it.
- scheduledRICCallback = callback;
- if (!isAnimationFrameScheduled) {
- // If rAF didn't already schedule one, we need to schedule a frame.
- // TODO: If this rAF doesn't materialize because the browser throttles, we
- // might want to still have setTimeout trigger rIC as a backup to ensure
- // that we keep performing work.
- isAnimationFrameScheduled = true;
- requestAnimationFrame(animationTick);
- }
- return 0;
- };
-} else {
- rIC = requestIdleCallback;
+{
+ Object.freeze(emptyObject);
}
-var rIC_1 = rIC;
-
-var ReactDOMFrameScheduling = {
- rIC: rIC_1
-};
+var emptyObject_1 = emptyObject;
/**
* 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.
- *
- * @providesModule ReactFeatureFlags
- *
*/
-var ReactFeatureFlags = {
- enableAsyncSubtreeAPI: true
-};
-var ReactFeatureFlags_1 = ReactFeatureFlags;
+
+var ReactPropTypesSecret$1 = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
+
+var ReactPropTypesSecret_1 = ReactPropTypesSecret$1;
/**
* 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.
- *
- * @providesModule ReactPriorityLevel
- *
*/
-var ReactPriorityLevel = {
- NoWork: 0, // No work is pending.
- SynchronousPriority: 1, // For controlled text inputs. Synchronous side-effects.
- TaskPriority: 2, // Completes at the end of the current tick.
- HighPriority: 3, // Interaction that needs to complete pretty soon to feel responsive.
- LowPriority: 4, // Data fetching, or result from updating stores.
- OffscreenPriority: 5 };
-
-var CallbackEffect = ReactTypeOfSideEffect.Callback;
-
-var NoWork = ReactPriorityLevel.NoWork;
-var SynchronousPriority = ReactPriorityLevel.SynchronousPriority;
-var TaskPriority = ReactPriorityLevel.TaskPriority;
-
-var ClassComponent$2 = ReactTypeOfWork.ClassComponent;
-var HostRoot$2 = ReactTypeOfWork.HostRoot;
{
- var warning$21 = warning_1;
+ var invariant$2 = invariant_1;
+ var warning$2 = warning_1;
+ var ReactPropTypesSecret = ReactPropTypesSecret_1;
+ var loggedTypeFailures = {};
}
-// Callbacks are not validated until invocation
+/**
+ * Assert that the values match with the type specs.
+ * Error messages are memorized and will only be shown once.
+ *
+ * @param {object} typeSpecs Map of name to a ReactPropType
+ * @param {object} values Runtime values that need to be type-checked
+ * @param {string} location e.g. "prop", "context", "child context"
+ * @param {string} componentName Name of the component for error messages.
+ * @param {?Function} getStack Returns the component stack.
+ * @private
+ */
+function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
+ {
+ for (var typeSpecName in typeSpecs) {
+ if (typeSpecs.hasOwnProperty(typeSpecName)) {
+ var error;
+ // Prop type validation may throw. In case they do, we don't want to
+ // fail the render phase where it didn't fail before. So we log it.
+ // After these have been cleaned up, we'll let them throw.
+ try {
+ // This is intentionally an invariant that gets caught. It's the same
+ // behavior as without this statement except with a better message.
+ invariant$2(typeof typeSpecs[typeSpecName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'the `prop-types` package, but received `%s`.', componentName || 'React class', location, typeSpecName, typeof typeSpecs[typeSpecName]);
+ error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
+ } catch (ex) {
+ error = ex;
+ }
+ warning$2(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error);
+ if (error instanceof Error && !(error.message in loggedTypeFailures)) {
+ // Only monitor this failure once because there tends to be a lot of the
+ // same error.
+ loggedTypeFailures[error.message] = true;
+ var stack = getStack ? getStack() : '';
-// 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.
+ warning$2(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : '');
+ }
+ }
+ }
+ }
+}
+var checkPropTypes_1 = checkPropTypes;
-var _queue1 = void 0;
-var _queue2 = void 0;
+var valueStack = [];
-function comparePriority(a, b) {
- // When comparing update priorities, treat sync and Task work as equal.
- // TODO: Could we avoid the need for this by always coercing sync priority
- // to Task when scheduling an update?
- if ((a === TaskPriority || a === SynchronousPriority) && (b === TaskPriority || b === SynchronousPriority)) {
- return 0;
- }
- if (a === NoWork && b !== NoWork) {
- return -255;
- }
- if (a !== NoWork && b === NoWork) {
- return 255;
- }
- return a - b;
+{
+ var fiberStack = [];
}
-function createUpdateQueue() {
- var queue = {
- first: null,
- last: null,
- hasForceUpdate: false,
- callbackList: null
- };
- {
- queue.isProcessing = false;
- }
- return queue;
-}
+var index = -1;
-function cloneUpdate(update) {
+function createCursor(defaultValue) {
return {
- priorityLevel: update.priorityLevel,
- partialState: update.partialState,
- callback: update.callback,
- isReplace: update.isReplace,
- isForced: update.isForced,
- isTopLevelUnmount: update.isTopLevelUnmount,
- next: null
+ current: defaultValue
};
}
-function insertUpdateIntoQueue(queue, update, insertAfter, insertBefore) {
- if (insertAfter !== null) {
- insertAfter.next = update;
- } else {
- // This is the first item in the queue.
- update.next = queue.first;
- queue.first = update;
- }
- if (insertBefore !== null) {
- update.next = insertBefore;
- } else {
- // This is the last item in the queue.
- queue.last = update;
- }
-}
-// Returns the update after which the incoming update should be inserted into
-// the queue, or null if it should be inserted at beginning.
-function findInsertionPosition(queue, update) {
- var priorityLevel = update.priorityLevel;
- var insertAfter = null;
- var insertBefore = null;
- if (queue.last !== null && comparePriority(queue.last.priorityLevel, priorityLevel) <= 0) {
- // Fast path for the common case where the update should be inserted at
- // the end of the queue.
- insertAfter = queue.last;
- } else {
- insertBefore = queue.first;
- while (insertBefore !== null && comparePriority(insertBefore.priorityLevel, priorityLevel) <= 0) {
- insertAfter = insertBefore;
- insertBefore = insertBefore.next;
+function pop(cursor, fiber) {
+ if (index < 0) {
+ {
+ warning_1(false, 'Unexpected pop.');
}
- }
- return insertAfter;
-}
-
-function ensureUpdateQueues(fiber) {
- var alternateFiber = fiber.alternate;
-
- var queue1 = fiber.updateQueue;
- if (queue1 === null) {
- queue1 = fiber.updateQueue = createUpdateQueue();
+ return;
}
- var queue2 = void 0;
- if (alternateFiber !== null) {
- queue2 = alternateFiber.updateQueue;
- if (queue2 === null) {
- queue2 = alternateFiber.updateQueue = createUpdateQueue();
+ {
+ if (fiber !== fiberStack[index]) {
+ warning_1(false, 'Unexpected Fiber popped.');
}
- } else {
- queue2 = null;
}
- _queue1 = queue1;
- // Return null if there is no alternate queue, or if its queue is the same.
- _queue2 = queue2 !== queue1 ? queue2 : null;
-}
+ cursor.current = valueStack[index];
-// The work-in-progress queue is a subset of the current queue (if it exists).
-// We need to insert the incoming update into both lists. However, it's possible
-// that the correct position in one list will be different from the position in
-// the other. Consider the following case:
-//
-// Current: 3-5-6
-// Work-in-progress: 6
-//
-// Then we receive an update with priority 4 and insert it into each list:
-//
-// Current: 3-4-5-6
-// Work-in-progress: 4-6
-//
-// In the current queue, the new update's `next` pointer points to the update
-// with priority 5. But in the work-in-progress queue, the pointer points to the
-// update with priority 6. Because these two queues share the same persistent
-// data structure, this won't do. (This can only happen when the incoming update
-// has higher priority than all the updates in the work-in-progress queue.)
-//
-// To solve this, in the case where the incoming update needs to be inserted
-// into two different positions, we'll make a clone of the update and insert
-// each copy into a separate queue. This forks the list while maintaining a
-// persistent structure, because the update that is added to the work-in-progress
-// is always added to the front of the list.
-//
-// However, if incoming update is inserted into the same position of both lists,
-// we shouldn't make a copy.
-//
-// If the update is cloned, it returns the cloned update.
-function insertUpdate(fiber, update) {
- // We'll have at least one and at most two distinct update queues.
- ensureUpdateQueues(fiber);
- var queue1 = _queue1;
- var queue2 = _queue2;
+ valueStack[index] = null;
- // Warn if an update is scheduled from inside an updater function.
{
- if (queue1.isProcessing || queue2 !== null && queue2.isProcessing) {
- warning$21(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.');
- }
+ fiberStack[index] = null;
}
- // Find the insertion position in the first queue.
- var insertAfter1 = findInsertionPosition(queue1, update);
- var insertBefore1 = insertAfter1 !== null ? insertAfter1.next : queue1.first;
+ index--;
+}
- if (queue2 === null) {
- // If there's no alternate queue, there's nothing else to do but insert.
- insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1);
- return null;
+function push(cursor, value, fiber) {
+ index++;
+
+ valueStack[index] = cursor.current;
+
+ {
+ fiberStack[index] = fiber;
}
- // If there is an alternate queue, find the insertion position.
- var insertAfter2 = findInsertionPosition(queue2, update);
- var insertBefore2 = insertAfter2 !== null ? insertAfter2.next : queue2.first;
+ cursor.current = value;
+}
- // Now we can insert into the first queue. This must come after finding both
- // insertion positions because it mutates the list.
- insertUpdateIntoQueue(queue1, update, insertAfter1, insertBefore1);
+function reset$1() {
+ while (index > -1) {
+ valueStack[index] = null;
- // See if the insertion positions are equal. Be careful to only compare
- // non-null values.
- if (insertBefore1 === insertBefore2 && insertBefore1 !== null || insertAfter1 === insertAfter2 && insertAfter1 !== null) {
- // The insertion positions are the same, so when we inserted into the first
- // queue, it also inserted into the alternate. All we need to do is update
- // the alternate queue's `first` and `last` pointers, in case they
- // have changed.
- if (insertAfter2 === null) {
- queue2.first = update;
- }
- if (insertBefore2 === null) {
- queue2.last = null;
+ {
+ fiberStack[index] = null;
}
- return null;
- } else {
- // The insertion positions are different, so we need to clone the update and
- // insert the clone into the alternate queue.
- var update2 = cloneUpdate(update);
- insertUpdateIntoQueue(queue2, update2, insertAfter2, insertBefore2);
- return update2;
- }
-}
-
-function addUpdate(fiber, partialState, callback, priorityLevel) {
- var update = {
- priorityLevel: priorityLevel,
- partialState: partialState,
- callback: callback,
- isReplace: false,
- isForced: false,
- isTopLevelUnmount: false,
- next: null
- };
- insertUpdate(fiber, update);
-}
-var addUpdate_1 = addUpdate;
-
-function addReplaceUpdate(fiber, state, callback, priorityLevel) {
- var update = {
- priorityLevel: priorityLevel,
- partialState: state,
- callback: callback,
- isReplace: true,
- isForced: false,
- isTopLevelUnmount: false,
- next: null
- };
- insertUpdate(fiber, update);
-}
-var addReplaceUpdate_1 = addReplaceUpdate;
-
-function addForceUpdate(fiber, callback, priorityLevel) {
- var update = {
- priorityLevel: priorityLevel,
- partialState: null,
- callback: callback,
- isReplace: false,
- isForced: true,
- isTopLevelUnmount: false,
- next: null
- };
- insertUpdate(fiber, update);
-}
-var addForceUpdate_1 = addForceUpdate;
-function getUpdatePriority(fiber) {
- var updateQueue = fiber.updateQueue;
- if (updateQueue === null) {
- return NoWork;
- }
- if (fiber.tag !== ClassComponent$2 && fiber.tag !== HostRoot$2) {
- return NoWork;
+ index--;
}
- return updateQueue.first !== null ? updateQueue.first.priorityLevel : NoWork;
}
-var getUpdatePriority_1 = getUpdatePriority;
-
-function addTopLevelUpdate$1(fiber, partialState, callback, priorityLevel) {
- var isTopLevelUnmount = partialState.element === null;
- var update = {
- priorityLevel: priorityLevel,
- partialState: partialState,
- callback: callback,
- isReplace: false,
- isForced: false,
- isTopLevelUnmount: isTopLevelUnmount,
- next: null
- };
- var update2 = insertUpdate(fiber, update);
-
- if (isTopLevelUnmount) {
- // TODO: Redesign the top-level mount/update/unmount API to avoid this
- // special case.
- var queue1 = _queue1;
- var queue2 = _queue2;
+var describeComponentFrame = function (name, source, ownerName) {
+ return '\n in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
+};
- // Drop all updates that are lower-priority, so that the tree is not
- // remounted. We need to do this for both queues.
- if (queue1 !== null && update.next !== null) {
- update.next = null;
- queue1.last = update;
- }
- if (queue2 !== null && update2 !== null && update2.next !== null) {
- update2.next = null;
- queue2.last = update;
- }
+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 '';
}
}
-var addTopLevelUpdate_1 = addTopLevelUpdate$1;
-function getStateFromUpdate(update, instance, prevState, props) {
- var partialState = update.partialState;
- if (typeof partialState === 'function') {
- var updateFn = partialState;
- return updateFn.call(instance, prevState, props);
- } else {
- return partialState;
- }
+// 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 beginUpdateQueue(current, workInProgress, queue, instance, prevState, props, priorityLevel) {
- 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 = {
- first: currentQueue.first,
- last: currentQueue.last,
- // These fields are no longer valid because they were already committed.
- // Reset them.
- callbackList: null,
- hasForceUpdate: false
- };
- }
-
+function getCurrentFiberOwnerName() {
{
- // Set this flag so we can warn if setState is called inside the update
- // function of another setState.
- queue.isProcessing = true;
- }
-
- // Calculate these using the the existing values as a base.
- var callbackList = queue.callbackList;
- var hasForceUpdate = queue.hasForceUpdate;
-
- // Applies updates with matching priority to the previous state to create
- // a new state object.
- var state = prevState;
- var dontMutatePrevState = true;
- var update = queue.first;
- while (update !== null && comparePriority(update.priorityLevel, priorityLevel) <= 0) {
- // Remove each update from the queue right before it is processed. That way
- // if setState is called from inside an updater function, the new update
- // will be inserted in the correct position.
- queue.first = update.next;
- if (queue.first === null) {
- queue.last = null;
- }
-
- 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) {
- state = assign({}, state, _partialState);
- } else {
- state = assign(state, _partialState);
- }
- dontMutatePrevState = false;
- }
- }
- if (update.isForced) {
- hasForceUpdate = true;
+ var fiber = ReactDebugCurrentFiber.current;
+ if (fiber === null) {
+ return null;
}
- // Second condition ignores top-level unmount callbacks if they are not the
- // last update in the queue, since a subsequent update will cause a remount.
- if (update.callback !== null && !(update.isTopLevelUnmount && update.next !== null)) {
- callbackList = callbackList !== null ? callbackList : [];
- callbackList.push(update.callback);
- workInProgress.effectTag |= CallbackEffect;
+ var owner = fiber._debugOwner;
+ if (owner !== null && typeof owner !== 'undefined') {
+ return getComponentName(owner);
}
- update = update.next;
- }
-
- queue.callbackList = callbackList;
- queue.hasForceUpdate = hasForceUpdate;
-
- if (queue.first === null && callbackList === null && !hasForceUpdate) {
- // The queue is empty and there are no callbacks. We can reset it.
- workInProgress.updateQueue = null;
- }
-
- {
- // No longer processing.
- queue.isProcessing = false;
}
-
- return state;
+ return null;
}
-var beginUpdateQueue_1 = beginUpdateQueue;
-function commitCallbacks(finishedWork, 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 _callback = callbackList[i];
- !(typeof _callback === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback) : void 0;
- _callback.call(context);
+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;
}
-var commitCallbacks_1 = commitCallbacks;
-var ReactFiberUpdateQueue = {
- addUpdate: addUpdate_1,
- addReplaceUpdate: addReplaceUpdate_1,
- addForceUpdate: addForceUpdate_1,
- getUpdatePriority: getUpdatePriority_1,
- addTopLevelUpdate: addTopLevelUpdate_1,
- beginUpdateQueue: beginUpdateQueue_1,
- commitCallbacks: commitCallbacks_1
-};
-
-/**
- * Copyright (c) 2013-present, Facebook, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- */
-
-var emptyObject = {};
-
-{
- Object.freeze(emptyObject);
+function resetCurrentFiber() {
+ ReactDebugCurrentFrame.getCurrentStack = null;
+ ReactDebugCurrentFiber.current = null;
+ ReactDebugCurrentFiber.phase = null;
}
-var emptyObject_1 = emptyObject;
-
-{
- var warning$23 = warning_1;
+function setCurrentFiber(fiber) {
+ ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum;
+ ReactDebugCurrentFiber.current = fiber;
+ ReactDebugCurrentFiber.phase = null;
}
-var valueStack = [];
-
-{
- var fiberStack = [];
+function setCurrentPhase(phase) {
+ ReactDebugCurrentFiber.phase = phase;
}
-var index$2 = -1;
+var ReactDebugCurrentFiber = {
+ current: null,
+ phase: null,
+ resetCurrentFiber: resetCurrentFiber,
+ setCurrentFiber: setCurrentFiber,
+ setCurrentPhase: setCurrentPhase,
+ getCurrentFiberOwnerName: getCurrentFiberOwnerName,
+ getCurrentFiberStackAddendum: getCurrentFiberStackAddendum
+};
+
+// Prefix measurements so that it's possible to filter them.
+// Longer prefixes are hard to read in DevTools.
+var reactEmoji = '\u269B';
+var warningEmoji = '\u26D4';
+var supportsUserTiming = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function';
+
+// Keep track of current fiber so that we know the path to unwind on pause.
+// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them?
+var currentFiber = null;
+// If we're in the middle of user code, which fiber and method is it?
+// Reusing `currentFiber` would be confusing for this because user code fiber
+// can change during commit phase too, but we don't need to unwind it (since
+// lifecycles in the commit phase don't resemble a tree).
+var currentPhase = null;
+var currentPhaseFiber = null;
+// Did lifecycle hook schedule an update? This is often a performance problem,
+// so we will keep track of it, and include it in the report.
+// Track commits caused by cascading updates.
+var isCommitting = false;
+var hasScheduledUpdateInCurrentCommit = false;
+var hasScheduledUpdateInCurrentPhase = false;
+var commitCountInCurrentWorkLoop = 0;
+var effectCountInCurrentCommit = 0;
+var isWaitingForCallback = false;
+// During commits, we only show a measurement once per method name
+// to avoid stretch the commit phase with measurement overhead.
+var labelsInCurrentCommit = new Set();
+
+var formatMarkName = function (markName) {
+ return reactEmoji + ' ' + markName;
+};
+
+var formatLabel = function (label, warning) {
+ var prefix = warning ? warningEmoji + ' ' : reactEmoji + ' ';
+ var suffix = warning ? ' Warning: ' + warning : '';
+ return '' + prefix + label + suffix;
+};
+
+var beginMark = function (markName) {
+ performance.mark(formatMarkName(markName));
+};
+
+var clearMark = function (markName) {
+ performance.clearMarks(formatMarkName(markName));
+};
+
+var endMark = function (label, markName, warning) {
+ var formattedMarkName = formatMarkName(markName);
+ var formattedLabel = formatLabel(label, warning);
+ try {
+ performance.measure(formattedLabel, formattedMarkName);
+ } catch (err) {}
+ // If previous mark was missing for some reason, this will throw.
+ // This could only happen if React crashed in an unexpected place earlier.
+ // Don't pile on with more errors.
-var createCursor$1 = function (defaultValue) {
- return {
- current: defaultValue
- };
+ // Clear marks immediately to avoid growing buffer.
+ performance.clearMarks(formattedMarkName);
+ performance.clearMeasures(formattedLabel);
};
-var isEmpty = function () {
- return index$2 === -1;
+var getFiberMarkName = function (label, debugID) {
+ return label + ' (#' + debugID + ')';
};
-var pop$1 = function (cursor, fiber) {
- if (index$2 < 0) {
- {
- warning$23(false, 'Unexpected pop.');
- }
- return;
- }
-
- {
- if (fiber !== fiberStack[index$2]) {
- warning$23(false, 'Unexpected Fiber popped.');
- }
+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;
}
+};
- cursor.current = valueStack[index$2];
-
- valueStack[index$2] = null;
+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);
- {
- fiberStack[index$2] = null;
+ 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);
- index$2--;
+ var markName = getFiberMarkName(label, debugID);
+ beginMark(markName);
+ return true;
};
-var push$1 = function (cursor, value, fiber) {
- index$2++;
+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);
+};
- valueStack[index$2] = cursor.current;
+var endFiberMark = function (fiber, phase, warning) {
+ 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);
+};
- {
- fiberStack[index$2] = fiber;
+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 ReturnComponent:
+ case Fragment:
+ return true;
+ default:
+ return false;
}
-
- cursor.current = value;
};
-var reset = function () {
- while (index$2 > -1) {
- valueStack[index$2] = null;
+var clearPendingPhaseMeasurement = function () {
+ if (currentPhase !== null && currentPhaseFiber !== null) {
+ clearFiberMark(currentPhaseFiber, currentPhase);
+ }
+ currentPhaseFiber = null;
+ currentPhase = null;
+ hasScheduledUpdateInCurrentPhase = false;
+};
- {
- fiberStack[index$2] = null;
+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);
}
-
- index$2--;
+ fiber = fiber['return'];
}
};
-var ReactFiberStack = {
- createCursor: createCursor$1,
- isEmpty: isEmpty,
- pop: pop$1,
- push: push$1,
- reset: reset
+var resumeTimersRecursively = function (fiber) {
+ if (fiber['return'] !== null) {
+ resumeTimersRecursively(fiber['return']);
+ }
+ if (fiber._debugIsCurrentlyTiming) {
+ beginFiberMark(fiber, null);
+ }
};
-// Trust the developer to only use this with a true check
-/**
- * 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.
- *
- * @providesModule ReactDebugFiberPerf
- *
- */
-
-var ReactDebugFiberPerf = null;
-
-{
- var _require$8 = ReactTypeOfWork,
- HostRoot$4 = _require$8.HostRoot,
- HostComponent$4 = _require$8.HostComponent,
- HostText$2 = _require$8.HostText,
- HostPortal$1 = _require$8.HostPortal,
- YieldComponent = _require$8.YieldComponent,
- Fragment = _require$8.Fragment;
-
- var getComponentName$5 = getComponentName_1;
-
- // 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;
- // During commits, we only show a measurement once per method name
- // to avoid stretch the commit phase with measurement overhead.
- var labelsInCurrentCommit = new Set();
-
- var formatMarkName = function (markName) {
- return reactEmoji + ' ' + markName;
- };
-
- var formatLabel = function (label, warning) {
- var prefix = warning ? warningEmoji + ' ' : reactEmoji + ' ';
- var suffix = warning ? ' Warning: ' + warning : '';
- return '' + prefix + label + suffix;
- };
-
- var beginMark = function (markName) {
- performance.mark(formatMarkName(markName));
- };
-
- var clearMark = function (markName) {
- performance.clearMarks(formatMarkName(markName));
- };
+var resumeTimers = function () {
+ // Resumes all measurements that were active during the last deferred loop.
+ if (currentFiber !== null) {
+ resumeTimersRecursively(currentFiber);
+ }
+};
- var endMark = function (label, markName, warning) {
- var formattedMarkName = formatMarkName(markName);
- var formattedLabel = formatLabel(label, warning);
- try {
- performance.measure(formattedLabel, formattedMarkName);
- } catch (err) {}
- // If previous mark was missing for some reason, this will throw.
- // This could only happen if React crashed in an unexpected place earlier.
- // Don't pile on with more errors.
-
- // Clear marks immediately to avoid growing buffer.
- performance.clearMarks(formattedMarkName);
- performance.clearMeasures(formattedLabel);
- };
+function recordEffect() {
+ if (enableUserTimingAPI) {
+ effectCountInCurrentCommit++;
+ }
+}
- var getFiberMarkName = function (label, debugID) {
- return label + ' (#' + debugID + ')';
- };
+function recordScheduleUpdate() {
+ if (enableUserTimingAPI) {
+ if (isCommitting) {
+ hasScheduledUpdateInCurrentCommit = true;
+ }
+ if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') {
+ hasScheduledUpdateInCurrentPhase = true;
+ }
+ }
+}
- 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;
+function startRequestCallbackTimer() {
+ if (enableUserTimingAPI) {
+ if (supportsUserTiming && !isWaitingForCallback) {
+ isWaitingForCallback = true;
+ beginMark('(Waiting for async callback...)');
}
- };
+ }
+}
- var beginFiberMark = function (fiber, phase) {
- var componentName = getComponentName$5(fiber) || 'Unknown';
- var debugID = fiber._debugID;
- var isMounted = fiber.alternate !== null;
- var label = getFiberLabel(componentName, isMounted, phase);
+function stopRequestCallbackTimer(didExpire) {
+ if (enableUserTimingAPI) {
+ if (supportsUserTiming) {
+ isWaitingForCallback = false;
+ var warning = didExpire ? 'React was blocked by main thread' : null;
+ endMark('(Waiting for async callback...)', '(Waiting for async callback...)', warning);
+ }
+ }
+}
- 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;
+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;
}
- labelsInCurrentCommit.add(label);
+ fiber._debugIsCurrentlyTiming = true;
+ }
+}
- var markName = getFiberMarkName(label, debugID);
- beginMark(markName);
- return 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);
+ }
+}
- var clearFiberMark = function (fiber, phase) {
- var componentName = getComponentName$5(fiber) || 'Unknown';
- var debugID = fiber._debugID;
- var isMounted = fiber.alternate !== null;
- var label = getFiberLabel(componentName, isMounted, phase);
- var markName = getFiberMarkName(label, debugID);
- clearMark(markName);
- };
+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);
+ }
+}
- var endFiberMark = function (fiber, phase, warning) {
- var componentName = getComponentName$5(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);
- };
+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 = 'An error was thrown inside this error boundary';
+ endFiberMark(fiber, null, warning);
+ }
+}
- var shouldIgnoreFiber = function (fiber) {
- // Host components should be skipped in the timeline.
- // We could check typeof fiber.type, but does this work with RN?
- switch (fiber.tag) {
- case HostRoot$4:
- case HostComponent$4:
- case HostText$2:
- case HostPortal$1:
- case YieldComponent:
- case Fragment:
- return true;
- default:
- return false;
+function startPhaseTimer(fiber, phase) {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
}
- };
+ clearPendingPhaseMeasurement();
+ if (!beginFiberMark(fiber, phase)) {
+ return;
+ }
+ currentPhaseFiber = fiber;
+ currentPhase = phase;
+ }
+}
- var clearPendingPhaseMeasurement = function () {
+function stopPhaseTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
if (currentPhase !== null && currentPhaseFiber !== null) {
- clearFiberMark(currentPhaseFiber, currentPhase);
+ var warning = hasScheduledUpdateInCurrentPhase ? 'Scheduled a cascading update' : null;
+ endFiberMark(currentPhaseFiber, currentPhase, warning);
}
- currentPhaseFiber = null;
currentPhase = null;
- hasScheduledUpdateInCurrentPhase = false;
- };
+ currentPhaseFiber = null;
+ }
+}
- 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'];
+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();
+ }
+}
- var resumeTimersRecursively = function (fiber) {
- if (fiber['return'] !== null) {
- resumeTimersRecursively(fiber['return']);
+function stopWorkLoopTimer(interruptedBy) {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
}
- if (fiber._debugIsCurrentlyTiming) {
- beginFiberMark(fiber, null);
+ var warning = null;
+ if (interruptedBy !== null) {
+ if (interruptedBy.tag === HostRoot) {
+ warning = 'A top-level update interrupted the previous render';
+ } else {
+ var componentName = getComponentName(interruptedBy) || 'Unknown';
+ warning = 'An update to ' + componentName + ' interrupted the previous render';
+ }
+ } else if (commitCountInCurrentWorkLoop > 1) {
+ warning = 'There were cascading updates';
}
- };
+ commitCountInCurrentWorkLoop = 0;
+ // Pause any measurements until the next loop.
+ pauseTimers();
+ endMark('(React Tree Reconciliation)', '(React Tree Reconciliation)', warning);
+ }
+}
- var resumeTimers = function () {
- // Resumes all measurements that were active during the last deferred loop.
- if (currentFiber !== null) {
- resumeTimersRecursively(currentFiber);
+function startCommitTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
}
- };
-
- ReactDebugFiberPerf = {
- recordEffect: function () {
- effectCountInCurrentCommit++;
- },
- recordScheduleUpdate: function () {
- if (isCommitting) {
- hasScheduledUpdateInCurrentCommit = true;
- }
- if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') {
- hasScheduledUpdateInCurrentPhase = true;
- }
- },
- startWorkTimer: function (fiber) {
- if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
- return;
- }
- // If we pause, this is the fiber to unwind from.
- currentFiber = fiber;
- if (!beginFiberMark(fiber, null)) {
- return;
- }
- fiber._debugIsCurrentlyTiming = true;
- },
- cancelWorkTimer: function (fiber) {
- if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
- return;
- }
- // Remember we shouldn't complete measurement for this fiber.
- // Otherwise flamechart will be deep even for small updates.
- fiber._debugIsCurrentlyTiming = false;
- clearFiberMark(fiber, null);
- },
- stopWorkTimer: function (fiber) {
- if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
- return;
- }
- // If we pause, its parent is the fiber to unwind from.
- currentFiber = fiber['return'];
- if (!fiber._debugIsCurrentlyTiming) {
- return;
- }
- fiber._debugIsCurrentlyTiming = false;
- endFiberMark(fiber, null, null);
- },
- stopFailedWorkTimer: function (fiber) {
- if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
- return;
- }
- // If we pause, its parent is the fiber to unwind from.
- currentFiber = fiber['return'];
- if (!fiber._debugIsCurrentlyTiming) {
- return;
- }
- fiber._debugIsCurrentlyTiming = false;
- var warning = 'An error was thrown inside this error boundary';
- endFiberMark(fiber, null, warning);
- },
- startPhaseTimer: function (fiber, phase) {
- if (!supportsUserTiming) {
- return;
- }
- clearPendingPhaseMeasurement();
- if (!beginFiberMark(fiber, phase)) {
- return;
- }
- currentPhaseFiber = fiber;
- currentPhase = phase;
- },
- stopPhaseTimer: function () {
- if (!supportsUserTiming) {
- return;
- }
- if (currentPhase !== null && currentPhaseFiber !== null) {
- var warning = hasScheduledUpdateInCurrentPhase ? 'Scheduled a cascading update' : null;
- endFiberMark(currentPhaseFiber, currentPhase, warning);
- }
- currentPhase = null;
- currentPhaseFiber = null;
- },
- startWorkLoopTimer: function () {
- 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();
- },
- stopWorkLoopTimer: function () {
- if (!supportsUserTiming) {
- return;
- }
- var warning = commitCountInCurrentWorkLoop > 1 ? 'There were cascading updates' : null;
- commitCountInCurrentWorkLoop = 0;
- // Pause any measurements until the next loop.
- pauseTimers();
- endMark('(React Tree Reconciliation)', '(React Tree Reconciliation)', warning);
- },
- startCommitTimer: function () {
- if (!supportsUserTiming) {
- return;
- }
- isCommitting = true;
- hasScheduledUpdateInCurrentCommit = false;
- labelsInCurrentCommit.clear();
- beginMark('(Committing Changes)');
- },
- stopCommitTimer: function () {
- if (!supportsUserTiming) {
- return;
- }
+ isCommitting = true;
+ hasScheduledUpdateInCurrentCommit = false;
+ labelsInCurrentCommit.clear();
+ beginMark('(Committing Changes)');
+ }
+}
- var warning = null;
- if (hasScheduledUpdateInCurrentCommit) {
- warning = 'Lifecycle hook scheduled a cascading update';
- } else if (commitCountInCurrentWorkLoop > 0) {
- warning = 'Caused by a cascading update in earlier commit';
- }
- hasScheduledUpdateInCurrentCommit = false;
- commitCountInCurrentWorkLoop++;
- isCommitting = false;
- labelsInCurrentCommit.clear();
+function stopCommitTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
- endMark('(Committing Changes)', '(Committing Changes)', warning);
- },
- startCommitHostEffectsTimer: function () {
- if (!supportsUserTiming) {
- return;
- }
- effectCountInCurrentCommit = 0;
- beginMark('(Committing Host Effects)');
- },
- stopCommitHostEffectsTimer: function () {
- if (!supportsUserTiming) {
- return;
- }
- var count = effectCountInCurrentCommit;
- effectCountInCurrentCommit = 0;
- endMark('(Committing Host Effects: ' + count + ' Total)', '(Committing Host Effects)', null);
- },
- startCommitLifeCyclesTimer: function () {
- if (!supportsUserTiming) {
- return;
- }
- effectCountInCurrentCommit = 0;
- beginMark('(Calling Lifecycle Methods)');
- },
- stopCommitLifeCyclesTimer: function () {
- if (!supportsUserTiming) {
- return;
- }
- var count = effectCountInCurrentCommit;
- effectCountInCurrentCommit = 0;
- endMark('(Calling Lifecycle Methods: ' + count + ' Total)', '(Calling Lifecycle Methods)', null);
+ var warning = null;
+ if (hasScheduledUpdateInCurrentCommit) {
+ warning = 'Lifecycle hook scheduled a cascading update';
+ } else if (commitCountInCurrentWorkLoop > 0) {
+ warning = 'Caused by a cascading update in earlier commit';
}
- };
+ hasScheduledUpdateInCurrentCommit = false;
+ commitCountInCurrentWorkLoop++;
+ isCommitting = false;
+ labelsInCurrentCommit.clear();
+
+ endMark('(Committing Changes)', '(Committing Changes)', warning);
+ }
}
-var ReactDebugFiberPerf_1 = ReactDebugFiberPerf;
+function startCommitHostEffectsTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ effectCountInCurrentCommit = 0;
+ beginMark('(Committing Host Effects)');
+ }
+}
-var isFiberMounted$1 = ReactFiberTreeReflection.isFiberMounted;
+function stopCommitHostEffectsTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ var count = effectCountInCurrentCommit;
+ effectCountInCurrentCommit = 0;
+ endMark('(Committing Host Effects: ' + count + ' Total)', '(Committing Host Effects)', null);
+ }
+}
-var ClassComponent$3 = ReactTypeOfWork.ClassComponent;
-var HostRoot$3 = ReactTypeOfWork.HostRoot;
+function startCommitLifeCyclesTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ effectCountInCurrentCommit = 0;
+ beginMark('(Calling Lifecycle Methods)');
+ }
+}
-var createCursor = ReactFiberStack.createCursor;
-var pop = ReactFiberStack.pop;
-var push = ReactFiberStack.push;
+function stopCommitLifeCyclesTimer() {
+ if (enableUserTimingAPI) {
+ if (!supportsUserTiming) {
+ return;
+ }
+ var count = effectCountInCurrentCommit;
+ effectCountInCurrentCommit = 0;
+ endMark('(Calling Lifecycle Methods: ' + count + ' Total)', '(Calling Lifecycle Methods)', null);
+ }
+}
{
- var warning$22 = warning_1;
- var checkPropTypes$1 = checkPropTypes_1;
- var ReactDebugCurrentFiber$2 = ReactDebugCurrentFiber_1;
-
- var _require4 = ReactDebugFiberPerf_1,
- startPhaseTimer = _require4.startPhaseTimer,
- stopPhaseTimer = _require4.stopPhaseTimer;
-
var warnedAboutMissingGetChildContext = {};
}
@@ -8729,7 +5888,7 @@ var didPerformWorkStackCursor = createCursor(false);
var previousContext = emptyObject_1;
function getUnmaskedContext(workInProgress) {
- var hasOwnContext = isContextProvider$1(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
@@ -8739,16 +5898,14 @@ function getUnmaskedContext(workInProgress) {
}
return contextStackCursor.current;
}
-var getUnmaskedContext_1 = getUnmaskedContext;
function cacheContext(workInProgress, unmaskedContext, maskedContext) {
var instance = workInProgress.stateNode;
instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
instance.__reactInternalMemoizedMaskedChildContext = maskedContext;
}
-var cacheContext_1 = cacheContext;
-var getMaskedContext = function (workInProgress, unmaskedContext) {
+function getMaskedContext(workInProgress, unmaskedContext) {
var type = workInProgress.type;
var contextTypes = type.contextTypes;
if (!contextTypes) {
@@ -8769,10 +5926,8 @@ var getMaskedContext = function (workInProgress, unmaskedContext) {
}
{
- var name = getComponentName_1(workInProgress) || 'Unknown';
- ReactDebugCurrentFiber$2.setCurrentFiber(workInProgress, null);
- checkPropTypes$1(contextTypes, context, 'context', name, ReactDebugCurrentFiber$2.getCurrentFiberStackAddendum);
- ReactDebugCurrentFiber$2.resetCurrentFiber();
+ var name = getComponentName(workInProgress) || 'Unknown';
+ checkPropTypes_1(contextTypes, context, 'context', name, ReactDebugCurrentFiber.getCurrentFiberStackAddendum);
}
// Cache unmasked context so we can avoid recreating masked context unless necessary.
@@ -8782,45 +5937,42 @@ var getMaskedContext = function (workInProgress, unmaskedContext) {
}
return context;
-};
+}
-var hasContextChanged = function () {
+function hasContextChanged() {
return didPerformWorkStackCursor.current;
-};
+}
function isContextConsumer(fiber) {
- return fiber.tag === ClassComponent$3 && fiber.type.contextTypes != null;
+ return fiber.tag === ClassComponent && fiber.type.contextTypes != null;
}
-var isContextConsumer_1 = isContextConsumer;
-function isContextProvider$1(fiber) {
- return fiber.tag === ClassComponent$3 && fiber.type.childContextTypes != null;
+function isContextProvider(fiber) {
+ return fiber.tag === ClassComponent && fiber.type.childContextTypes != null;
}
-var isContextProvider_1 = isContextProvider$1;
function popContextProvider(fiber) {
- if (!isContextProvider$1(fiber)) {
+ if (!isContextProvider(fiber)) {
return;
}
pop(didPerformWorkStackCursor, fiber);
pop(contextStackCursor, fiber);
}
-var popContextProvider_1 = popContextProvider;
-var popTopLevelContextObject = function (fiber) {
+function popTopLevelContextObject(fiber) {
pop(didPerformWorkStackCursor, fiber);
pop(contextStackCursor, fiber);
-};
+}
-var pushTopLevelContextObject = function (fiber, context, didChange) {
+function pushTopLevelContextObject(fiber, context, didChange) {
!(contextStackCursor.cursor == null) ? invariant_1(false, 'Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue.') : void 0;
push(contextStackCursor, context, fiber);
push(didPerformWorkStackCursor, didChange, fiber);
-};
+}
-function processChildContext$1(fiber, parentContext, isReconciling) {
+function processChildContext(fiber, parentContext) {
var instance = fiber.stateNode;
var childContextTypes = fiber.type.childContextTypes;
@@ -8828,11 +5980,11 @@ function processChildContext$1(fiber, parentContext, isReconciling) {
// It has only been added in Fiber to match the (unintentional) behavior in Stack.
if (typeof instance.getChildContext !== 'function') {
{
- var componentName = getComponentName_1(fiber) || 'Unknown';
+ var componentName = getComponentName(fiber) || 'Unknown';
if (!warnedAboutMissingGetChildContext[componentName]) {
warnedAboutMissingGetChildContext[componentName] = true;
- warning$22(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);
+ warning_1(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;
@@ -8840,34 +5992,33 @@ function processChildContext$1(fiber, parentContext, isReconciling) {
var childContext = void 0;
{
- ReactDebugCurrentFiber$2.setCurrentFiber(fiber, 'getChildContext');
- startPhaseTimer(fiber, 'getChildContext');
- childContext = instance.getChildContext();
- stopPhaseTimer();
- ReactDebugCurrentFiber$2.resetCurrentFiber();
+ ReactDebugCurrentFiber.setCurrentPhase('getChildContext');
+ }
+ startPhaseTimer(fiber, 'getChildContext');
+ childContext = instance.getChildContext();
+ stopPhaseTimer();
+ {
+ ReactDebugCurrentFiber.setCurrentPhase(null);
}
for (var contextKey in childContext) {
- !(contextKey in childContextTypes) ? invariant_1(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', getComponentName_1(fiber) || 'Unknown', contextKey) : void 0;
+ !(contextKey in childContextTypes) ? invariant_1(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', getComponentName(fiber) || 'Unknown', contextKey) : void 0;
}
{
- var name = getComponentName_1(fiber) || 'Unknown';
- // We can only provide accurate element stacks if we pass work-in-progress tree
- // during the begin or complete phase. However currently this function is also
- // called from unstable_renderSubtree legacy implementation. In this case it unsafe to
- // assume anything about the given fiber. We won't pass it down if we aren't sure.
- // TODO: remove this hack when we delete unstable_renderSubtree in Fiber.
- var workInProgress = isReconciling ? fiber : null;
- ReactDebugCurrentFiber$2.setCurrentFiber(workInProgress, null);
- checkPropTypes$1(childContextTypes, childContext, 'child context', name, ReactDebugCurrentFiber$2.getCurrentFiberStackAddendum);
- ReactDebugCurrentFiber$2.resetCurrentFiber();
+ var name = getComponentName(fiber) || 'Unknown';
+ checkPropTypes_1(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 assign({}, parentContext, childContext);
+ return _assign({}, parentContext, childContext);
}
-var processChildContext_1 = processChildContext$1;
-var pushContextProvider = function (workInProgress) {
- if (!isContextProvider$1(workInProgress)) {
+function pushContextProvider(workInProgress) {
+ if (!isContextProvider(workInProgress)) {
return false;
}
@@ -8878,15 +6029,15 @@ var pushContextProvider = function (workInProgress) {
var memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyObject_1;
// Remember the parent context so we can merge with it later.
- // Inherit the parent's did-perform-work value to avoid inadvertantly blocking updates.
+ // 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;
-};
+}
-var invalidateContextProvider = function (workInProgress, didChange) {
+function invalidateContextProvider(workInProgress, didChange) {
var instance = workInProgress.stateNode;
!instance ? invariant_1(false, 'Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue.') : void 0;
@@ -8894,7 +6045,7 @@ var invalidateContextProvider = function (workInProgress, 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$1(workInProgress, previousContext, true);
+ var mergedContext = processChildContext(workInProgress, previousContext);
instance.__reactInternalMemoizedMergedChildContext = mergedContext;
// Replace the old (or empty) context with the new one.
@@ -8908,22 +6059,22 @@ var invalidateContextProvider = function (workInProgress, didChange) {
pop(didPerformWorkStackCursor, workInProgress);
push(didPerformWorkStackCursor, didChange, workInProgress);
}
-};
+}
-var resetContext = function () {
+function resetContext() {
previousContext = emptyObject_1;
contextStackCursor.current = emptyObject_1;
didPerformWorkStackCursor.current = false;
-};
+}
-var findCurrentUnmaskedContext$1 = function (fiber) {
+function findCurrentUnmaskedContext(fiber) {
// Currently this is only used with renderSubtreeIntoContainer; not sure if it
// makes sense elsewhere
- !(isFiberMounted$1(fiber) && fiber.tag === ClassComponent$3) ? invariant_1(false, 'Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+ !(isFiberMounted(fiber) && fiber.tag === ClassComponent) ? invariant_1(false, 'Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.') : void 0;
var node = fiber;
- while (node.tag !== HostRoot$3) {
- if (isContextProvider$1(node)) {
+ while (node.tag !== HostRoot) {
+ if (isContextProvider(node)) {
return node.stateNode.__reactInternalMemoizedMergedChildContext;
}
var parent = node['return'];
@@ -8931,66 +6082,43 @@ var findCurrentUnmaskedContext$1 = function (fiber) {
node = parent;
}
return node.stateNode.context;
-};
-
-var ReactFiberContext = {
- getUnmaskedContext: getUnmaskedContext_1,
- cacheContext: cacheContext_1,
- getMaskedContext: getMaskedContext,
- hasContextChanged: hasContextChanged,
- isContextConsumer: isContextConsumer_1,
- isContextProvider: isContextProvider_1,
- popContextProvider: popContextProvider_1,
- popTopLevelContextObject: popTopLevelContextObject,
- pushTopLevelContextObject: pushTopLevelContextObject,
- processChildContext: processChildContext_1,
- pushContextProvider: pushContextProvider,
- invalidateContextProvider: invalidateContextProvider,
- resetContext: resetContext,
- findCurrentUnmaskedContext: findCurrentUnmaskedContext$1
-};
+}
-/**
- * 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.
- *
- * @providesModule ReactTypeOfInternalContext
- *
- */
+var NoWork = 0; // TODO: Use an opaque type once ESLint et al support the syntax
-var ReactTypeOfInternalContext = {
- NoContext: 0,
- AsyncUpdates: 1
-};
+var Sync = 1;
+var Never = 2147483647; // Max int32: Math.pow(2, 31) - 1
-var IndeterminateComponent$1 = ReactTypeOfWork.IndeterminateComponent;
-var ClassComponent$4 = ReactTypeOfWork.ClassComponent;
-var HostRoot$5 = ReactTypeOfWork.HostRoot;
-var HostComponent$5 = ReactTypeOfWork.HostComponent;
-var HostText$3 = ReactTypeOfWork.HostText;
-var HostPortal$2 = ReactTypeOfWork.HostPortal;
-var CoroutineComponent = ReactTypeOfWork.CoroutineComponent;
-var YieldComponent$1 = ReactTypeOfWork.YieldComponent;
-var Fragment$1 = ReactTypeOfWork.Fragment;
+var UNIT_SIZE = 10;
+var MAGIC_NUMBER_OFFSET = 2;
-var NoWork$1 = ReactPriorityLevel.NoWork;
+// 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;
+}
-var NoContext = ReactTypeOfInternalContext.NoContext;
+function expirationTimeToMs(expirationTime) {
+ return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
+}
-var NoEffect$1 = ReactTypeOfSideEffect.NoEffect;
+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 AsyncUpdates = 1;
{
- var getComponentName$6 = getComponentName_1;
var hasBadMapPolyfill = false;
try {
var nonExtensibleObject = Object.preventExtensions({});
/* eslint-disable no-new */
- new Map([[nonExtensibleObject, null]]);
- new Set([nonExtensibleObject]);
+
/* eslint-enable no-new */
} catch (e) {
// TODO: Consider warning about bad polyfills
@@ -9029,13 +6157,13 @@ function FiberNode(tag, key, internalContextTag) {
this.internalContextTag = internalContextTag;
// Effects
- this.effectTag = NoEffect$1;
+ this.effectTag = NoEffect;
this.nextEffect = null;
this.firstEffect = null;
this.lastEffect = null;
- this.pendingWorkPriority = NoWork$1;
+ this.expirationTime = NoWork;
this.alternate = null;
@@ -9073,7 +6201,7 @@ function shouldConstruct(Component) {
}
// This is used to create an alternate fiber to do work on.
-var createWorkInProgress = function (current, renderPriority) {
+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
@@ -9097,7 +6225,7 @@ var createWorkInProgress = function (current, renderPriority) {
} else {
// We already have an alternate.
// Reset the effect tag.
- workInProgress.effectTag = NoEffect$1;
+ workInProgress.effectTag = NoEffect;
// The effect list is no longer valid.
workInProgress.nextEffect = null;
@@ -9105,71 +6233,45 @@ var createWorkInProgress = function (current, renderPriority) {
workInProgress.lastEffect = null;
}
- workInProgress.pendingWorkPriority = renderPriority;
+ workInProgress.expirationTime = expirationTime;
+ workInProgress.pendingProps = pendingProps;
workInProgress.child = current.child;
workInProgress.memoizedProps = current.memoizedProps;
workInProgress.memoizedState = current.memoizedState;
workInProgress.updateQueue = current.updateQueue;
- // pendingProps is set by the parent during reconciliation.
- // TODO: Pass this as an argument.
-
// These will be overridden during the parent's reconciliation
workInProgress.sibling = current.sibling;
workInProgress.index = current.index;
workInProgress.ref = current.ref;
return workInProgress;
-};
+}
-var createHostRootFiber$1 = function () {
- var fiber = createFiber(HostRoot$5, null, NoContext);
+function createHostRootFiber() {
+ var fiber = createFiber(HostRoot, null, NoContext);
return fiber;
-};
+}
-var createFiberFromElement = function (element, internalContextTag, priorityLevel) {
+function createFiberFromElement(element, internalContextTag, expirationTime) {
var owner = null;
{
owner = element._owner;
}
- var fiber = createFiberFromElementType(element.type, element.key, internalContextTag, owner);
- fiber.pendingProps = element.props;
- fiber.pendingWorkPriority = priorityLevel;
-
- {
- fiber._debugSource = element._source;
- fiber._debugOwner = element._owner;
- }
-
- return fiber;
-};
-
-var createFiberFromFragment = function (elements, internalContextTag, priorityLevel) {
- // TODO: Consider supporting keyed fragments. Technically, we accidentally
- // support that in the existing React.
- var fiber = createFiber(Fragment$1, null, internalContextTag);
- fiber.pendingProps = elements;
- fiber.pendingWorkPriority = priorityLevel;
- return fiber;
-};
-
-var createFiberFromText = function (content, internalContextTag, priorityLevel) {
- var fiber = createFiber(HostText$3, null, internalContextTag);
- fiber.pendingProps = content;
- fiber.pendingWorkPriority = priorityLevel;
- return fiber;
-};
-
-function createFiberFromElementType(type, key, internalContextTag, debugOwner) {
var fiber = void 0;
+ var type = element.type,
+ key = element.key;
+
if (typeof type === 'function') {
- fiber = shouldConstruct(type) ? createFiber(ClassComponent$4, key, internalContextTag) : createFiber(IndeterminateComponent$1, key, internalContextTag);
+ fiber = shouldConstruct(type) ? createFiber(ClassComponent, key, internalContextTag) : createFiber(IndeterminateComponent, key, internalContextTag);
fiber.type = type;
+ fiber.pendingProps = element.props;
} else if (typeof type === 'string') {
- fiber = createFiber(HostComponent$5, key, internalContextTag);
+ fiber = createFiber(HostComponent, key, internalContextTag);
fiber.type = type;
+ fiber.pendingProps = element.props;
} else if (typeof type === 'object' && type !== null && 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.
@@ -9178,309 +6280,941 @@ function createFiberFromElementType(type, key, internalContextTag, debugOwner) {
// 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 = element.props;
} else {
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.";
+ 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 = debugOwner ? getComponentName$6(debugOwner) : null;
+ var ownerName = owner ? getComponentName(owner) : null;
if (ownerName) {
info += '\n\nCheck the render method of `' + ownerName + '`.';
}
}
invariant_1(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);
}
+
+ {
+ fiber._debugSource = element._source;
+ fiber._debugOwner = element._owner;
+ }
+
+ fiber.expirationTime = expirationTime;
+
return fiber;
}
-var createFiberFromElementType_1 = createFiberFromElementType;
+function createFiberFromFragment(elements, internalContextTag, expirationTime, key) {
+ var fiber = createFiber(Fragment, key, internalContextTag);
+ fiber.pendingProps = elements;
+ fiber.expirationTime = expirationTime;
+ return fiber;
+}
+
+function createFiberFromText(content, internalContextTag, expirationTime) {
+ var fiber = createFiber(HostText, null, internalContextTag);
+ fiber.pendingProps = content;
+ fiber.expirationTime = expirationTime;
+ return fiber;
+}
-var createFiberFromHostInstanceForDeletion = function () {
- var fiber = createFiber(HostComponent$5, null, NoContext);
+function createFiberFromHostInstanceForDeletion() {
+ var fiber = createFiber(HostComponent, null, NoContext);
fiber.type = 'DELETED';
return fiber;
-};
+}
-var createFiberFromCoroutine = function (coroutine, internalContextTag, priorityLevel) {
- var fiber = createFiber(CoroutineComponent, coroutine.key, internalContextTag);
- fiber.type = coroutine.handler;
- fiber.pendingProps = coroutine;
- fiber.pendingWorkPriority = priorityLevel;
+function createFiberFromCall(call, internalContextTag, expirationTime) {
+ var fiber = createFiber(CallComponent, call.key, internalContextTag);
+ fiber.type = call.handler;
+ fiber.pendingProps = call;
+ fiber.expirationTime = expirationTime;
return fiber;
-};
+}
-var createFiberFromYield = function (yieldNode, internalContextTag, priorityLevel) {
- var fiber = createFiber(YieldComponent$1, null, internalContextTag);
+function createFiberFromReturn(returnNode, internalContextTag, expirationTime) {
+ var fiber = createFiber(ReturnComponent, null, internalContextTag);
+ fiber.expirationTime = expirationTime;
return fiber;
-};
+}
-var createFiberFromPortal = function (portal, internalContextTag, priorityLevel) {
- var fiber = createFiber(HostPortal$2, portal.key, internalContextTag);
+function createFiberFromPortal(portal, internalContextTag, expirationTime) {
+ var fiber = createFiber(HostPortal, portal.key, internalContextTag);
fiber.pendingProps = portal.children || [];
- fiber.pendingWorkPriority = priorityLevel;
+ fiber.expirationTime = expirationTime;
fiber.stateNode = {
containerInfo: portal.containerInfo,
+ pendingChildren: null, // Used by persistent updates
implementation: portal.implementation
};
return fiber;
-};
-
-var largerPriority = function (p1, p2) {
- return p1 !== NoWork$1 && (p2 === NoWork$1 || p2 > p1) ? p1 : p2;
-};
-
-var ReactFiber = {
- createWorkInProgress: createWorkInProgress,
- createHostRootFiber: createHostRootFiber$1,
- createFiberFromElement: createFiberFromElement,
- createFiberFromFragment: createFiberFromFragment,
- createFiberFromText: createFiberFromText,
- createFiberFromElementType: createFiberFromElementType_1,
- createFiberFromHostInstanceForDeletion: createFiberFromHostInstanceForDeletion,
- createFiberFromCoroutine: createFiberFromCoroutine,
- createFiberFromYield: createFiberFromYield,
- createFiberFromPortal: createFiberFromPortal,
- largerPriority: largerPriority
-};
-
-var createHostRootFiber = ReactFiber.createHostRootFiber;
+}
-var createFiberRoot$1 = function (containerInfo) {
+function createFiberRoot(containerInfo, hydrate) {
// Cyclic construction. This cheats the type system right now because
// stateNode is any.
var uninitializedFiber = createHostRootFiber();
var root = {
current: uninitializedFiber,
containerInfo: containerInfo,
- isScheduled: false,
- nextScheduledRoot: null,
+ pendingChildren: null,
+ remainingExpirationTime: NoWork,
+ isReadyForCommit: false,
+ finishedWork: null,
context: null,
- pendingContext: null
+ pendingContext: null,
+ hydrate: hydrate,
+ nextScheduledRoot: null
};
uninitializedFiber.stateNode = root;
return root;
-};
+}
-var ReactFiberRoot = {
- createFiberRoot: createFiberRoot$1
-};
+var onCommitFiberRoot = null;
+var onCommitFiberUnmount = null;
+var hasLoggedError = false;
-var defaultShowDialog = function (capturedError) {
+function catchErrors(fn) {
+ return function (arg) {
+ try {
+ return fn(arg);
+ } catch (err) {
+ if (true && !hasLoggedError) {
+ hasLoggedError = true;
+ warning_1(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_1(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_1(false, 'React DevTools encountered an error: %s.', err);
+ }
+ }
+ // DevTools exists
return true;
-};
+}
-var showDialog = defaultShowDialog;
+function onCommitRoot(root) {
+ if (typeof onCommitFiberRoot === 'function') {
+ onCommitFiberRoot(root);
+ }
+}
-function logCapturedError$1(capturedError) {
- var logError = showDialog(capturedError);
+function onCommitUnmount(fiber) {
+ if (typeof onCommitFiberUnmount === 'function') {
+ onCommitFiberUnmount(fiber);
+ }
+}
- // Allow injected showDialog() to prevent default console.error logging.
- // This enables renderers like ReactNative to better manage redbox behavior.
- if (logError === false) {
+{
+ var 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_1(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;
}
- var error = capturedError.error;
+ // 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') {
+ var updateFn = partialState;
+
+ // Invoke setState callback an extra time to help detect side-effects.
+ if (debugRenderPhaseSideEffects) {
+ updateFn.call(instance, prevState, props);
+ }
+
+ return updateFn.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
+ };
+ }
+
{
- var componentName = capturedError.componentName,
- componentStack = capturedError.componentStack,
- errorBoundaryName = capturedError.errorBoundaryName,
- errorBoundaryFound = capturedError.errorBoundaryFound,
- willRetry = capturedError.willRetry;
+ // 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;
- var componentNameMessage = componentName ? 'The above error occurred in the <' + componentName + '> component:' : 'The above error occurred in one of your React components:';
+ // 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;
+ }
- 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.';
+ // 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;
}
+ }
+
+ // Process the update
+ var _partialState = void 0;
+ if (update.isReplace) {
+ state = getStateFromUpdate(update, instance, state, props);
+ dontMutatePrevState = true;
} else {
- errorBoundaryMessage = 'Consider adding an error boundary to your tree to customize error handling behavior.\n' + 'You can learn more about error boundaries at https://fb.me/react-error-boundaries.';
+ _partialState = getStateFromUpdate(update, instance, state, props);
+ if (_partialState) {
+ if (dontMutatePrevState) {
+ // $FlowFixMe: Idk how to type this properly.
+ state = _assign({}, state, _partialState);
+ } else {
+ state = _assign(state, _partialState);
+ }
+ dontMutatePrevState = false;
+ }
}
- var combinedMessage = '' + componentNameMessage + componentStack + '\n\n' + ('' + errorBoundaryMessage);
+ 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;
+ }
- // 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);
+ 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;
}
-var injection$1 = {
- /**
- * Display custom dialog for lifecycle errors.
- * Return false to prevent default behavior of logging to console.error.
- */
- injectDialog: function (fn) {
- !(showDialog === defaultShowDialog) ? invariant_1(false, 'The custom dialog was already injected.') : void 0;
- !(typeof fn === 'function') ? invariant_1(false, 'Injected showDialog() must be a function.') : void 0;
- showDialog = fn;
+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;
+ !(typeof _callback === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback) : void 0;
+ _callback.call(context);
+ }
+}
-var logCapturedError_1 = logCapturedError$1;
+var fakeInternalInstance = {};
+var isArray = Array.isArray;
-var ReactFiberErrorLogger = {
- injection: injection$1,
- logCapturedError: logCapturedError_1
-};
+{
+ var didWarnAboutStateAssignmentForComponent = {};
-/**
- * Copyright (c) 2014-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.
- *
- * @providesModule ReactCoroutine
- *
- */
+ var warnOnInvalidCallback = function (callback, callerName) {
+ warning_1(callback === null || typeof callback === 'function', '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
+ };
-// The Symbol used to tag the special React types. If there is no native Symbol
-// nor polyfill, then a plain number is used for performance.
-var REACT_COROUTINE_TYPE$1;
-var REACT_YIELD_TYPE$1;
-if (typeof Symbol === 'function' && Symbol['for']) {
- REACT_COROUTINE_TYPE$1 = Symbol['for']('react.coroutine');
- REACT_YIELD_TYPE$1 = Symbol['for']('react.yield');
-} else {
- REACT_COROUTINE_TYPE$1 = 0xeac8;
- REACT_YIELD_TYPE$1 = 0xeac9;
+ // 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_1(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 createCoroutine = function (children, handler, props) {
- var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
-
- var coroutine = {
- // This tag allow us to uniquely identify this as a React Coroutine
- $$typeof: REACT_COROUTINE_TYPE$1,
- key: key == null ? null : '' + key,
- children: children,
- handler: handler,
- props: props
+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);
+ }
};
- {
- // TODO: Add _store property for marking this as validated.
- if (Object.freeze) {
- Object.freeze(coroutine.props);
- Object.freeze(coroutine);
+ 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();
+
+ // Simulate an async bailout/interruption by invoking lifecycle twice.
+ if (debugRenderPhaseSideEffects) {
+ instance.shouldComponentUpdate(newProps, newState, newContext);
+ }
+
+ {
+ warning_1(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_1(oldProps, newProps) || !shallowEqual_1(oldState, newState);
}
+
+ return true;
}
- return coroutine;
-};
+ function checkClassInstance(workInProgress) {
+ var instance = workInProgress.stateNode;
+ var type = workInProgress.type;
+ {
+ var name = getComponentName(workInProgress);
+ var renderPresent = instance.render;
-var createYield = function (value) {
- var yieldNode = {
- // This tag allow us to uniquely identify this as a React Yield
- $$typeof: REACT_YIELD_TYPE$1,
- value: value
- };
+ if (!renderPresent) {
+ if (type.prototype && typeof type.prototype.render === 'function') {
+ warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name);
+ } else {
+ warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name);
+ }
+ }
- {
- // TODO: Add _store property for marking this as validated.
- if (Object.freeze) {
- Object.freeze(yieldNode);
+ var noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state;
+ warning_1(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_1(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_1(noInstancePropTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name);
+ var noInstanceContextTypes = !instance.contextTypes;
+ warning_1(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_1(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_1(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_1(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_1(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_1(noComponentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name);
+ var hasMutatedProps = instance.props !== workInProgress.pendingProps;
+ warning_1(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_1(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_1(false, '%s.state: must be set to an object or null', getComponentName(workInProgress));
+ }
+ if (typeof instance.getChildContext === 'function') {
+ warning_1(typeof workInProgress.type.childContextTypes === 'object', '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', getComponentName(workInProgress));
}
}
- return yieldNode;
-};
+ function resetInputPointers(workInProgress, instance) {
+ instance.props = workInProgress.memoizedProps;
+ instance.state = workInProgress.memoizedState;
+ }
-/**
- * Verifies the object is a coroutine object.
- */
-var isCoroutine = function (object) {
- return typeof object === 'object' && object !== null && object.$$typeof === REACT_COROUTINE_TYPE$1;
-};
+ 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;
+ }
+ }
-/**
- * Verifies the object is a yield object.
- */
-var isYield = function (object) {
- return typeof object === 'object' && object !== null && object.$$typeof === REACT_YIELD_TYPE$1;
-};
+ function constructClassInstance(workInProgress, props) {
+ var ctor = workInProgress.type;
+ var unmaskedContext = getUnmaskedContext(workInProgress);
+ var needsContext = isContextConsumer(workInProgress);
+ var context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject_1;
+ var instance = new ctor(props, context);
+ adoptClassInstance(workInProgress, instance);
-var REACT_YIELD_TYPE_1 = REACT_YIELD_TYPE$1;
-var REACT_COROUTINE_TYPE_1 = REACT_COROUTINE_TYPE$1;
+ // 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);
+ }
-var ReactCoroutine = {
- createCoroutine: createCoroutine,
- createYield: createYield,
- isCoroutine: isCoroutine,
- isYield: isYield,
- REACT_YIELD_TYPE: REACT_YIELD_TYPE_1,
- REACT_COROUTINE_TYPE: REACT_COROUTINE_TYPE_1
-};
+ return instance;
+ }
-/**
- * Copyright (c) 2014-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.
- *
- * @providesModule ReactPortal
- *
- */
+ function callComponentWillMount(workInProgress, instance) {
+ startPhaseTimer(workInProgress, 'componentWillMount');
+ var oldState = instance.state;
+ instance.componentWillMount();
+ stopPhaseTimer();
-// The Symbol used to tag the special React types. If there is no native Symbol
-// nor polyfill, then a plain number is used for performance.
-var REACT_PORTAL_TYPE$1 = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.portal') || 0xeaca;
+ // Simulate an async bailout/interruption by invoking lifecycle twice.
+ if (debugRenderPhaseSideEffects) {
+ instance.componentWillMount();
+ }
-var createPortal$1 = function (children, containerInfo,
-// TODO: figure out the API for cross-renderer implementation.
-implementation) {
- var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
+ if (oldState !== instance.state) {
+ {
+ warning_1(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);
+ }
+ }
- return {
- // This tag allow us to uniquely identify this as a React Portal
- $$typeof: REACT_PORTAL_TYPE$1,
- key: key == null ? null : '' + key,
- children: children,
- containerInfo: containerInfo,
- implementation: implementation
- };
-};
+ function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) {
+ startPhaseTimer(workInProgress, 'componentWillReceiveProps');
+ var oldState = instance.state;
+ instance.componentWillReceiveProps(newProps, newContext);
+ stopPhaseTimer();
-/**
- * Verifies the object is a portal object.
- */
-var isPortal = function (object) {
- return typeof object === 'object' && object !== null && object.$$typeof === REACT_PORTAL_TYPE$1;
-};
+ // Simulate an async bailout/interruption by invoking lifecycle twice.
+ if (debugRenderPhaseSideEffects) {
+ instance.componentWillReceiveProps(newProps, newContext);
+ }
+
+ if (instance.state !== oldState) {
+ {
+ var componentName = getComponentName(workInProgress) || 'Component';
+ if (!didWarnAboutStateAssignmentForComponent[componentName]) {
+ warning_1(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);
+ }
+ }
-var REACT_PORTAL_TYPE_1 = REACT_PORTAL_TYPE$1;
+ // Invokes the mount life-cycles on a previously never rendered instance.
+ function mountClassInstance(workInProgress, renderExpirationTime) {
+ var current = workInProgress.alternate;
-var ReactPortal = {
- createPortal: createPortal$1,
- isPortal: isPortal,
- REACT_PORTAL_TYPE: REACT_PORTAL_TYPE_1
-};
+ {
+ checkClassInstance(workInProgress);
+ }
+
+ var instance = workInProgress.stateNode;
+ var state = instance.state || null;
+
+ var props = workInProgress.pendingProps;
+ !props ? invariant_1(false, 'There must be pending props for an initial mount. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+
+ var unmaskedContext = getUnmaskedContext(workInProgress);
+
+ instance.props = props;
+ instance.state = workInProgress.memoizedState = state;
+ instance.refs = emptyObject_1;
+ instance.context = getMaskedContext(workInProgress, unmaskedContext);
+
+ if (enableAsyncSubtreeAPI && workInProgress.type != null && workInProgress.type.prototype != null && workInProgress.type.prototype.unstable_isAsyncReactComponent === true) {
+ workInProgress.internalContextTag |= AsyncUpdates;
+ }
+
+ if (typeof instance.componentWillMount === '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;
+ // }
-var REACT_COROUTINE_TYPE = ReactCoroutine.REACT_COROUTINE_TYPE;
-var REACT_YIELD_TYPE = ReactCoroutine.REACT_YIELD_TYPE;
+ // // Update the input pointers now so that they are correct when we call
+ // // componentWillMount
+ // instance.props = newProps;
+ // instance.state = newState;
+ // instance.context = newContext;
-var REACT_PORTAL_TYPE = ReactPortal.REACT_PORTAL_TYPE;
+ // 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;
+ if (!newProps) {
+ // If there aren't any new props, then we'll reuse the memoized props.
+ // This could be from already completed work.
+ newProps = oldProps;
+ !(newProps != null) ? invariant_1(false, 'There should always be pending or memoized props. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+ }
+ 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.
+ if (typeof instance.componentWillReceiveProps === 'function' && (oldProps !== newProps || oldContext !== newContext)) {
+ callComponentWillReceiveProps(workInProgress, instance, newProps, newContext);
+ }
-{
- var _require3$4 = ReactDebugCurrentFiber_1,
- getCurrentFiberStackAddendum$5 = _require3$4.getCurrentFiberStackAddendum;
+ // 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 (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) {
+ if (typeof instance.componentWillUpdate === 'function') {
+ startPhaseTimer(workInProgress, 'componentWillUpdate');
+ instance.componentWillUpdate(newProps, newState, newContext);
+ stopPhaseTimer();
+
+ // Simulate an async bailout/interruption by invoking lifecycle twice.
+ if (debugRenderPhaseSideEffects) {
+ instance.componentWillUpdate(newProps, newState, newContext);
+ }
+ }
+ 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;
+ }
- var warning$26 = warning_1;
+ return {
+ adoptClassInstance: adoptClassInstance,
+ constructClassInstance: constructClassInstance,
+ mountClassInstance: mountClassInstance,
+ // resumeMountClassInstance,
+ updateClassInstance: updateClassInstance
+ };
+};
+
+// 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 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;
+}
+
+var getCurrentFiberStackAddendum$1 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
+
+
+{
var didWarnAboutMaps = false;
/**
* Warn if there's no key explicitly set on dynamic arrays of children or
@@ -9488,6 +7222,7 @@ var REACT_PORTAL_TYPE = ReactPortal.REACT_PORTAL_TYPE;
* updates.
*/
var ownerHasKeyUseWarning = {};
+ var ownerHasFunctionTypeWarning = {};
var warnForMissingKey = function (child) {
if (child === null || typeof child !== 'object') {
@@ -9499,55 +7234,17 @@ var REACT_PORTAL_TYPE = ReactPortal.REACT_PORTAL_TYPE;
!(typeof child._store === 'object') ? invariant_1(false, 'React Component in warnForMissingKey should have a _store. This error is likely caused by a bug in React. Please file an issue.') : void 0;
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$5() || '');
+ 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$26(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$5());
+ warning_1(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 createWorkInProgress$2 = ReactFiber.createWorkInProgress;
-var createFiberFromElement$1 = ReactFiber.createFiberFromElement;
-var createFiberFromFragment$1 = ReactFiber.createFiberFromFragment;
-var createFiberFromText$1 = ReactFiber.createFiberFromText;
-var createFiberFromCoroutine$1 = ReactFiber.createFiberFromCoroutine;
-var createFiberFromYield$1 = ReactFiber.createFiberFromYield;
-var createFiberFromPortal$1 = ReactFiber.createFiberFromPortal;
-
-
-var isArray = Array.isArray;
-
-var FunctionalComponent$2 = ReactTypeOfWork.FunctionalComponent;
-var ClassComponent$7 = ReactTypeOfWork.ClassComponent;
-var HostText$5 = ReactTypeOfWork.HostText;
-var HostPortal$5 = ReactTypeOfWork.HostPortal;
-var CoroutineComponent$2 = ReactTypeOfWork.CoroutineComponent;
-var YieldComponent$3 = ReactTypeOfWork.YieldComponent;
-var Fragment$3 = ReactTypeOfWork.Fragment;
-var NoEffect$2 = ReactTypeOfSideEffect.NoEffect;
-var Placement$3 = ReactTypeOfSideEffect.Placement;
-var Deletion$1 = ReactTypeOfSideEffect.Deletion;
-
-
-var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
-var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
-// The Symbol used to tag the ReactElement type. If there is no native Symbol
-// nor polyfill, then a plain number is used for performance.
-var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;
-
-function getIteratorFn(maybeIterable) {
- if (maybeIterable === null || typeof maybeIterable === 'undefined') {
- return null;
- }
- var iteratorFn = ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
- if (typeof iteratorFn === 'function') {
- return iteratorFn;
- }
- return null;
-}
+var isArray$1 = Array.isArray;
function coerceRef(current, element) {
var mixedRef = element.ref;
@@ -9556,14 +7253,9 @@ function coerceRef(current, element) {
var owner = element._owner;
var inst = void 0;
if (owner) {
- if (typeof owner.tag === 'number') {
- var ownerFiber = owner;
- !(ownerFiber.tag === ClassComponent$7) ? invariant_1(false, 'Stateless function components cannot have refs.') : void 0;
- inst = ownerFiber.stateNode;
- } else {
- // Stack
- inst = owner.getPublicInstance();
- }
+ var ownerFiber = owner;
+ !(ownerFiber.tag === ClassComponent) ? invariant_1(false, 'Stateless function components cannot have refs.') : void 0;
+ inst = ownerFiber.stateNode;
}
!inst ? invariant_1(false, 'Missing owner for string ref %s. This error is likely caused by a bug in React. Please file an issue.', mixedRef) : void 0;
var stringRef = '' + mixedRef;
@@ -9593,35 +7285,33 @@ 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$5() || '');
+ addendum = ' If you meant to render a collection of children, use an array ' + 'instead.' + (getCurrentFiberStackAddendum$1() || '');
}
invariant_1(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() {
- warning$26(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$5() || '');
+ 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_1(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(shouldClone, shouldTrackSideEffects) {
+function ChildReconciler(shouldTrackSideEffects) {
function deleteChild(returnFiber, childToDelete) {
if (!shouldTrackSideEffects) {
// Noop.
return;
}
- if (!shouldClone) {
- // When we're reconciling in place we have a work in progress copy. We
- // actually want the current copy. If there is no current copy, then we
- // don't need to track deletion side-effects.
- if (childToDelete.alternate === null) {
- return;
- }
- childToDelete = childToDelete.alternate;
- }
// 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
@@ -9635,7 +7325,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
}
childToDelete.nextEffect = null;
- childToDelete.effectTag = Deletion$1;
+ childToDelete.effectTag = Deletion;
}
function deleteRemainingChildren(returnFiber, currentFirstChild) {
@@ -9671,24 +7361,13 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
return existingChildren;
}
- function useFiber(fiber, priority) {
+ 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.
- if (shouldClone) {
- var clone = createWorkInProgress$2(fiber, priority);
- clone.index = 0;
- clone.sibling = null;
- return clone;
- } else {
- // We override the pending priority even if it is higher, because if
- // we're reconciling at a lower priority that means that this was
- // down-prioritized.
- fiber.pendingWorkPriority = priority;
- fiber.effectTag = NoEffect$2;
- fiber.index = 0;
- fiber.sibling = null;
- return fiber;
- }
+ var clone = createWorkInProgress(fiber, pendingProps, expirationTime);
+ clone.index = 0;
+ clone.sibling = null;
+ return clone;
}
function placeChild(newFiber, lastPlacedIndex, newIndex) {
@@ -9702,7 +7381,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
var oldIndex = current.index;
if (oldIndex < lastPlacedIndex) {
// This is a move.
- newFiber.effectTag = Placement$3;
+ newFiber.effectTag = Placement;
return lastPlacedIndex;
} else {
// This item can stay in place.
@@ -9710,7 +7389,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
}
} else {
// This is an insertion.
- newFiber.effectTag = Placement$3;
+ newFiber.effectTag = Placement;
return lastPlacedIndex;
}
}
@@ -9719,115 +7398,110 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// 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$3;
+ newFiber.effectTag = Placement;
}
return newFiber;
}
- function updateTextNode(returnFiber, current, textContent, priority) {
- if (current === null || current.tag !== HostText$5) {
+ function updateTextNode(returnFiber, current, textContent, expirationTime) {
+ if (current === null || current.tag !== HostText) {
// Insert
- var created = createFiberFromText$1(textContent, returnFiber.internalContextTag, priority);
+ var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime);
created['return'] = returnFiber;
return created;
} else {
// Update
- var existing = useFiber(current, priority);
- existing.pendingProps = textContent;
+ var existing = useFiber(current, textContent, expirationTime);
existing['return'] = returnFiber;
return existing;
}
}
- function updateElement(returnFiber, current, element, priority) {
- if (current === null || current.type !== element.type) {
- // Insert
- var created = createFiberFromElement$1(element, returnFiber.internalContextTag, priority);
- created.ref = coerceRef(current, element);
- created['return'] = returnFiber;
- return created;
- } else {
+ function updateElement(returnFiber, current, element, expirationTime) {
+ if (current !== null && current.type === element.type) {
// Move based on index
- var existing = useFiber(current, priority);
+ var existing = useFiber(current, element.props, expirationTime);
existing.ref = coerceRef(current, element);
- existing.pendingProps = element.props;
existing['return'] = returnFiber;
{
existing._debugSource = element._source;
existing._debugOwner = element._owner;
}
return existing;
+ } else {
+ // Insert
+ var created = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime);
+ created.ref = coerceRef(current, element);
+ created['return'] = returnFiber;
+ return created;
}
}
- function updateCoroutine(returnFiber, current, coroutine, priority) {
+ function updateCall(returnFiber, current, call, expirationTime) {
// TODO: Should this also compare handler to determine whether to reuse?
- if (current === null || current.tag !== CoroutineComponent$2) {
+ if (current === null || current.tag !== CallComponent) {
// Insert
- var created = createFiberFromCoroutine$1(coroutine, returnFiber.internalContextTag, priority);
+ var created = createFiberFromCall(call, returnFiber.internalContextTag, expirationTime);
created['return'] = returnFiber;
return created;
} else {
// Move based on index
- var existing = useFiber(current, priority);
- existing.pendingProps = coroutine;
+ var existing = useFiber(current, call, expirationTime);
existing['return'] = returnFiber;
return existing;
}
}
- function updateYield(returnFiber, current, yieldNode, priority) {
- if (current === null || current.tag !== YieldComponent$3) {
+ function updateReturn(returnFiber, current, returnNode, expirationTime) {
+ if (current === null || current.tag !== ReturnComponent) {
// Insert
- var created = createFiberFromYield$1(yieldNode, returnFiber.internalContextTag, priority);
- created.type = yieldNode.value;
+ var created = createFiberFromReturn(returnNode, returnFiber.internalContextTag, expirationTime);
+ created.type = returnNode.value;
created['return'] = returnFiber;
return created;
} else {
// Move based on index
- var existing = useFiber(current, priority);
- existing.type = yieldNode.value;
+ var existing = useFiber(current, null, expirationTime);
+ existing.type = returnNode.value;
existing['return'] = returnFiber;
return existing;
}
}
- function updatePortal(returnFiber, current, portal, priority) {
- if (current === null || current.tag !== HostPortal$5 || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) {
+ 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$1(portal, returnFiber.internalContextTag, priority);
+ var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime);
created['return'] = returnFiber;
return created;
} else {
// Update
- var existing = useFiber(current, priority);
- existing.pendingProps = portal.children || [];
+ var existing = useFiber(current, portal.children || [], expirationTime);
existing['return'] = returnFiber;
return existing;
}
}
- function updateFragment(returnFiber, current, fragment, priority) {
- if (current === null || current.tag !== Fragment$3) {
+ function updateFragment(returnFiber, current, fragment, expirationTime, key) {
+ if (current === null || current.tag !== Fragment) {
// Insert
- var created = createFiberFromFragment$1(fragment, returnFiber.internalContextTag, priority);
+ var created = createFiberFromFragment(fragment, returnFiber.internalContextTag, expirationTime, key);
created['return'] = returnFiber;
return created;
} else {
// Update
- var existing = useFiber(current, priority);
- existing.pendingProps = fragment;
+ var existing = useFiber(current, fragment, expirationTime);
existing['return'] = returnFiber;
return existing;
}
}
- function createChild(returnFiber, newChild, priority) {
+ function createChild(returnFiber, newChild, expirationTime) {
if (typeof newChild === 'string' || typeof newChild === 'number') {
- // Text nodes doesn't have keys. If the previous node is implicitly keyed
+ // 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$1('' + newChild, returnFiber.internalContextTag, priority);
+ var created = createFiberFromText('' + newChild, returnFiber.internalContextTag, expirationTime);
created['return'] = returnFiber;
return created;
}
@@ -9836,39 +7510,45 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
switch (newChild.$$typeof) {
case REACT_ELEMENT_TYPE:
{
- var _created = createFiberFromElement$1(newChild, returnFiber.internalContextTag, priority);
- _created.ref = coerceRef(null, newChild);
- _created['return'] = returnFiber;
- return _created;
- }
-
- case REACT_COROUTINE_TYPE:
- {
- var _created2 = createFiberFromCoroutine$1(newChild, returnFiber.internalContextTag, priority);
- _created2['return'] = returnFiber;
- return _created2;
+ if (newChild.type === REACT_FRAGMENT_TYPE) {
+ var _created = createFiberFromFragment(newChild.props.children, returnFiber.internalContextTag, expirationTime, newChild.key);
+ _created['return'] = returnFiber;
+ return _created;
+ } else {
+ var _created2 = createFiberFromElement(newChild, returnFiber.internalContextTag, expirationTime);
+ _created2.ref = coerceRef(null, newChild);
+ _created2['return'] = returnFiber;
+ return _created2;
+ }
}
- case REACT_YIELD_TYPE:
+ case REACT_CALL_TYPE:
{
- var _created3 = createFiberFromYield$1(newChild, returnFiber.internalContextTag, priority);
- _created3.type = newChild.value;
+ var _created3 = createFiberFromCall(newChild, returnFiber.internalContextTag, expirationTime);
_created3['return'] = returnFiber;
return _created3;
}
- case REACT_PORTAL_TYPE:
+ case REACT_RETURN_TYPE:
{
- var _created4 = createFiberFromPortal$1(newChild, returnFiber.internalContextTag, priority);
+ var _created4 = createFiberFromReturn(newChild, returnFiber.internalContextTag, expirationTime);
+ _created4.type = newChild.value;
_created4['return'] = returnFiber;
return _created4;
}
+
+ case REACT_PORTAL_TYPE:
+ {
+ var _created5 = createFiberFromPortal(newChild, returnFiber.internalContextTag, expirationTime);
+ _created5['return'] = returnFiber;
+ return _created5;
+ }
}
- if (isArray(newChild) || getIteratorFn(newChild)) {
- var _created5 = createFiberFromFragment$1(newChild, returnFiber.internalContextTag, priority);
- _created5['return'] = returnFiber;
- return _created5;
+ if (isArray$1(newChild) || getIteratorFn(newChild)) {
+ var _created6 = createFiberFromFragment(newChild, returnFiber.internalContextTag, expirationTime, null);
+ _created6['return'] = returnFiber;
+ return _created6;
}
throwOnInvalidObjectType(returnFiber, newChild);
@@ -9883,19 +7563,19 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
return null;
}
- function updateSlot(returnFiber, oldFiber, newChild, priority) {
+ 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 doesn't have keys. If the previous node is implicitly keyed
+ // 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, priority);
+ return updateTextNode(returnFiber, oldFiber, '' + newChild, expirationTime);
}
if (typeof newChild === 'object' && newChild !== null) {
@@ -9903,28 +7583,31 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
case REACT_ELEMENT_TYPE:
{
if (newChild.key === key) {
- return updateElement(returnFiber, oldFiber, newChild, priority);
+ 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_COROUTINE_TYPE:
+ case REACT_CALL_TYPE:
{
if (newChild.key === key) {
- return updateCoroutine(returnFiber, oldFiber, newChild, priority);
+ return updateCall(returnFiber, oldFiber, newChild, expirationTime);
} else {
return null;
}
}
- case REACT_YIELD_TYPE:
+ case REACT_RETURN_TYPE:
{
- // Yields doesn't have keys. If the previous node is implicitly keyed
+ // Returns 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
// yield.
if (key === null) {
- return updateYield(returnFiber, oldFiber, newChild, priority);
+ return updateReturn(returnFiber, oldFiber, newChild, expirationTime);
} else {
return null;
}
@@ -9933,20 +7616,19 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
case REACT_PORTAL_TYPE:
{
if (newChild.key === key) {
- return updatePortal(returnFiber, oldFiber, newChild, priority);
+ return updatePortal(returnFiber, oldFiber, newChild, expirationTime);
} else {
return null;
}
}
}
- if (isArray(newChild) || getIteratorFn(newChild)) {
- // Fragments doesn't have keys so if the previous key is implicit we can
- // update it.
+ if (isArray$1(newChild) || getIteratorFn(newChild)) {
if (key !== null) {
return null;
}
- return updateFragment(returnFiber, oldFiber, newChild, priority);
+
+ return updateFragment(returnFiber, oldFiber, newChild, expirationTime, null);
}
throwOnInvalidObjectType(returnFiber, newChild);
@@ -9961,12 +7643,12 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
return null;
}
- function updateFromMap(existingChildren, returnFiber, newIdx, newChild, priority) {
+ function updateFromMap(existingChildren, returnFiber, newIdx, newChild, expirationTime) {
if (typeof newChild === 'string' || typeof newChild === 'number') {
- // Text nodes doesn't have keys, so we neither have to check the old nor
+ // 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, priority);
+ return updateTextNode(returnFiber, matchedFiber, '' + newChild, expirationTime);
}
if (typeof newChild === 'object' && newChild !== null) {
@@ -9974,33 +7656,36 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
case REACT_ELEMENT_TYPE:
{
var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
- return updateElement(returnFiber, _matchedFiber, newChild, priority);
+ if (newChild.type === REACT_FRAGMENT_TYPE) {
+ return updateFragment(returnFiber, _matchedFiber, newChild.props.children, expirationTime, newChild.key);
+ }
+ return updateElement(returnFiber, _matchedFiber, newChild, expirationTime);
}
- case REACT_COROUTINE_TYPE:
+ case REACT_CALL_TYPE:
{
var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
- return updateCoroutine(returnFiber, _matchedFiber2, newChild, priority);
+ return updateCall(returnFiber, _matchedFiber2, newChild, expirationTime);
}
- case REACT_YIELD_TYPE:
+ case REACT_RETURN_TYPE:
{
- // Yields doesn't have keys, so we neither have to check the old nor
- // new node for the key. If both are yields, they match.
+ // Returns don't have keys, so we neither have to check the old nor
+ // new node for the key. If both are returns, they match.
var _matchedFiber3 = existingChildren.get(newIdx) || null;
- return updateYield(returnFiber, _matchedFiber3, newChild, priority);
+ return updateReturn(returnFiber, _matchedFiber3, newChild, expirationTime);
}
case REACT_PORTAL_TYPE:
{
var _matchedFiber4 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
- return updatePortal(returnFiber, _matchedFiber4, newChild, priority);
+ return updatePortal(returnFiber, _matchedFiber4, newChild, expirationTime);
}
}
- if (isArray(newChild) || getIteratorFn(newChild)) {
+ if (isArray$1(newChild) || getIteratorFn(newChild)) {
var _matchedFiber5 = existingChildren.get(newIdx) || null;
- return updateFragment(returnFiber, _matchedFiber5, newChild, priority);
+ return updateFragment(returnFiber, _matchedFiber5, newChild, expirationTime, null);
}
throwOnInvalidObjectType(returnFiber, newChild);
@@ -10025,7 +7710,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
}
switch (child.$$typeof) {
case REACT_ELEMENT_TYPE:
- case REACT_COROUTINE_TYPE:
+ case REACT_CALL_TYPE:
case REACT_PORTAL_TYPE:
warnForMissingKey(child);
var key = child.key;
@@ -10041,7 +7726,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
knownKeys.add(key);
break;
}
- warning$26(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$5());
+ warning_1(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;
@@ -10050,7 +7735,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
return knownKeys;
}
- function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, priority) {
+ 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
@@ -10093,7 +7778,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
} else {
nextOldFiber = oldFiber.sibling;
}
- var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], priority);
+ 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
@@ -10136,7 +7821,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// 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], priority);
+ var _newFiber = createChild(returnFiber, newChildren[newIdx], expirationTime);
if (!_newFiber) {
continue;
}
@@ -10157,7 +7842,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// 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], priority);
+ var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], expirationTime);
if (_newFiber2) {
if (shouldTrackSideEffects) {
if (_newFiber2.alternate !== null) {
@@ -10189,7 +7874,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
return resultingFirstChild;
}
- function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, priority) {
+ function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, expirationTime) {
// This is the same implementation as reconcileChildrenArray(),
// but using the iterator instead.
@@ -10201,7 +7886,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
if (typeof newChildrenIterable.entries === 'function') {
var possibleMap = newChildrenIterable;
if (possibleMap.entries === iteratorFn) {
- warning$26(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$5());
+ warning_1(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;
}
}
@@ -10238,7 +7923,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
} else {
nextOldFiber = oldFiber.sibling;
}
- var newFiber = updateSlot(returnFiber, oldFiber, step.value, priority);
+ 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
@@ -10281,7 +7966,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// 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, priority);
+ var _newFiber3 = createChild(returnFiber, step.value, expirationTime);
if (_newFiber3 === null) {
continue;
}
@@ -10302,7 +7987,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// 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, priority);
+ var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, expirationTime);
if (_newFiber4 !== null) {
if (shouldTrackSideEffects) {
if (_newFiber4.alternate !== null) {
@@ -10334,38 +8019,36 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
return resultingFirstChild;
}
- function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, priority) {
+ 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$5) {
+ 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, priority);
- existing.pendingProps = textContent;
+ 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$1(textContent, returnFiber.internalContextTag, priority);
+ var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime);
created['return'] = returnFiber;
return created;
}
- function reconcileSingleElement(returnFiber, currentFirstChild, element, priority) {
+ 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.type === element.type) {
+ if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.type === element.type) {
deleteRemainingChildren(returnFiber, child.sibling);
- var existing = useFiber(child, priority);
+ var existing = useFiber(child, element.type === REACT_FRAGMENT_TYPE ? element.props.children : element.props, expirationTime);
existing.ref = coerceRef(child, element);
- existing.pendingProps = element.props;
existing['return'] = returnFiber;
{
existing._debugSource = element._source;
@@ -10382,23 +8065,28 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
child = child.sibling;
}
- var created = createFiberFromElement$1(element, returnFiber.internalContextTag, priority);
- created.ref = coerceRef(currentFirstChild, element);
- created['return'] = returnFiber;
- return created;
+ if (element.type === REACT_FRAGMENT_TYPE) {
+ var created = createFiberFromFragment(element.props.children, returnFiber.internalContextTag, expirationTime, element.key);
+ created['return'] = returnFiber;
+ return created;
+ } else {
+ var _created7 = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime);
+ _created7.ref = coerceRef(currentFirstChild, element);
+ _created7['return'] = returnFiber;
+ return _created7;
+ }
}
- function reconcileSingleCoroutine(returnFiber, currentFirstChild, coroutine, priority) {
- var key = coroutine.key;
+ function reconcileSingleCall(returnFiber, currentFirstChild, call, expirationTime) {
+ var key = call.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 === CoroutineComponent$2) {
+ if (child.tag === CallComponent) {
deleteRemainingChildren(returnFiber, child.sibling);
- var existing = useFiber(child, priority);
- existing.pendingProps = coroutine;
+ var existing = useFiber(child, call, expirationTime);
existing['return'] = returnFiber;
return existing;
} else {
@@ -10411,19 +8099,19 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
child = child.sibling;
}
- var created = createFiberFromCoroutine$1(coroutine, returnFiber.internalContextTag, priority);
+ var created = createFiberFromCall(call, returnFiber.internalContextTag, expirationTime);
created['return'] = returnFiber;
return created;
}
- function reconcileSingleYield(returnFiber, currentFirstChild, yieldNode, priority) {
+ function reconcileSingleReturn(returnFiber, currentFirstChild, returnNode, expirationTime) {
// There's no need to check for keys on yields since they're stateless.
var child = currentFirstChild;
if (child !== null) {
- if (child.tag === YieldComponent$3) {
+ if (child.tag === ReturnComponent) {
deleteRemainingChildren(returnFiber, child.sibling);
- var existing = useFiber(child, priority);
- existing.type = yieldNode.value;
+ var existing = useFiber(child, null, expirationTime);
+ existing.type = returnNode.value;
existing['return'] = returnFiber;
return existing;
} else {
@@ -10431,23 +8119,22 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
}
}
- var created = createFiberFromYield$1(yieldNode, returnFiber.internalContextTag, priority);
- created.type = yieldNode.value;
+ var created = createFiberFromReturn(returnNode, returnFiber.internalContextTag, expirationTime);
+ created.type = returnNode.value;
created['return'] = returnFiber;
return created;
}
- function reconcileSinglePortal(returnFiber, currentFirstChild, portal, priority) {
+ 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$5 && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) {
+ if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) {
deleteRemainingChildren(returnFiber, child.sibling);
- var existing = useFiber(child, priority);
- existing.pendingProps = portal.children || [];
+ var existing = useFiber(child, portal.children || [], expirationTime);
existing['return'] = returnFiber;
return existing;
} else {
@@ -10460,7 +8147,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
child = child.sibling;
}
- var created = createFiberFromPortal$1(portal, returnFiber.internalContextTag, priority);
+ var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime);
created['return'] = returnFiber;
return created;
}
@@ -10468,42 +8155,46 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// 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, priority) {
+ 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) {
- // Support only the subset of return types that Stack supports. Treat
- // everything else as empty, but log a warning.
switch (newChild.$$typeof) {
case REACT_ELEMENT_TYPE:
- return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, priority));
-
- case REACT_COROUTINE_TYPE:
- return placeSingleChild(reconcileSingleCoroutine(returnFiber, currentFirstChild, newChild, priority));
-
- case REACT_YIELD_TYPE:
- return placeSingleChild(reconcileSingleYield(returnFiber, currentFirstChild, newChild, priority));
+ return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, expirationTime));
+ case REACT_CALL_TYPE:
+ return placeSingleChild(reconcileSingleCall(returnFiber, currentFirstChild, newChild, expirationTime));
+ case REACT_RETURN_TYPE:
+ return placeSingleChild(reconcileSingleReturn(returnFiber, currentFirstChild, newChild, expirationTime));
case REACT_PORTAL_TYPE:
- return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, priority));
+ return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, expirationTime));
}
}
if (typeof newChild === 'string' || typeof newChild === 'number') {
- return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, priority));
+ return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, expirationTime));
}
- if (isArray(newChild)) {
- return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, priority);
+ if (isArray$1(newChild)) {
+ return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, expirationTime);
}
if (getIteratorFn(newChild)) {
- return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, priority);
+ return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, expirationTime);
}
if (isObject) {
@@ -10520,7 +8211,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// component, throw an error. If Fiber return types are disabled,
// we already threw above.
switch (returnFiber.tag) {
- case ClassComponent$7:
+ case ClassComponent:
{
{
var instance = returnFiber.stateNode;
@@ -10533,7 +8224,7 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
// Intentionally fall through to the next case, which handles both
// functions and classes
// eslint-disable-next-lined no-fallthrough
- case FunctionalComponent$2:
+ case FunctionalComponent:
{
var Component = returnFiber.type;
invariant_1(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');
@@ -10548,13 +8239,10 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
return reconcileChildFibers;
}
-var reconcileChildFibers$1 = ChildReconciler(true, true);
+var reconcileChildFibers = ChildReconciler(true);
+var mountChildFibers = ChildReconciler(false);
-var reconcileChildFibersInPlace$1 = ChildReconciler(false, true);
-
-var mountChildFibersInPlace$1 = ChildReconciler(false, false);
-
-var cloneChildFibers$1 = function (current, workInProgress) {
+function cloneChildFibers(current, workInProgress) {
!(current === null || workInProgress.child === current.child) ? invariant_1(false, 'Resuming work not yet implemented.') : void 0;
if (workInProgress.child === null) {
@@ -10562,613 +8250,23 @@ var cloneChildFibers$1 = function (current, workInProgress) {
}
var currentChild = workInProgress.child;
- var newChild = createWorkInProgress$2(currentChild, currentChild.pendingWorkPriority);
- // TODO: Pass this as an argument, since it's easy to forget.
- newChild.pendingProps = currentChild.pendingProps;
+ 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$2(currentChild, currentChild.pendingWorkPriority);
- newChild.pendingProps = currentChild.pendingProps;
+ newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
newChild['return'] = workInProgress;
}
newChild.sibling = null;
-};
-
-var ReactChildFiber = {
- reconcileChildFibers: reconcileChildFibers$1,
- reconcileChildFibersInPlace: reconcileChildFibersInPlace$1,
- mountChildFibersInPlace: mountChildFibersInPlace$1,
- cloneChildFibers: cloneChildFibers$1
-};
-
-/**
- * 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.
- *
- * @typechecks
- *
- */
-
-/*eslint-disable no-self-compare */
-
-var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
-
-/**
- * inlined Object.is polyfill to avoid requiring consumers ship their own
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
- */
-function is(x, y) {
- // SameValue algorithm
- if (x === y) {
- // Steps 1-5, 7-10
- // Steps 6.b-6.e: +0 != -0
- // Added the nonzero y check to make Flow happy, but it is redundant
- return x !== 0 || y !== 0 || 1 / x === 1 / y;
- } else {
- // Step 6.a: NaN == NaN
- return x !== x && y !== y;
- }
}
-/**
- * Performs equality by iterating through keys on an object and returning false
- * when any key has values which are not strictly equal between the arguments.
- * Returns true when the values of all keys are strictly equal.
- */
-function shallowEqual(objA, objB) {
- if (is(objA, objB)) {
- return true;
- }
-
- if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
- return false;
- }
-
- var keysA = Object.keys(objA);
- var keysB = Object.keys(objB);
-
- if (keysA.length !== keysB.length) {
- return false;
- }
-
- // Test for A's keys different from B.
- for (var i = 0; i < keysA.length; i++) {
- if (!hasOwnProperty$2.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
- return false;
- }
- }
-
- return true;
-}
-
-var shallowEqual_1 = shallowEqual;
-
-var Update$1 = ReactTypeOfSideEffect.Update;
-
-
-
-var AsyncUpdates$1 = ReactTypeOfInternalContext.AsyncUpdates;
-
-var cacheContext$1 = ReactFiberContext.cacheContext;
-var getMaskedContext$2 = ReactFiberContext.getMaskedContext;
-var getUnmaskedContext$2 = ReactFiberContext.getUnmaskedContext;
-var isContextConsumer$1 = ReactFiberContext.isContextConsumer;
-
-var addUpdate$1 = ReactFiberUpdateQueue.addUpdate;
-var addReplaceUpdate$1 = ReactFiberUpdateQueue.addReplaceUpdate;
-var addForceUpdate$1 = ReactFiberUpdateQueue.addForceUpdate;
-var beginUpdateQueue$2 = ReactFiberUpdateQueue.beginUpdateQueue;
-
-var _require5 = ReactFiberContext;
-var hasContextChanged$2 = _require5.hasContextChanged;
-
-var isMounted$1 = ReactFiberTreeReflection.isMounted;
-
-
-
-
-
-
-
-var fakeInternalInstance = {};
-var isArray$1 = Array.isArray;
-
{
- var _require7$1 = ReactDebugFiberPerf_1,
- startPhaseTimer$1 = _require7$1.startPhaseTimer,
- stopPhaseTimer$1 = _require7$1.stopPhaseTimer;
-
- var warning$27 = warning_1;
- var warnOnInvalidCallback = function (callback, callerName) {
- warning$27(callback === null || typeof callback === 'function', '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
- };
-
- // 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_1(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 (scheduleUpdate, getPriorityContext, memoizeProps, memoizeState) {
- // Class component state updater
- var updater = {
- isMounted: isMounted$1,
- enqueueSetState: function (instance, partialState, callback) {
- var fiber = ReactInstanceMap_1.get(instance);
- var priorityLevel = getPriorityContext(fiber, false);
- callback = callback === undefined ? null : callback;
- {
- warnOnInvalidCallback(callback, 'setState');
- }
- addUpdate$1(fiber, partialState, callback, priorityLevel);
- scheduleUpdate(fiber, priorityLevel);
- },
- enqueueReplaceState: function (instance, state, callback) {
- var fiber = ReactInstanceMap_1.get(instance);
- var priorityLevel = getPriorityContext(fiber, false);
- callback = callback === undefined ? null : callback;
- {
- warnOnInvalidCallback(callback, 'replaceState');
- }
- addReplaceUpdate$1(fiber, state, callback, priorityLevel);
- scheduleUpdate(fiber, priorityLevel);
- },
- enqueueForceUpdate: function (instance, callback) {
- var fiber = ReactInstanceMap_1.get(instance);
- var priorityLevel = getPriorityContext(fiber, false);
- callback = callback === undefined ? null : callback;
- {
- warnOnInvalidCallback(callback, 'forceUpdate');
- }
- addForceUpdate$1(fiber, callback, priorityLevel);
- scheduleUpdate(fiber, priorityLevel);
- }
- };
-
- 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$1(workInProgress, 'shouldComponentUpdate');
- }
- var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, newContext);
- {
- stopPhaseTimer$1();
- }
-
- {
- warning$27(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentName_1(workInProgress) || 'Unknown');
- }
-
- return shouldUpdate;
- }
-
- if (type.prototype && type.prototype.isPureReactComponent) {
- return !shallowEqual_1(oldProps, newProps) || !shallowEqual_1(oldState, newState);
- }
-
- return true;
- }
-
- function checkClassInstance(workInProgress) {
- var instance = workInProgress.stateNode;
- var type = workInProgress.type;
- {
- var name = getComponentName_1(workInProgress);
- var renderPresent = instance.render;
- warning$27(renderPresent, '%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$27(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$27(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$27(noInstancePropTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name);
- var noInstanceContextTypes = !instance.contextTypes;
- warning$27(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$27(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$27(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_1(workInProgress) || 'A pure component');
- }
- var noComponentDidUnmount = typeof instance.componentDidUnmount !== 'function';
- warning$27(noComponentDidUnmount, '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name);
- var noComponentWillRecieveProps = typeof instance.componentWillRecieveProps !== 'function';
- warning$27(noComponentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name);
- var hasMutatedProps = instance.props !== workInProgress.pendingProps;
- warning$27(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$27(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$1(state))) {
- invariant_1(false, '%s.state: must be set to an object or null', getComponentName_1(workInProgress));
- }
- if (typeof instance.getChildContext === 'function') {
- !(typeof workInProgress.type.childContextTypes === 'object') ? invariant_1(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', getComponentName_1(workInProgress)) : void 0;
- }
- }
-
- 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
- ReactInstanceMap_1.set(instance, workInProgress);
- {
- instance._reactInternalInstance = fakeInternalInstance;
- }
- }
-
- function constructClassInstance(workInProgress, props) {
- var ctor = workInProgress.type;
- var unmaskedContext = getUnmaskedContext$2(workInProgress);
- var needsContext = isContextConsumer$1(workInProgress);
- var context = needsContext ? getMaskedContext$2(workInProgress, unmaskedContext) : emptyObject_1;
- var instance = new ctor(props, context);
- adoptClassInstance(workInProgress, instance);
-
- // 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$1(workInProgress, unmaskedContext, context);
- }
-
- return instance;
- }
-
- function callComponentWillMount(workInProgress, instance) {
- {
- startPhaseTimer$1(workInProgress, 'componentWillMount');
- }
- var oldState = instance.state;
- instance.componentWillMount();
- {
- stopPhaseTimer$1();
- }
-
- if (oldState !== instance.state) {
- {
- warning$27(false, '%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentName_1(workInProgress));
- }
- updater.enqueueReplaceState(instance, instance.state, null);
- }
- }
-
- function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) {
- {
- startPhaseTimer$1(workInProgress, 'componentWillReceiveProps');
- }
- var oldState = instance.state;
- instance.componentWillReceiveProps(newProps, newContext);
- {
- stopPhaseTimer$1();
- }
-
- if (instance.state !== oldState) {
- {
- warning$27(false, '%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentName_1(workInProgress));
- }
- updater.enqueueReplaceState(instance, instance.state, null);
- }
- }
-
- // Invokes the mount life-cycles on a previously never rendered instance.
- function mountClassInstance(workInProgress, priorityLevel) {
- var current = workInProgress.alternate;
-
- {
- checkClassInstance(workInProgress);
- }
-
- var instance = workInProgress.stateNode;
- var state = instance.state || null;
-
- var props = workInProgress.pendingProps;
- !props ? invariant_1(false, 'There must be pending props for an initial mount. This error is likely caused by a bug in React. Please file an issue.') : void 0;
-
- var unmaskedContext = getUnmaskedContext$2(workInProgress);
-
- instance.props = props;
- instance.state = state;
- instance.refs = emptyObject_1;
- instance.context = getMaskedContext$2(workInProgress, unmaskedContext);
-
- if (ReactFeatureFlags_1.enableAsyncSubtreeAPI && workInProgress.type != null && workInProgress.type.prototype != null && workInProgress.type.prototype.unstable_isAsyncReactComponent === true) {
- workInProgress.internalContextTag |= AsyncUpdates$1;
- }
-
- if (typeof instance.componentWillMount === '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 = beginUpdateQueue$2(current, workInProgress, updateQueue, instance, state, props, priorityLevel);
- }
- }
- if (typeof instance.componentDidMount === 'function') {
- workInProgress.effectTag |= Update$1;
- }
- }
-
- // 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 = beginUpdateQueue(
- // 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 = beginUpdateQueue(
- // 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, priorityLevel) {
- var instance = workInProgress.stateNode;
- resetInputPointers(workInProgress, instance);
-
- var oldProps = workInProgress.memoizedProps;
- var newProps = workInProgress.pendingProps;
- if (!newProps) {
- // If there aren't any new props, then we'll reuse the memoized props.
- // This could be from already completed work.
- newProps = oldProps;
- !(newProps != null) ? invariant_1(false, 'There should always be pending or memoized props. This error is likely caused by a bug in React. Please file an issue.') : void 0;
- }
- var oldContext = instance.context;
- var newUnmaskedContext = getUnmaskedContext$2(workInProgress);
- var newContext = getMaskedContext$2(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.
-
- if (typeof instance.componentWillReceiveProps === 'function' && (oldProps !== newProps || oldContext !== newContext)) {
- callComponentWillReceiveProps(workInProgress, instance, newProps, newContext);
- }
-
- // 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 = beginUpdateQueue$2(current, workInProgress, workInProgress.updateQueue, instance, oldState, newProps, priorityLevel);
- } else {
- newState = oldState;
- }
-
- if (oldProps === newProps && oldState === newState && !hasContextChanged$2() && !(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$1;
- }
- }
- return false;
- }
-
- var shouldUpdate = checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext);
-
- if (shouldUpdate) {
- if (typeof instance.componentWillUpdate === 'function') {
- {
- startPhaseTimer$1(workInProgress, 'componentWillUpdate');
- }
- instance.componentWillUpdate(newProps, newState, newContext);
- {
- stopPhaseTimer$1();
- }
- }
- if (typeof instance.componentDidUpdate === 'function') {
- workInProgress.effectTag |= Update$1;
- }
- } 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$1;
- }
- }
-
- // 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,
- constructClassInstance: constructClassInstance,
- mountClassInstance: mountClassInstance,
- // resumeMountClassInstance,
- updateClassInstance: updateClassInstance
- };
-};
-
-var mountChildFibersInPlace = ReactChildFiber.mountChildFibersInPlace;
-var reconcileChildFibers = ReactChildFiber.reconcileChildFibers;
-var reconcileChildFibersInPlace = ReactChildFiber.reconcileChildFibersInPlace;
-var cloneChildFibers = ReactChildFiber.cloneChildFibers;
-
-var beginUpdateQueue$1 = ReactFiberUpdateQueue.beginUpdateQueue;
-
-
-
-var getMaskedContext$1 = ReactFiberContext.getMaskedContext;
-var getUnmaskedContext$1 = ReactFiberContext.getUnmaskedContext;
-var hasContextChanged$1 = ReactFiberContext.hasContextChanged;
-var pushContextProvider$1 = ReactFiberContext.pushContextProvider;
-var pushTopLevelContextObject$1 = ReactFiberContext.pushTopLevelContextObject;
-var invalidateContextProvider$1 = ReactFiberContext.invalidateContextProvider;
-
-var IndeterminateComponent$2 = ReactTypeOfWork.IndeterminateComponent;
-var FunctionalComponent$1 = ReactTypeOfWork.FunctionalComponent;
-var ClassComponent$6 = ReactTypeOfWork.ClassComponent;
-var HostRoot$7 = ReactTypeOfWork.HostRoot;
-var HostComponent$7 = ReactTypeOfWork.HostComponent;
-var HostText$4 = ReactTypeOfWork.HostText;
-var HostPortal$4 = ReactTypeOfWork.HostPortal;
-var CoroutineComponent$1 = ReactTypeOfWork.CoroutineComponent;
-var CoroutineHandlerPhase = ReactTypeOfWork.CoroutineHandlerPhase;
-var YieldComponent$2 = ReactTypeOfWork.YieldComponent;
-var Fragment$2 = ReactTypeOfWork.Fragment;
-
-var NoWork$3 = ReactPriorityLevel.NoWork;
-var OffscreenPriority$1 = ReactPriorityLevel.OffscreenPriority;
-
-var PerformedWork$1 = ReactTypeOfSideEffect.PerformedWork;
-var Placement$2 = ReactTypeOfSideEffect.Placement;
-var ContentReset$1 = ReactTypeOfSideEffect.ContentReset;
-var Err$1 = ReactTypeOfSideEffect.Err;
-var Ref$1 = ReactTypeOfSideEffect.Ref;
-
-
-
-var ReactCurrentOwner$2 = ReactGlobalSharedState_1.ReactCurrentOwner;
-
-
-
-{
- var ReactDebugCurrentFiber$4 = ReactDebugCurrentFiber_1;
-
- var _require7 = ReactDebugFiberPerf_1,
- cancelWorkTimer = _require7.cancelWorkTimer;
-
- var warning$25 = warning_1;
-
var warnedAboutStatelessRefs = {};
}
-var ReactFiberBeginWork = function (config, hostContext, hydrationContext, scheduleUpdate, getPriorityContext) {
+var ReactFiberBeginWork = function (config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber) {
var shouldSetTextContent = config.shouldSetTextContent,
useSyncScheduling = config.useSyncScheduling,
shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree;
@@ -11178,43 +8276,40 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
resetHydrationState = hydrationContext.resetHydrationState,
tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance;
- var _ReactFiberClassCompo = ReactFiberClassComponent(scheduleUpdate, getPriorityContext, memoizeProps, memoizeState),
+ var _ReactFiberClassCompo = ReactFiberClassComponent(scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState),
adoptClassInstance = _ReactFiberClassCompo.adoptClassInstance,
constructClassInstance = _ReactFiberClassCompo.constructClassInstance,
mountClassInstance = _ReactFiberClassCompo.mountClassInstance,
updateClassInstance = _ReactFiberClassCompo.updateClassInstance;
+ // TODO: Remove this and use reconcileChildrenAtExpirationTime directly.
+
+
function reconcileChildren(current, workInProgress, nextChildren) {
- var priorityLevel = workInProgress.pendingWorkPriority;
- reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel);
+ reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, workInProgress.expirationTime);
}
- function reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel) {
+ 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 = mountChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel);
- } else if (current.child === workInProgress.child) {
+ 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, workInProgress.child, nextChildren, priorityLevel);
- } else {
- // If, on the other hand, it is already using a clone, that means we've
- // already begun some work on this tree and we can continue where we left
- // off by reconciling against the existing children.
- workInProgress.child = reconcileChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel);
+ workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderExpirationTime);
}
}
function updateFragment(current, workInProgress) {
var nextChildren = workInProgress.pendingProps;
- if (hasContextChanged$1()) {
+ 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.
if (nextChildren === null) {
@@ -11232,7 +8327,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
var ref = workInProgress.ref;
if (ref !== null && (!current || current.ref !== ref)) {
// Schedule a Ref effect
- workInProgress.effectTag |= Ref$1;
+ workInProgress.effectTag |= Ref;
}
}
@@ -11241,7 +8336,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
var nextProps = workInProgress.pendingProps;
var memoizedProps = workInProgress.memoizedProps;
- if (hasContextChanged$1()) {
+ 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.
if (nextProps === null) {
@@ -11255,44 +8350,44 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
// It used to be here.
}
- var unmaskedContext = getUnmaskedContext$1(workInProgress);
- var context = getMaskedContext$1(workInProgress, unmaskedContext);
+ var unmaskedContext = getUnmaskedContext(workInProgress);
+ var context = getMaskedContext(workInProgress, unmaskedContext);
var nextChildren;
{
- ReactCurrentOwner$2.current = workInProgress;
- ReactDebugCurrentFiber$4.setCurrentFiber(workInProgress, 'render');
+ ReactCurrentOwner.current = workInProgress;
+ ReactDebugCurrentFiber.setCurrentPhase('render');
nextChildren = fn(nextProps, context);
- ReactDebugCurrentFiber$4.setCurrentFiber(workInProgress, null);
+ ReactDebugCurrentFiber.setCurrentPhase(null);
}
// React DevTools reads this flag.
- workInProgress.effectTag |= PerformedWork$1;
+ workInProgress.effectTag |= PerformedWork;
reconcileChildren(current, workInProgress, nextChildren);
memoizeProps(workInProgress, nextProps);
return workInProgress.child;
}
- function updateClassComponent(current, workInProgress, priorityLevel) {
+ 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$1(workInProgress);
+ 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, priorityLevel);
+ mountClassInstance(workInProgress, renderExpirationTime);
shouldUpdate = true;
} else {
invariant_1(false, 'Resuming work not yet implemented.');
// In a resume, we'll already have an instance we can reuse.
- // shouldUpdate = resumeMountClassInstance(workInProgress, priorityLevel);
+ // shouldUpdate = resumeMountClassInstance(workInProgress, renderExpirationTime);
}
} else {
- shouldUpdate = updateClassInstance(current, workInProgress, priorityLevel);
+ shouldUpdate = updateClassInstance(current, workInProgress, renderExpirationTime);
}
return finishClassComponent(current, workInProgress, shouldUpdate, hasContext);
}
@@ -11304,7 +8399,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
if (!shouldUpdate) {
// Context providers should defer to sCU for rendering
if (hasContext) {
- invalidateContextProvider$1(workInProgress, false);
+ invalidateContextProvider(workInProgress, false);
}
return bailoutOnAlreadyFinishedWork(current, workInProgress);
@@ -11313,15 +8408,18 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
var instance = workInProgress.stateNode;
// Rerender
- ReactCurrentOwner$2.current = workInProgress;
+ ReactCurrentOwner.current = workInProgress;
var nextChildren = void 0;
{
- ReactDebugCurrentFiber$4.setCurrentFiber(workInProgress, 'render');
+ ReactDebugCurrentFiber.setCurrentPhase('render');
nextChildren = instance.render();
- ReactDebugCurrentFiber$4.setCurrentFiber(workInProgress, null);
+ if (debugRenderPhaseSideEffects) {
+ instance.render();
+ }
+ ReactDebugCurrentFiber.setCurrentPhase(null);
}
// React DevTools reads this flag.
- workInProgress.effectTag |= PerformedWork$1;
+ 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.
@@ -11330,7 +8428,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
// The context might have changed so we need to recalculate it.
if (hasContext) {
- invalidateContextProvider$1(workInProgress, true);
+ invalidateContextProvider(workInProgress, true);
}
return workInProgress.child;
@@ -11339,28 +8437,29 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
function pushHostRootContext(workInProgress) {
var root = workInProgress.stateNode;
if (root.pendingContext) {
- pushTopLevelContextObject$1(workInProgress, root.pendingContext, root.pendingContext !== root.context);
+ pushTopLevelContextObject(workInProgress, root.pendingContext, root.pendingContext !== root.context);
} else if (root.context) {
// Should always be set
- pushTopLevelContextObject$1(workInProgress, root.context, false);
+ pushTopLevelContextObject(workInProgress, root.context, false);
}
pushHostContainer(workInProgress, root.containerInfo);
}
- function updateHostRoot(current, workInProgress, priorityLevel) {
+ function updateHostRoot(current, workInProgress, renderExpirationTime) {
pushHostRootContext(workInProgress);
var updateQueue = workInProgress.updateQueue;
if (updateQueue !== null) {
var prevState = workInProgress.memoizedState;
- var state = beginUpdateQueue$1(current, workInProgress, updateQueue, null, prevState, null, priorityLevel);
+ 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 matching this priority.
+ // no work that expires at this time.
resetHydrationState();
return bailoutOnAlreadyFinishedWork(current, workInProgress);
}
var element = state.element;
- if ((current === null || current.child === null) && enterHydrationState(workInProgress)) {
+ 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
@@ -11370,12 +8469,12 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
// 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$2;
+ 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 = mountChildFibersInPlace(workInProgress, workInProgress.child, element, priorityLevel);
+ workInProgress.child = mountChildFibers(workInProgress, null, element, renderExpirationTime);
} else {
// Otherwise reset hydration state in case we aborted and resumed another
// root.
@@ -11390,7 +8489,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
return bailoutOnAlreadyFinishedWork(current, workInProgress);
}
- function updateHostComponent(current, workInProgress, renderPriority) {
+ function updateHostComponent(current, workInProgress, renderExpirationTime) {
pushHostContext(workInProgress);
if (current === null) {
@@ -11406,7 +8505,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
}
var prevProps = current !== null ? current.memoizedProps : null;
- if (hasContextChanged$1()) {
+ 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 (nextProps === null || memoizedProps === nextProps) {
@@ -11425,16 +8524,16 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
} 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$1;
+ workInProgress.effectTag |= ContentReset;
}
markRef(current, workInProgress);
// Check the host config to see if the children are offscreen/hidden.
- if (renderPriority !== OffscreenPriority$1 && !useSyncScheduling && shouldDeprioritizeSubtree(type, nextProps)) {
+ if (renderExpirationTime !== Never && !useSyncScheduling && shouldDeprioritizeSubtree(type, nextProps)) {
// Down-prioritize the children.
- workInProgress.pendingWorkPriority = OffscreenPriority$1;
- // Bailout and come back to this fiber later at OffscreenPriority.
+ workInProgress.expirationTime = Never;
+ // Bailout and come back to this fiber later.
return null;
}
@@ -11457,45 +8556,49 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
return null;
}
- function mountIndeterminateComponent(current, workInProgress, priorityLevel) {
+ function mountIndeterminateComponent(current, workInProgress, renderExpirationTime) {
!(current === null) ? invariant_1(false, 'An indeterminate component should never have mounted. This error is likely caused by a bug in React. Please file an issue.') : void 0;
var fn = workInProgress.type;
var props = workInProgress.pendingProps;
- var unmaskedContext = getUnmaskedContext$1(workInProgress);
- var context = getMaskedContext$1(workInProgress, unmaskedContext);
+ var unmaskedContext = getUnmaskedContext(workInProgress);
+ var context = getMaskedContext(workInProgress, unmaskedContext);
var value;
{
- ReactCurrentOwner$2.current = workInProgress;
+ if (fn.prototype && typeof fn.prototype.render === 'function') {
+ var componentName = getComponentName(workInProgress);
+ warning_1(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);
+ }
+ ReactCurrentOwner.current = workInProgress;
value = fn(props, context);
}
// React DevTools reads this flag.
- workInProgress.effectTag |= PerformedWork$1;
+ workInProgress.effectTag |= PerformedWork;
if (typeof value === 'object' && value !== null && typeof value.render === 'function') {
// Proceed under the assumption that this is a class instance
- workInProgress.tag = ClassComponent$6;
+ workInProgress.tag = ClassComponent;
// 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$1(workInProgress);
+ var hasContext = pushContextProvider(workInProgress);
adoptClassInstance(workInProgress, value);
- mountClassInstance(workInProgress, priorityLevel);
+ mountClassInstance(workInProgress, renderExpirationTime);
return finishClassComponent(current, workInProgress, true, hasContext);
} else {
// Proceed under the assumption that this is a functional component
- workInProgress.tag = FunctionalComponent$1;
+ workInProgress.tag = FunctionalComponent;
{
var Component = workInProgress.type;
if (Component) {
- warning$25(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component');
+ warning_1(!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$4.getCurrentFiberOwnerName();
+ var ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
if (ownerName) {
info += '\n\nCheck the render method of `' + ownerName + '`.';
}
@@ -11507,7 +8610,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
}
if (!warnedAboutStatelessRefs[warningKey]) {
warnedAboutStatelessRefs[warningKey] = true;
- warning$25(false, 'Stateless function components cannot be given refs. ' + 'Attempts to access this ref will fail.%s%s', info, ReactDebugCurrentFiber$4.getCurrentFiberStackAddendum());
+ warning_1(false, 'Stateless function components cannot be given refs. ' + 'Attempts to access this ref will fail.%s%s', info, ReactDebugCurrentFiber.getCurrentFiberStackAddendum());
}
}
}
@@ -11517,46 +8620,42 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
}
}
- function updateCoroutineComponent(current, workInProgress) {
- var nextCoroutine = workInProgress.pendingProps;
- if (hasContextChanged$1()) {
+ function updateCallComponent(current, workInProgress, renderExpirationTime) {
+ var nextCall = 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.
- if (nextCoroutine === null) {
- nextCoroutine = current && current.memoizedProps;
- !(nextCoroutine !== null) ? invariant_1(false, 'We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+ if (nextCall === null) {
+ nextCall = current && current.memoizedProps;
+ !(nextCall !== null) ? invariant_1(false, 'We should always have pending or current props. This error is likely caused by a bug in React. Please file an issue.') : void 0;
}
- } else if (nextCoroutine === null || workInProgress.memoizedProps === nextCoroutine) {
- nextCoroutine = workInProgress.memoizedProps;
+ } else if (nextCall === null || workInProgress.memoizedProps === nextCall) {
+ nextCall = 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 = nextCoroutine.children;
- var priorityLevel = workInProgress.pendingWorkPriority;
+ var nextChildren = nextCall.children;
- // The following is a fork of reconcileChildrenAtPriority but using
+ // The following is a fork of reconcileChildrenAtExpirationTime but using
// stateNode to store the child.
if (current === null) {
- workInProgress.stateNode = mountChildFibersInPlace(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel);
- } else if (current.child === workInProgress.child) {
- workInProgress.stateNode = reconcileChildFibers(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel);
+ workInProgress.stateNode = mountChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
} else {
- workInProgress.stateNode = reconcileChildFibersInPlace(workInProgress, workInProgress.stateNode, nextChildren, priorityLevel);
+ workInProgress.stateNode = reconcileChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
}
- memoizeProps(workInProgress, nextCoroutine);
+ memoizeProps(workInProgress, nextCall);
// 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) {
+ function updatePortalComponent(current, workInProgress, renderExpirationTime) {
pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
- var priorityLevel = workInProgress.pendingWorkPriority;
var nextChildren = workInProgress.pendingProps;
- if (hasContextChanged$1()) {
+ 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.
if (nextChildren === null) {
@@ -11573,7 +8672,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
// 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 = reconcileChildFibersInPlace(workInProgress, workInProgress.child, nextChildren, priorityLevel);
+ workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
memoizeProps(workInProgress, nextChildren);
} else {
reconcileChildren(current, workInProgress, nextChildren);
@@ -11602,9 +8701,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
*/
function bailoutOnAlreadyFinishedWork(current, workInProgress) {
- {
- cancelWorkTimer(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
@@ -11625,20 +8722,18 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
}
function bailoutOnLowPriority(current, workInProgress) {
- {
- cancelWorkTimer(workInProgress);
- }
+ cancelWorkTimer(workInProgress);
// TODO: Handle HostComponent tags here as well and call pushHostContext()?
// See PR 8590 discussion for context
switch (workInProgress.tag) {
- case HostRoot$7:
+ case HostRoot:
pushHostRootContext(workInProgress);
break;
- case ClassComponent$6:
- pushContextProvider$1(workInProgress);
+ case ClassComponent:
+ pushContextProvider(workInProgress);
break;
- case HostPortal$4:
+ case HostPortal:
pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
break;
}
@@ -11655,57 +8750,53 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
function memoizeState(workInProgress, nextState) {
workInProgress.memoizedState = nextState;
// Don't reset the updateQueue, in case there are pending updates. Resetting
- // is handled by beginUpdateQueue.
+ // is handled by processUpdateQueue.
}
- function beginWork(current, workInProgress, priorityLevel) {
- if (workInProgress.pendingWorkPriority === NoWork$3 || workInProgress.pendingWorkPriority > priorityLevel) {
+ function beginWork(current, workInProgress, renderExpirationTime) {
+ if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
return bailoutOnLowPriority(current, workInProgress);
}
- {
- ReactDebugCurrentFiber$4.setCurrentFiber(workInProgress, null);
- }
-
switch (workInProgress.tag) {
- case IndeterminateComponent$2:
- return mountIndeterminateComponent(current, workInProgress, priorityLevel);
- case FunctionalComponent$1:
+ case IndeterminateComponent:
+ return mountIndeterminateComponent(current, workInProgress, renderExpirationTime);
+ case FunctionalComponent:
return updateFunctionalComponent(current, workInProgress);
- case ClassComponent$6:
- return updateClassComponent(current, workInProgress, priorityLevel);
- case HostRoot$7:
- return updateHostRoot(current, workInProgress, priorityLevel);
- case HostComponent$7:
- return updateHostComponent(current, workInProgress, priorityLevel);
- case HostText$4:
+ 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 CoroutineHandlerPhase:
+ case CallHandlerPhase:
// This is a restart. Reset the tag to the initial phase.
- workInProgress.tag = CoroutineComponent$1;
+ workInProgress.tag = CallComponent;
// Intentionally fall through since this is now the same.
- case CoroutineComponent$1:
- return updateCoroutineComponent(current, workInProgress);
- case YieldComponent$2:
- // A yield component is just a placeholder, we can just run through the
+ 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$4:
- return updatePortalComponent(current, workInProgress);
- case Fragment$2:
+ case HostPortal:
+ return updatePortalComponent(current, workInProgress, renderExpirationTime);
+ case Fragment:
return updateFragment(current, workInProgress);
default:
invariant_1(false, 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.');
}
}
- function beginFailedWork(current, workInProgress, priorityLevel) {
+ function beginFailedWork(current, workInProgress, renderExpirationTime) {
// Push context providers here to avoid a push/pop context mismatch.
switch (workInProgress.tag) {
- case ClassComponent$6:
- pushContextProvider$1(workInProgress);
+ case ClassComponent:
+ pushContextProvider(workInProgress);
break;
- case HostRoot$7:
+ case HostRoot:
pushHostRootContext(workInProgress);
break;
default:
@@ -11713,7 +8804,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
}
// Add an error effect so we can handle the error during the commit phase
- workInProgress.effectTag |= Err$1;
+ 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
@@ -11726,7 +8817,7 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
workInProgress.child = current.child;
}
- if (workInProgress.pendingWorkPriority === NoWork$3 || workInProgress.pendingWorkPriority > priorityLevel) {
+ if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
return bailoutOnLowPriority(current, workInProgress);
}
@@ -11737,9 +8828,9 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
// Unmount the current children as if the component rendered null
var nextChildren = null;
- reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel);
+ reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, renderExpirationTime);
- if (workInProgress.tag === ClassComponent$6) {
+ if (workInProgress.tag === ClassComponent) {
var instance = workInProgress.stateNode;
workInProgress.memoizedProps = instance.props;
workInProgress.memoizedState = instance.state;
@@ -11754,43 +8845,14 @@ var ReactFiberBeginWork = function (config, hostContext, hydrationContext, sched
};
};
-var reconcileChildFibers$2 = ReactChildFiber.reconcileChildFibers;
-
-var popContextProvider$2 = ReactFiberContext.popContextProvider;
-var popTopLevelContextObject$1 = ReactFiberContext.popTopLevelContextObject;
-
-
-
-
-var IndeterminateComponent$3 = ReactTypeOfWork.IndeterminateComponent;
-var FunctionalComponent$3 = ReactTypeOfWork.FunctionalComponent;
-var ClassComponent$8 = ReactTypeOfWork.ClassComponent;
-var HostRoot$8 = ReactTypeOfWork.HostRoot;
-var HostComponent$8 = ReactTypeOfWork.HostComponent;
-var HostText$6 = ReactTypeOfWork.HostText;
-var HostPortal$6 = ReactTypeOfWork.HostPortal;
-var CoroutineComponent$3 = ReactTypeOfWork.CoroutineComponent;
-var CoroutineHandlerPhase$1 = ReactTypeOfWork.CoroutineHandlerPhase;
-var YieldComponent$4 = ReactTypeOfWork.YieldComponent;
-var Fragment$4 = ReactTypeOfWork.Fragment;
-var Placement$4 = ReactTypeOfSideEffect.Placement;
-var Ref$2 = ReactTypeOfSideEffect.Ref;
-var Update$2 = ReactTypeOfSideEffect.Update;
-var OffscreenPriority$2 = ReactPriorityLevel.OffscreenPriority;
-
-
-{
- var ReactDebugCurrentFiber$5 = ReactDebugCurrentFiber_1;
-}
-
-
-
var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
var createInstance = config.createInstance,
createTextInstance = config.createTextInstance,
appendInitialChild = config.appendInitialChild,
finalizeInitialChildren = config.finalizeInitialChildren,
- prepareUpdate = config.prepareUpdate;
+ prepareUpdate = config.prepareUpdate,
+ mutation = config.mutation,
+ persistence = config.persistence;
var getRootHostContainer = hostContext.getRootHostContainer,
popHostContext = hostContext.popHostContext,
getHostContext = hostContext.getHostContext,
@@ -11803,23 +8865,23 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
function markUpdate(workInProgress) {
// Tag the fiber with an update effect. This turns a Placement into
// an UpdateAndPlacement.
- workInProgress.effectTag |= Update$2;
+ workInProgress.effectTag |= Update;
}
function markRef(workInProgress) {
- workInProgress.effectTag |= Ref$2;
+ workInProgress.effectTag |= Ref;
}
- function appendAllYields(yields, workInProgress) {
+ function appendAllReturns(returns, workInProgress) {
var node = workInProgress.stateNode;
if (node) {
node['return'] = workInProgress;
}
while (node !== null) {
- if (node.tag === HostComponent$8 || node.tag === HostText$6 || node.tag === HostPortal$6) {
- invariant_1(false, 'A coroutine cannot have host component children.');
- } else if (node.tag === YieldComponent$4) {
- yields.push(node.type);
+ if (node.tag === HostComponent || node.tag === HostText || node.tag === HostPortal) {
+ invariant_1(false, 'A call cannot have host component children.');
+ } else if (node.tag === ReturnComponent) {
+ returns.push(node.type);
} else if (node.child !== null) {
node.child['return'] = node;
node = node.child;
@@ -11836,31 +8898,29 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
}
}
- function moveCoroutineToHandlerPhase(current, workInProgress) {
- var coroutine = workInProgress.memoizedProps;
- !coroutine ? invariant_1(false, 'Should be resolved by now. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+ function moveCallToHandlerPhase(current, workInProgress, renderExpirationTime) {
+ var call = workInProgress.memoizedProps;
+ !call ? invariant_1(false, 'Should be resolved by now. This error is likely caused by a bug in React. Please file an issue.') : void 0;
- // First step of the coroutine has completed. Now we need to do the second.
- // TODO: It would be nice to have a multi stage coroutine represented by a
+ // 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 = CoroutineHandlerPhase$1;
+ workInProgress.tag = CallHandlerPhase;
- // Build up the yields.
+ // Build up the returns.
// TODO: Compare this to a generator or opaque helpers like Children.
- var yields = [];
- appendAllYields(yields, workInProgress);
- var fn = coroutine.handler;
- var props = coroutine.props;
- var nextChildren = fn(props, yields);
+ var returns = [];
+ appendAllReturns(returns, workInProgress);
+ var fn = call.handler;
+ var props = call.props;
+ var nextChildren = fn(props, returns);
var currentFirstChild = current !== null ? current.child : null;
- // Inherit the priority of the returnFiber.
- var priority = workInProgress.pendingWorkPriority;
- workInProgress.child = reconcileChildFibers$2(workInProgress, currentFirstChild, nextChildren, priority);
+ workInProgress.child = reconcileChildFibers(workInProgress, currentFirstChild, nextChildren, renderExpirationTime);
return workInProgress.child;
}
@@ -11869,13 +8929,14 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
// children to find all the terminal nodes.
var node = workInProgress.child;
while (node !== null) {
- if (node.tag === HostComponent$8 || node.tag === HostText$6) {
+ if (node.tag === HostComponent || node.tag === HostText) {
appendInitialChild(parent, node.stateNode);
- } else if (node.tag === HostPortal$6) {
+ } 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;
}
@@ -11888,37 +8949,176 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
}
node = node['return'];
}
+ node.sibling['return'] = node['return'];
node = node.sibling;
}
}
- function completeWork(current, workInProgress, renderPriority) {
- {
- ReactDebugCurrentFiber$5.setCurrentFiber(workInProgress, null);
+ 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) {
+ // 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_1(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) {
+ // 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)) {
+ 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_1(false, 'Persistent reconciler is disabled.');
+ }
+ } else {
+ if (enableNoopReconciler) {
+ // No host operations
+ updateHostContainer = function (workInProgress) {
+ // Noop
+ };
+ updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance) {
+ // Noop
+ };
+ updateHostText = function (current, workInProgress, oldText, newText) {
+ // Noop
+ };
+ } else {
+ invariant_1(false, 'Noop reconciler is disabled.');
}
+ }
+ function completeWork(current, workInProgress, renderExpirationTime) {
// Get the latest props.
var newProps = workInProgress.pendingProps;
if (newProps === null) {
newProps = workInProgress.memoizedProps;
- } else if (workInProgress.pendingWorkPriority !== OffscreenPriority$2 || renderPriority === OffscreenPriority$2) {
+ } else if (workInProgress.expirationTime !== Never || renderExpirationTime === Never) {
// Reset the pending props, unless this was a down-prioritization.
workInProgress.pendingProps = null;
}
switch (workInProgress.tag) {
- case FunctionalComponent$3:
+ case FunctionalComponent:
return null;
- case ClassComponent$8:
+ case ClassComponent:
{
// We are leaving this subtree, so pop context if any.
- popContextProvider$2(workInProgress);
+ popContextProvider(workInProgress);
return null;
}
- case HostRoot$8:
+ case HostRoot:
{
popHostContainer(workInProgress);
- popTopLevelContextObject$1(workInProgress);
+ popTopLevelContextObject(workInProgress);
var fiberRoot = workInProgress.stateNode;
if (fiberRoot.pendingContext) {
fiberRoot.context = fiberRoot.pendingContext;
@@ -11931,11 +9131,12 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
popHydrationState(workInProgress);
// This resets the hacky state to fix isMounted before committing.
// TODO: Delete this when we delete isMounted and findDOMNode.
- workInProgress.effectTag &= ~Placement$4;
+ workInProgress.effectTag &= ~Placement;
}
+ updateHostContainer(workInProgress);
return null;
}
- case HostComponent$8:
+ case HostComponent:
{
popHostContext(workInProgress);
var rootContainerInstance = getRootHostContainer();
@@ -11952,13 +9153,8 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
var currentHostContext = getHostContext();
var updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext);
- // TODO: Type this specific to this type of component.
- workInProgress.updateQueue = updatePayload;
- // If the update payload indicates that there is a change or if there
- // is a new ref we mark this as an update.
- if (updatePayload) {
- markUpdate(workInProgress);
- }
+ updateHostComponent(current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance);
+
if (current.ref !== workInProgress.ref) {
markRef(workInProgress);
}
@@ -11976,7 +9172,7 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
// bottom->up. Top->down is faster in IE11.
var wasHydrated = popHydrationState(workInProgress);
if (wasHydrated) {
- // TOOD: Move this and createInstance step into the beginPhase
+ // 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
@@ -12004,16 +9200,14 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
}
return null;
}
- case HostText$6:
+ 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.
- if (oldText !== newText) {
- markUpdate(workInProgress);
- }
+ updateHostText(current, workInProgress, oldText, newText);
} else {
if (typeof newText !== 'string') {
!(workInProgress.stateNode !== null) ? invariant_1(false, 'We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.') : void 0;
@@ -12033,24 +9227,23 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
}
return null;
}
- case CoroutineComponent$3:
- return moveCoroutineToHandlerPhase(current, workInProgress);
- case CoroutineHandlerPhase$1:
- // Reset the tag to now be a first phase coroutine.
- workInProgress.tag = CoroutineComponent$3;
+ 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 YieldComponent$4:
+ case ReturnComponent:
// Does nothing.
return null;
- case Fragment$4:
+ case Fragment:
return null;
- case HostPortal$6:
- // TODO: Only mark this as an update if we have any pending callbacks.
- markUpdate(workInProgress);
+ case HostPortal:
popHostContainer(workInProgress);
+ updateHostContainer(workInProgress);
return null;
// Error cases
- case IndeterminateComponent$3:
+ case IndeterminateComponent:
invariant_1(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:
@@ -12063,137 +9256,29 @@ var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
};
};
-{
- var warning$28 = warning_1;
-}
-
-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$28(false, 'React DevTools encountered an error: %s', err);
- }
- }
- };
-}
-
-function injectInternals$1(internals) {
- if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
- // No DevTools
- return false;
- }
- var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;
- if (!hook.supportsFiber) {
- {
- warning$28(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$28(false, 'React DevTools encountered an error: %s.', err);
- }
- }
- // DevTools exists
- return true;
-}
-
-function onCommitRoot$1(root) {
- if (typeof onCommitFiberRoot === 'function') {
- onCommitFiberRoot(root);
- }
-}
-
-function onCommitUnmount$1(fiber) {
- if (typeof onCommitFiberUnmount === 'function') {
- onCommitFiberUnmount(fiber);
- }
-}
-
-var injectInternals_1 = injectInternals$1;
-var onCommitRoot_1 = onCommitRoot$1;
-var onCommitUnmount_1 = onCommitUnmount$1;
-
-var ReactFiberDevToolsHook = {
- injectInternals: injectInternals_1,
- onCommitRoot: onCommitRoot_1,
- onCommitUnmount: onCommitUnmount_1
-};
-
-var ClassComponent$9 = ReactTypeOfWork.ClassComponent;
-var HostRoot$9 = ReactTypeOfWork.HostRoot;
-var HostComponent$9 = ReactTypeOfWork.HostComponent;
-var HostText$7 = ReactTypeOfWork.HostText;
-var HostPortal$7 = ReactTypeOfWork.HostPortal;
-var CoroutineComponent$4 = ReactTypeOfWork.CoroutineComponent;
+var invokeGuardedCallback$2 = ReactErrorUtils.invokeGuardedCallback;
+var hasCaughtError$1 = ReactErrorUtils.hasCaughtError;
+var clearCaughtError$1 = ReactErrorUtils.clearCaughtError;
-var commitCallbacks$1 = ReactFiberUpdateQueue.commitCallbacks;
-
-var onCommitUnmount = ReactFiberDevToolsHook.onCommitUnmount;
-
-var invokeGuardedCallback$2 = ReactErrorUtils_1.invokeGuardedCallback;
-var hasCaughtError$1 = ReactErrorUtils_1.hasCaughtError;
-var clearCaughtError$1 = ReactErrorUtils_1.clearCaughtError;
-
-var Placement$5 = ReactTypeOfSideEffect.Placement;
-var Update$3 = ReactTypeOfSideEffect.Update;
-var Callback$1 = ReactTypeOfSideEffect.Callback;
-var ContentReset$2 = ReactTypeOfSideEffect.ContentReset;
-
-
-
-{
- var _require5$1 = ReactDebugFiberPerf_1,
- startPhaseTimer$2 = _require5$1.startPhaseTimer,
- stopPhaseTimer$2 = _require5$1.stopPhaseTimer;
-}
var ReactFiberCommitWork = function (config, captureError) {
- var commitMount = config.commitMount,
- commitUpdate = config.commitUpdate,
- resetTextContent = config.resetTextContent,
- commitTextUpdate = config.commitTextUpdate,
- appendChild = config.appendChild,
- appendChildToContainer = config.appendChildToContainer,
- insertBefore = config.insertBefore,
- insertInContainerBefore = config.insertInContainerBefore,
- removeChild = config.removeChild,
- removeChildFromContainer = config.removeChildFromContainer,
- getPublicInstance = config.getPublicInstance;
+ var getPublicInstance = config.getPublicInstance,
+ mutation = config.mutation,
+ persistence = config.persistence;
- {
- var callComponentWillUnmountWithTimerInDev = function (current, instance) {
- startPhaseTimer$2(current, 'componentWillUnmount');
- instance.props = current.memoizedProps;
- instance.state = current.memoizedState;
- instance.componentWillUnmount();
- stopPhaseTimer$2();
- };
- }
+ 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$2(null, callComponentWillUnmountWithTimerInDev, null, current, instance);
+ invokeGuardedCallback$2(null, callComponentWillUnmountWithTimer, null, current, instance);
if (hasCaughtError$1()) {
var unmountError = clearCaughtError$1();
captureError(current, unmountError);
@@ -12214,6 +9299,269 @@ var ReactFiberCommitWork = function (config, captureError) {
}
}
+ 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 = finishedWork.child !== null ? finishedWork.child.stateNode : null;
+ 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_1(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;
+ }
+ }
+
+ if (!mutation) {
+ var commitContainer = void 0;
+ if (persistence) {
+ var replaceContainerChildren = persistence.replaceContainerChildren,
+ createContainerChildSet = persistence.createContainerChildSet;
+
+ var 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_1(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_1(false, 'Persistent reconciler is disabled.');
+ } else {
+ invariant_1(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) {
@@ -12226,7 +9574,7 @@ var ReactFiberCommitWork = function (config, captureError) {
}
function isHostParent(fiber) {
- return fiber.tag === HostComponent$9 || fiber.tag === HostRoot$9 || fiber.tag === HostPortal$7;
+ return fiber.tag === HostComponent || fiber.tag === HostRoot || fiber.tag === HostPortal;
}
function getHostSibling(fiber) {
@@ -12246,16 +9594,16 @@ var ReactFiberCommitWork = function (config, captureError) {
}
node.sibling['return'] = node['return'];
node = node.sibling;
- while (node.tag !== HostComponent$9 && node.tag !== HostText$7) {
+ 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$5) {
+ 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$7) {
+ if (node.child === null || node.tag === HostPortal) {
continue siblings;
} else {
node.child['return'] = node;
@@ -12263,7 +9611,7 @@ var ReactFiberCommitWork = function (config, captureError) {
}
}
// Check if this host node is stable or about to be placed.
- if (!(node.effectTag & Placement$5)) {
+ if (!(node.effectTag & Placement)) {
// Found it!
return node.stateNode;
}
@@ -12276,26 +9624,26 @@ var ReactFiberCommitWork = function (config, captureError) {
var parent = void 0;
var isContainer = void 0;
switch (parentFiber.tag) {
- case HostComponent$9:
+ case HostComponent:
parent = parentFiber.stateNode;
isContainer = false;
break;
- case HostRoot$9:
+ case HostRoot:
parent = parentFiber.stateNode.containerInfo;
isContainer = true;
break;
- case HostPortal$7:
+ case HostPortal:
parent = parentFiber.stateNode.containerInfo;
isContainer = true;
break;
default:
invariant_1(false, 'Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue.');
}
- if (parentFiber.effectTag & ContentReset$2) {
+ 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$2;
+ parentFiber.effectTag &= ~ContentReset;
}
var before = getHostSibling(finishedWork);
@@ -12303,7 +9651,7 @@ var ReactFiberCommitWork = function (config, captureError) {
// children to find all the terminal nodes.
var node = finishedWork;
while (true) {
- if (node.tag === HostComponent$9 || node.tag === HostText$7) {
+ if (node.tag === HostComponent || node.tag === HostText) {
if (before) {
if (isContainer) {
insertInContainerBefore(parent, node.stateNode, before);
@@ -12317,7 +9665,7 @@ var ReactFiberCommitWork = function (config, captureError) {
appendChild(parent, node.stateNode);
}
}
- } else if (node.tag === HostPortal$7) {
+ } 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.
@@ -12340,35 +9688,6 @@ var ReactFiberCommitWork = function (config, captureError) {
}
}
- 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 && node.tag !== HostPortal$7) {
- 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 unmountHostComponents(current) {
// We only have the top Fiber that was inserted but we need recurse down its
var node = current;
@@ -12385,15 +9704,15 @@ var ReactFiberCommitWork = function (config, captureError) {
findParent: while (true) {
!(parent !== null) ? invariant_1(false, 'Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue.') : void 0;
switch (parent.tag) {
- case HostComponent$9:
+ case HostComponent:
currentParent = parent.stateNode;
currentParentIsContainer = false;
break findParent;
- case HostRoot$9:
+ case HostRoot:
currentParent = parent.stateNode.containerInfo;
currentParentIsContainer = true;
break findParent;
- case HostPortal$7:
+ case HostPortal:
currentParent = parent.stateNode.containerInfo;
currentParentIsContainer = true;
break findParent;
@@ -12403,7 +9722,7 @@ var ReactFiberCommitWork = function (config, captureError) {
currentParentIsValid = true;
}
- if (node.tag === HostComponent$9 || node.tag === HostText$7) {
+ 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.
@@ -12413,7 +9732,7 @@ var ReactFiberCommitWork = function (config, captureError) {
removeChild(currentParent, node.stateNode);
}
// Don't visit children because we already visited them.
- } else if (node.tag === HostPortal$7) {
+ } 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;
@@ -12440,7 +9759,7 @@ var ReactFiberCommitWork = function (config, captureError) {
return;
}
node = node['return'];
- if (node.tag === HostPortal$7) {
+ 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;
@@ -12455,66 +9774,16 @@ var ReactFiberCommitWork = function (config, captureError) {
// Recursively delete all host nodes from the parent.
// Detach refs and call componentWillUnmount() on the whole subtree.
unmountHostComponents(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;
- }
- }
-
- // 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$9:
- {
- safelyDetachRef(current);
- var instance = current.stateNode;
- if (typeof instance.componentWillUnmount === 'function') {
- safelyCallComponentWillUnmount(current, instance);
- }
- return;
- }
- case HostComponent$9:
- {
- safelyDetachRef(current);
- return;
- }
- case CoroutineComponent$4:
- {
- commitNestedUnmounts(current.stateNode);
- return;
- }
- case HostPortal$7:
- {
- // TODO: this is recursive.
- // We are also not using this parent because
- // the portal will get pushed immediately.
- unmountHostComponents(current);
- return;
- }
- }
+ detachFiber(current);
}
function commitWork(current, finishedWork) {
switch (finishedWork.tag) {
- case ClassComponent$9:
+ case ClassComponent:
{
return;
}
- case HostComponent$9:
+ case HostComponent:
{
var instance = finishedWork.stateNode;
if (instance != null) {
@@ -12534,7 +9803,7 @@ var ReactFiberCommitWork = function (config, captureError) {
}
return;
}
- case HostText$7:
+ case HostText:
{
!(finishedWork.stateNode !== null) ? invariant_1(false, 'This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue.') : void 0;
var textInstance = finishedWork.stateNode;
@@ -12546,89 +9815,8 @@ var ReactFiberCommitWork = function (config, captureError) {
commitTextUpdate(textInstance, oldText, newText);
return;
}
- case HostRoot$9:
- {
- return;
- }
- case HostPortal$7:
- {
- return;
- }
- default:
- {
- invariant_1(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 commitLifeCycles(current, finishedWork) {
- switch (finishedWork.tag) {
- case ClassComponent$9:
- {
- var instance = finishedWork.stateNode;
- if (finishedWork.effectTag & Update$3) {
- if (current === null) {
- {
- startPhaseTimer$2(finishedWork, 'componentDidMount');
- }
- instance.props = finishedWork.memoizedProps;
- instance.state = finishedWork.memoizedState;
- instance.componentDidMount();
- {
- stopPhaseTimer$2();
- }
- } else {
- var prevProps = current.memoizedProps;
- var prevState = current.memoizedState;
- {
- startPhaseTimer$2(finishedWork, 'componentDidUpdate');
- }
- instance.props = finishedWork.memoizedProps;
- instance.state = finishedWork.memoizedState;
- instance.componentDidUpdate(prevProps, prevState);
- {
- stopPhaseTimer$2();
- }
- }
- }
- if (finishedWork.effectTag & Callback$1 && finishedWork.updateQueue !== null) {
- commitCallbacks$1(finishedWork, finishedWork.updateQueue, instance);
- }
- return;
- }
- case HostRoot$9:
- {
- var updateQueue = finishedWork.updateQueue;
- if (updateQueue !== null) {
- var _instance = finishedWork.child && finishedWork.child.stateNode;
- commitCallbacks$1(finishedWork, updateQueue, _instance);
- }
- return;
- }
- case HostComponent$9:
- {
- 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$3) {
- var type = finishedWork.type;
- var props = finishedWork.memoizedProps;
- commitMount(_instance2, type, props, finishedWork);
- }
-
- return;
- }
- case HostText$7:
+ case HostRoot:
{
- // We have no life-cycles associated with text.
- return;
- }
- case HostPortal$7:
- {
- // We have no life-cycles associated with portals.
return;
}
default:
@@ -12638,43 +9826,25 @@ var ReactFiberCommitWork = function (config, captureError) {
}
}
- function commitAttachRef(finishedWork) {
- var ref = finishedWork.ref;
- if (ref !== null) {
- var instance = finishedWork.stateNode;
- switch (finishedWork.tag) {
- case HostComponent$9:
- ref(getPublicInstance(instance));
- break;
- default:
- ref(instance);
- }
- }
+ function commitResetTextContent(current) {
+ resetTextContent(current.stateNode);
}
- function commitDetachRef(current) {
- var currentRef = current.ref;
- if (currentRef !== null) {
- currentRef(null);
- }
+ if (enableMutatingReconciler) {
+ return {
+ commitResetTextContent: commitResetTextContent,
+ commitPlacement: commitPlacement,
+ commitDeletion: commitDeletion,
+ commitWork: commitWork,
+ commitLifeCycles: commitLifeCycles,
+ commitAttachRef: commitAttachRef,
+ commitDetachRef: commitDetachRef
+ };
+ } else {
+ invariant_1(false, 'Mutating reconciler is disabled.');
}
-
- return {
- commitPlacement: commitPlacement,
- commitDeletion: commitDeletion,
- commitWork: commitWork,
- commitLifeCycles: commitLifeCycles,
- commitAttachRef: commitAttachRef,
- commitDetachRef: commitDetachRef
- };
};
-var createCursor$2 = ReactFiberStack.createCursor;
-var pop$2 = ReactFiberStack.pop;
-var push$2 = ReactFiberStack.push;
-
-
-
var NO_CONTEXT = {};
var ReactFiberHostContext = function (config) {
@@ -12682,9 +9852,9 @@ var ReactFiberHostContext = function (config) {
getRootHostContext = config.getRootHostContext;
- var contextStackCursor = createCursor$2(NO_CONTEXT);
- var contextFiberStackCursor = createCursor$2(NO_CONTEXT);
- var rootInstanceStackCursor = createCursor$2(NO_CONTEXT);
+ var contextStackCursor = createCursor(NO_CONTEXT);
+ var contextFiberStackCursor = createCursor(NO_CONTEXT);
+ var rootInstanceStackCursor = createCursor(NO_CONTEXT);
function requiredContext(c) {
!(c !== NO_CONTEXT) ? invariant_1(false, 'Expected host context to exist. This error is likely caused by a bug in React. Please file an issue.') : void 0;
@@ -12699,20 +9869,20 @@ var ReactFiberHostContext = function (config) {
function pushHostContainer(fiber, nextRootInstance) {
// Push current root instance onto the stack;
// This allows us to reset root when portals are popped.
- push$2(rootInstanceStackCursor, nextRootInstance, fiber);
+ 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$2(contextFiberStackCursor, fiber, fiber);
- push$2(contextStackCursor, nextRootContext, fiber);
+ push(contextFiberStackCursor, fiber, fiber);
+ push(contextStackCursor, nextRootContext, fiber);
}
function popHostContainer(fiber) {
- pop$2(contextStackCursor, fiber);
- pop$2(contextFiberStackCursor, fiber);
- pop$2(rootInstanceStackCursor, fiber);
+ pop(contextStackCursor, fiber);
+ pop(contextFiberStackCursor, fiber);
+ pop(rootInstanceStackCursor, fiber);
}
function getHostContext() {
@@ -12732,8 +9902,8 @@ var ReactFiberHostContext = function (config) {
// Track the context and the Fiber that provided it.
// This enables us to pop only Fibers that provide unique contexts.
- push$2(contextFiberStackCursor, fiber, fiber);
- push$2(contextStackCursor, nextContext, fiber);
+ push(contextFiberStackCursor, fiber, fiber);
+ push(contextStackCursor, nextContext, fiber);
}
function popHostContext(fiber) {
@@ -12743,8 +9913,8 @@ var ReactFiberHostContext = function (config) {
return;
}
- pop$2(contextStackCursor, fiber);
- pop$2(contextFiberStackCursor, fiber);
+ pop(contextStackCursor, fiber);
+ pop(contextFiberStackCursor, fiber);
}
function resetHostContainer() {
@@ -12763,30 +9933,13 @@ var ReactFiberHostContext = function (config) {
};
};
-var HostComponent$10 = ReactTypeOfWork.HostComponent;
-var HostText$8 = ReactTypeOfWork.HostText;
-var HostRoot$10 = ReactTypeOfWork.HostRoot;
-
-var Deletion$2 = ReactTypeOfSideEffect.Deletion;
-var Placement$6 = ReactTypeOfSideEffect.Placement;
-
-var createFiberFromHostInstanceForDeletion$1 = ReactFiber.createFiberFromHostInstanceForDeletion;
-
var ReactFiberHydrationContext = function (config) {
var shouldSetTextContent = config.shouldSetTextContent,
- canHydrateInstance = config.canHydrateInstance,
- canHydrateTextInstance = config.canHydrateTextInstance,
- getNextHydratableSibling = config.getNextHydratableSibling,
- getFirstHydratableChild = config.getFirstHydratableChild,
- hydrateInstance = config.hydrateInstance,
- hydrateTextInstance = config.hydrateTextInstance,
- didNotHydrateInstance = config.didNotHydrateInstance,
- didNotFindHydratableInstance = config.didNotFindHydratableInstance,
- didNotFindHydratableTextInstance = config.didNotFindHydratableTextInstance;
+ hydration = config.hydration;
// If this doesn't have hydration mode.
- if (!(canHydrateInstance && canHydrateTextInstance && getNextHydratableSibling && getFirstHydratableChild && hydrateInstance && hydrateTextInstance && didNotHydrateInstance && didNotFindHydratableInstance && didNotFindHydratableTextInstance)) {
+ if (!hydration) {
return {
enterHydrationState: function () {
return false;
@@ -12805,8 +9958,24 @@ var ReactFiberHydrationContext = function (config) {
};
}
+ 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;
@@ -12822,19 +9991,19 @@ var ReactFiberHydrationContext = function (config) {
function deleteHydratableInstance(returnFiber, instance) {
{
switch (returnFiber.tag) {
- case HostRoot$10:
- didNotHydrateInstance(returnFiber.stateNode.containerInfo, instance);
+ case HostRoot:
+ didNotHydrateContainerInstance(returnFiber.stateNode.containerInfo, instance);
break;
- case HostComponent$10:
- didNotHydrateInstance(returnFiber.stateNode, instance);
+ case HostComponent:
+ didNotHydrateInstance(returnFiber.type, returnFiber.memoizedProps, returnFiber.stateNode, instance);
break;
}
}
- var childToDelete = createFiberFromHostInstanceForDeletion$1();
+ var childToDelete = createFiberFromHostInstanceForDeletion();
childToDelete.stateNode = instance;
childToDelete['return'] = returnFiber;
- childToDelete.effectTag = Deletion$2;
+ childToDelete.effectTag = Deletion;
// This might seem like it belongs on progressedFirstDeletion. However,
// these children are not part of the reconciliation list of children.
@@ -12850,49 +10019,71 @@ var ReactFiberHydrationContext = function (config) {
}
function insertNonHydratedInstance(returnFiber, fiber) {
- fiber.effectTag |= Placement$6;
+ fiber.effectTag |= Placement;
{
- var parentInstance;
switch (returnFiber.tag) {
- // TODO: Currently we don't warn for insertions into the root because
- // we always insert into the root in the non-hydrating case. We just
- // delete the existing content. Reenable this once we have a better
- // strategy for determining if we're hydrating or not.
- // case HostRoot:
- // parentInstance = returnFiber.stateNode.containerInfo;
- // break;
- case HostComponent$10:
- parentInstance = returnFiber.stateNode;
- break;
+ 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;
}
- switch (fiber.tag) {
- case HostComponent$10:
- var type = fiber.type;
- var props = fiber.pendingProps;
- didNotFindHydratableInstance(parentInstance, type, props);
- break;
- case HostText$8:
- var text = fiber.pendingProps;
- didNotFindHydratableTextInstance(parentInstance, text);
- break;
- }
}
}
- function canHydrate(fiber, nextInstance) {
+ function tryHydrate(fiber, nextInstance) {
switch (fiber.tag) {
- case HostComponent$10:
+ case HostComponent:
{
var type = fiber.type;
var props = fiber.pendingProps;
- return canHydrateInstance(nextInstance, type, props);
+ var instance = canHydrateInstance(nextInstance, type, props);
+ if (instance !== null) {
+ fiber.stateNode = instance;
+ return true;
+ }
+ return false;
}
- case HostText$8:
+ case HostText:
{
var text = fiber.pendingProps;
- return canHydrateTextInstance(nextInstance, text);
+ var textInstance = canHydrateTextInstance(nextInstance, text);
+ if (textInstance !== null) {
+ fiber.stateNode = textInstance;
+ return true;
+ }
+ return false;
}
default:
return false;
@@ -12911,12 +10102,12 @@ var ReactFiberHydrationContext = function (config) {
hydrationParentFiber = fiber;
return;
}
- if (!canHydrate(fiber, nextInstance)) {
+ if (!tryHydrate(fiber, nextInstance)) {
// If we can't hydrate this instance let's try the next one.
// We use this as a heuristic. It's based on intuition and not data so it
// might be flawed or unnecessary.
nextInstance = getNextHydratableSibling(nextInstance);
- if (!nextInstance || !canHydrate(fiber, nextInstance)) {
+ if (!nextInstance || !tryHydrate(fiber, nextInstance)) {
// Nothing to hydrate. Make it an insertion.
insertNonHydratedInstance(hydrationParentFiber, fiber);
isHydrating = false;
@@ -12929,7 +10120,6 @@ var ReactFiberHydrationContext = function (config) {
// fiber associated with it.
deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance);
}
- fiber.stateNode = nextInstance;
hydrationParentFiber = fiber;
nextHydratableInstance = getFirstHydratableChild(nextInstance);
}
@@ -12949,13 +10139,39 @@ var ReactFiberHydrationContext = function (config) {
function prepareToHydrateHostTextInstance(fiber) {
var textInstance = fiber.stateNode;
- var shouldUpdate = hydrateTextInstance(textInstance, fiber.memoizedProps, fiber);
+ 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$10 && parent.tag !== HostRoot$10) {
+ while (parent !== null && parent.tag !== HostComponent && parent.tag !== HostRoot) {
parent = parent['return'];
}
hydrationParentFiber = parent;
@@ -12983,7 +10199,7 @@ var ReactFiberHydrationContext = function (config) {
// other nodes in them. We also ignore components with pure text content in
// side of them.
// TODO: Better heuristic.
- if (fiber.tag !== HostComponent$10 || type !== 'head' && type !== 'body' && !shouldSetTextContent(type, fiber.memoizedProps)) {
+ if (fiber.tag !== HostComponent || type !== 'head' && type !== 'body' && !shouldSetTextContent(type, fiber.memoizedProps)) {
var nextInstance = nextHydratableInstance;
while (nextInstance) {
deleteHydratableInstance(fiber, nextInstance);
@@ -13012,124 +10228,107 @@ var ReactFiberHydrationContext = function (config) {
};
};
-/**
- * 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.
- *
- * @providesModule ReactFiberInstrumentation
- *
- */
-
// 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$2 = {
+var ReactFiberInstrumentation = {
debugTool: null
};
-var ReactFiberInstrumentation_1 = ReactFiberInstrumentation$2;
-
-var popContextProvider$1 = ReactFiberContext.popContextProvider;
-
-var reset$1 = ReactFiberStack.reset;
-
-var getStackAddendumByWorkInProgressFiber$2 = ReactFiberComponentTreeHook.getStackAddendumByWorkInProgressFiber;
-
-var logCapturedError = ReactFiberErrorLogger.logCapturedError;
-
-var invokeGuardedCallback$1 = ReactErrorUtils_1.invokeGuardedCallback;
-var hasCaughtError = ReactErrorUtils_1.hasCaughtError;
-var clearCaughtError = ReactErrorUtils_1.clearCaughtError;
-
-
-
-
-
-
-
-var ReactCurrentOwner$1 = ReactGlobalSharedState_1.ReactCurrentOwner;
+var ReactFiberInstrumentation_1 = ReactFiberInstrumentation;
+var defaultShowDialog = function (capturedError) {
+ return true;
+};
+var showDialog = defaultShowDialog;
-var createWorkInProgress$1 = ReactFiber.createWorkInProgress;
-var largerPriority$1 = ReactFiber.largerPriority;
+function logCapturedError(capturedError) {
+ var logError = showDialog(capturedError);
-var onCommitRoot = ReactFiberDevToolsHook.onCommitRoot;
+ // Allow injected showDialog() to prevent default console.error logging.
+ // This enables renderers like ReactNative to better manage redbox behavior.
+ if (logError === false) {
+ return;
+ }
-var NoWork$2 = ReactPriorityLevel.NoWork;
-var SynchronousPriority$1 = ReactPriorityLevel.SynchronousPriority;
-var TaskPriority$1 = ReactPriorityLevel.TaskPriority;
-var HighPriority = ReactPriorityLevel.HighPriority;
-var LowPriority = ReactPriorityLevel.LowPriority;
-var OffscreenPriority = ReactPriorityLevel.OffscreenPriority;
+ var error = capturedError.error;
+ var suppressLogging = error && error.suppressReactErrorLogging;
+ if (suppressLogging) {
+ return;
+ }
-var AsyncUpdates = ReactTypeOfInternalContext.AsyncUpdates;
+ {
+ var componentName = capturedError.componentName,
+ componentStack = capturedError.componentStack,
+ errorBoundaryName = capturedError.errorBoundaryName,
+ errorBoundaryFound = capturedError.errorBoundaryFound,
+ willRetry = capturedError.willRetry;
-var PerformedWork = ReactTypeOfSideEffect.PerformedWork;
-var Placement$1 = ReactTypeOfSideEffect.Placement;
-var Update = ReactTypeOfSideEffect.Update;
-var PlacementAndUpdate = ReactTypeOfSideEffect.PlacementAndUpdate;
-var Deletion = ReactTypeOfSideEffect.Deletion;
-var ContentReset = ReactTypeOfSideEffect.ContentReset;
-var Callback = ReactTypeOfSideEffect.Callback;
-var Err = ReactTypeOfSideEffect.Err;
-var Ref = ReactTypeOfSideEffect.Ref;
-var HostRoot$6 = ReactTypeOfWork.HostRoot;
-var HostComponent$6 = ReactTypeOfWork.HostComponent;
-var HostPortal$3 = ReactTypeOfWork.HostPortal;
-var ClassComponent$5 = ReactTypeOfWork.ClassComponent;
+ var componentNameMessage = componentName ? 'The above error occurred in the <' + componentName + '> component:' : 'The above error occurred in one of your React components:';
-var getUpdatePriority$1 = ReactFiberUpdateQueue.getUpdatePriority;
+ 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);
-var _require14 = ReactFiberContext;
-var resetContext$1 = _require14.resetContext;
+ // 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$1 = ReactErrorUtils.invokeGuardedCallback;
+var hasCaughtError = ReactErrorUtils.hasCaughtError;
+var clearCaughtError = ReactErrorUtils.clearCaughtError;
{
- var warning$24 = warning_1;
- var ReactFiberInstrumentation$1 = ReactFiberInstrumentation_1;
- var ReactDebugCurrentFiber$3 = ReactDebugCurrentFiber_1;
-
- var _require15 = ReactDebugFiberPerf_1,
- recordEffect = _require15.recordEffect,
- recordScheduleUpdate = _require15.recordScheduleUpdate,
- startWorkTimer = _require15.startWorkTimer,
- stopWorkTimer = _require15.stopWorkTimer,
- stopFailedWorkTimer = _require15.stopFailedWorkTimer,
- startWorkLoopTimer = _require15.startWorkLoopTimer,
- stopWorkLoopTimer = _require15.stopWorkLoopTimer,
- startCommitTimer = _require15.startCommitTimer,
- stopCommitTimer = _require15.stopCommitTimer,
- startCommitHostEffectsTimer = _require15.startCommitHostEffectsTimer,
- stopCommitHostEffectsTimer = _require15.stopCommitHostEffectsTimer,
- startCommitLifeCyclesTimer = _require15.startCommitLifeCyclesTimer,
- stopCommitLifeCyclesTimer = _require15.stopCommitLifeCyclesTimer;
-
- var warnAboutUpdateOnUnmounted = function (instance) {
- var ctor = instance.constructor;
- warning$24(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.', ctor && (ctor.displayName || ctor.name) || 'ReactClass');
+ var didWarnAboutStateTransition = false;
+ var didWarnSetStateChildContext = false;
+ var didWarnStateUpdateForUnmountedComponent = {};
+
+ var warnAboutUpdateOnUnmounted = function (fiber) {
+ var componentName = getComponentName(fiber) || 'ReactClass';
+ if (didWarnStateUpdateForUnmountedComponent[componentName]) {
+ return;
+ }
+ warning_1(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;
};
var warnAboutInvalidUpdates = function (instance) {
- switch (ReactDebugCurrentFiber$3.phase) {
+ switch (ReactDebugCurrentFiber.phase) {
case 'getChildContext':
- warning$24(false, 'setState(...): Cannot call setState() inside getChildContext()');
+ if (didWarnSetStateChildContext) {
+ return;
+ }
+ warning_1(false, 'setState(...): Cannot call setState() inside getChildContext()');
+ didWarnSetStateChildContext = true;
break;
case 'render':
- warning$24(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`.');
+ if (didWarnAboutStateTransition) {
+ return;
+ }
+ warning_1(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 timeHeuristicForUnitOfWork = 1;
-
var ReactFiberScheduler = function (config) {
var hostContext = ReactFiberHostContext(config);
var hydrationContext = ReactFiberHydrationContext(config);
@@ -13137,7 +10336,7 @@ var ReactFiberScheduler = function (config) {
popHostContext = hostContext.popHostContext,
resetHostContainer = hostContext.resetHostContainer;
- var _ReactFiberBeginWork = ReactFiberBeginWork(config, hostContext, hydrationContext, scheduleUpdate, getPriorityContext),
+ var _ReactFiberBeginWork = ReactFiberBeginWork(config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber),
beginWork = _ReactFiberBeginWork.beginWork,
beginFailedWork = _ReactFiberBeginWork.beginFailedWork;
@@ -13145,6 +10344,7 @@ var ReactFiberScheduler = function (config) {
completeWork = _ReactFiberCompleteWo.completeWork;
var _ReactFiberCommitWork = ReactFiberCommitWork(config, captureError),
+ commitResetTextContent = _ReactFiberCommitWork.commitResetTextContent,
commitPlacement = _ReactFiberCommitWork.commitPlacement,
commitDeletion = _ReactFiberCommitWork.commitDeletion,
commitWork = _ReactFiberCommitWork.commitWork,
@@ -13152,47 +10352,34 @@ var ReactFiberScheduler = function (config) {
commitAttachRef = _ReactFiberCommitWork.commitAttachRef,
commitDetachRef = _ReactFiberCommitWork.commitDetachRef;
- var scheduleDeferredCallback = config.scheduleDeferredCallback,
+ var now = config.now,
+ scheduleDeferredCallback = config.scheduleDeferredCallback,
+ cancelDeferredCallback = config.cancelDeferredCallback,
useSyncScheduling = config.useSyncScheduling,
prepareForCommit = config.prepareForCommit,
resetAfterCommit = config.resetAfterCommit;
- // The priority level to use when scheduling an update. We use NoWork to
- // represent the default priority.
- // TODO: Should we change this to an array instead of using the call stack?
- // Might be less confusing.
+ // Represents the current time in ms.
- var priorityContext = NoWork$2;
+ var startTime = now();
+ var mostRecentCurrentTime = msToExpirationTime(0);
- // Keeps track of whether we're currently in a work loop.
- var isPerformingWork = false;
+ // 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;
- // Keeps track of whether the current deadline has expired.
- var deadlineHasExpired = false;
-
- // Keeps track of whether we should should batch sync updates.
- var isBatchingUpdates = false;
-
- // This is needed for the weird case where the initial mount is synchronous
- // even inside batchedUpdates :(
- var isUnbatchingUpdates = false;
+ var isWorking = false;
// The next work in progress fiber that we're currently working on.
var nextUnitOfWork = null;
- var nextPriorityLevel = NoWork$2;
+ 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;
- var pendingCommit = null;
-
- // Linked list of roots with scheduled work on them.
- var nextScheduledRoot = null;
- var lastScheduledRoot = null;
-
- // Keep track of which host environment callbacks are scheduled.
- var isCallbackScheduled = false;
-
// 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;
@@ -13209,88 +10396,27 @@ var ReactFiberScheduler = function (config) {
var isCommitting = false;
var isUnmounting = false;
- // Use these to prevent an infinite loop of nested updates
- var NESTED_UPDATE_LIMIT = 1000;
- var nestedUpdateCount = 0;
- var nextRenderedTree = null;
+ // Used for performance tracking.
+ var interruptedBy = null;
function resetContextStack() {
// Reset the stack
reset$1();
// Reset the cursors
- resetContext$1();
+ resetContext();
resetHostContainer();
}
- // resetNextUnitOfWork mutates the current priority context. It is reset after
- // after the workLoop exits, so never call resetNextUnitOfWork from outside
- // the work loop.
- function resetNextUnitOfWork() {
- // Clear out roots with no more work on them, or if they have uncaught errors
- while (nextScheduledRoot !== null && nextScheduledRoot.current.pendingWorkPriority === NoWork$2) {
- // Unschedule this root.
- nextScheduledRoot.isScheduled = false;
- // Read the next pointer now.
- // We need to clear it in case this root gets scheduled again later.
- var next = nextScheduledRoot.nextScheduledRoot;
- nextScheduledRoot.nextScheduledRoot = null;
- // Exit if we cleared all the roots and there's no work to do.
- if (nextScheduledRoot === lastScheduledRoot) {
- nextScheduledRoot = null;
- lastScheduledRoot = null;
- nextPriorityLevel = NoWork$2;
- return null;
- }
- // Continue with the next root.
- // If there's no work on it, it will get unscheduled too.
- nextScheduledRoot = next;
- }
-
- var root = nextScheduledRoot;
- var highestPriorityRoot = null;
- var highestPriorityLevel = NoWork$2;
- while (root !== null) {
- if (root.current.pendingWorkPriority !== NoWork$2 && (highestPriorityLevel === NoWork$2 || highestPriorityLevel > root.current.pendingWorkPriority)) {
- highestPriorityLevel = root.current.pendingWorkPriority;
- highestPriorityRoot = root;
- }
- // We didn't find anything to do in this root, so let's try the next one.
- root = root.nextScheduledRoot;
- }
- if (highestPriorityRoot !== null) {
- nextPriorityLevel = highestPriorityLevel;
- // Before we start any new work, let's make sure that we have a fresh
- // stack to work from.
- // TODO: This call is buried a bit too deep. It would be nice to have
- // a single point which happens right before any new work and
- // unfortunately this is it.
- resetContextStack();
-
- nextUnitOfWork = createWorkInProgress$1(highestPriorityRoot.current, highestPriorityLevel);
- if (highestPriorityRoot !== nextRenderedTree) {
- // We've switched trees. Reset the nested update counter.
- nestedUpdateCount = 0;
- nextRenderedTree = highestPriorityRoot;
- }
- return;
- }
-
- nextPriorityLevel = NoWork$2;
- nextUnitOfWork = null;
- nextRenderedTree = null;
- return;
- }
-
function commitAllHostEffects() {
while (nextEffect !== null) {
{
- ReactDebugCurrentFiber$3.setCurrentFiber(nextEffect, null);
- recordEffect();
+ ReactDebugCurrentFiber.setCurrentFiber(nextEffect);
}
+ recordEffect();
var effectTag = nextEffect.effectTag;
if (effectTag & ContentReset) {
- config.resetTextContent(nextEffect.stateNode);
+ commitResetTextContent(nextEffect);
}
if (effectTag & Ref) {
@@ -13306,7 +10432,7 @@ var ReactFiberScheduler = function (config) {
// effect tag and switch on that value.
var primaryEffectTag = effectTag & ~(Callback | Err | ContentReset | Ref | PerformedWork);
switch (primaryEffectTag) {
- case Placement$1:
+ case Placement:
{
commitPlacement(nextEffect);
// Clear the "placement" from effect tag so that we know that this is inserted, before
@@ -13314,7 +10440,7 @@ var ReactFiberScheduler = function (config) {
// 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$1;
+ nextEffect.effectTag &= ~Placement;
break;
}
case PlacementAndUpdate:
@@ -13323,7 +10449,7 @@ var ReactFiberScheduler = function (config) {
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$1;
+ nextEffect.effectTag &= ~Placement;
// Update
var _current = nextEffect.alternate;
@@ -13348,7 +10474,7 @@ var ReactFiberScheduler = function (config) {
}
{
- ReactDebugCurrentFiber$3.resetCurrentFiber();
+ ReactDebugCurrentFiber.resetCurrentFiber();
}
}
@@ -13356,26 +10482,19 @@ var ReactFiberScheduler = function (config) {
while (nextEffect !== null) {
var effectTag = nextEffect.effectTag;
- // Use Task priority for lifecycle updates
if (effectTag & (Update | Callback)) {
- {
- recordEffect();
- }
+ recordEffect();
var current = nextEffect.alternate;
commitLifeCycles(current, nextEffect);
}
if (effectTag & Ref) {
- {
- recordEffect();
- }
+ recordEffect();
commitAttachRef(nextEffect);
}
if (effectTag & Err) {
- {
- recordEffect();
- }
+ recordEffect();
commitErrorHandling(nextEffect);
}
@@ -13391,28 +10510,21 @@ var ReactFiberScheduler = function (config) {
}
}
- function commitAllWork(finishedWork) {
+ 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();
- }
+ startCommitTimer();
- pendingCommit = null;
var root = finishedWork.stateNode;
!(root.current !== finishedWork) ? invariant_1(false, '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.') : void 0;
-
- if (nextPriorityLevel === SynchronousPriority$1 || nextPriorityLevel === TaskPriority$1) {
- // Keep track of the number of iterations to prevent an infinite
- // update loop.
- nestedUpdateCount++;
- }
+ root.isReadyForCommit = false;
// Reset this to null before calling lifecycles
- ReactCurrentOwner$1.current = null;
+ ReactCurrentOwner.current = null;
var firstEffect = void 0;
if (finishedWork.effectTag > PerformedWork) {
@@ -13437,9 +10549,7 @@ var ReactFiberScheduler = function (config) {
// The first pass performs all the host insertions, updates, deletions and
// ref unmounts.
nextEffect = firstEffect;
- {
- startCommitHostEffectsTimer();
- }
+ startCommitHostEffectsTimer();
while (nextEffect !== null) {
var didError = false;
var _error = void 0;
@@ -13459,9 +10569,7 @@ var ReactFiberScheduler = function (config) {
}
}
}
- {
- stopCommitHostEffectsTimer();
- }
+ stopCommitHostEffectsTimer();
resetAfterCommit();
@@ -13476,9 +10584,7 @@ var ReactFiberScheduler = function (config) {
// and deletions in the entire tree have already been invoked.
// This pass also triggers any renderer-specific initial effects.
nextEffect = firstEffect;
- {
- startCommitLifeCyclesTimer();
- }
+ startCommitLifeCyclesTimer();
while (nextEffect !== null) {
var _didError = false;
var _error2 = void 0;
@@ -13499,15 +10605,14 @@ var ReactFiberScheduler = function (config) {
}
isCommitting = false;
- {
- stopCommitLifeCyclesTimer();
- stopCommitTimer();
- }
+ isWorking = false;
+ stopCommitLifeCyclesTimer();
+ stopCommitTimer();
if (typeof onCommitRoot === 'function') {
onCommitRoot(finishedWork.stateNode);
}
- if (true && ReactFiberInstrumentation$1.debugTool) {
- ReactFiberInstrumentation$1.debugTool.onCommitWork(finishedWork);
+ if (true && ReactFiberInstrumentation_1.debugTool) {
+ ReactFiberInstrumentation_1.debugTool.onCommitWork(finishedWork);
}
// If we caught any errors during this commit, schedule their boundaries
@@ -13517,29 +10622,43 @@ var ReactFiberScheduler = function (config) {
commitPhaseBoundaries = null;
}
- // This tree is done. Reset the unit of work pointer to the next highest
- // priority root. If there's no more work left, the pointer is set to null.
- resetNextUnitOfWork();
+ 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 resetWorkPriority(workInProgress, renderPriority) {
- if (workInProgress.pendingWorkPriority !== NoWork$2 && workInProgress.pendingWorkPriority > renderPriority) {
- // This was a down-prioritization. Don't bubble priority from children.
+ 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 update priority.
- var newPriority = getUpdatePriority$1(workInProgress);
+ // Check for pending updates.
+ var newExpirationTime = getUpdateExpirationTime(workInProgress);
- // TODO: Coroutines need to visit stateNode
+ // TODO: Calls need to visit stateNode
+ // Bubble up the earliest expiration time.
var child = workInProgress.child;
while (child !== null) {
- // Ensure that remaining work priority bubbles up.
- newPriority = largerPriority$1(newPriority, child.pendingWorkPriority);
+ if (child.expirationTime !== NoWork && (newExpirationTime === NoWork || newExpirationTime > child.expirationTime)) {
+ newExpirationTime = child.expirationTime;
+ }
child = child.sibling;
}
- workInProgress.pendingWorkPriority = newPriority;
+ workInProgress.expirationTime = newExpirationTime;
}
function completeUnitOfWork(workInProgress) {
@@ -13549,19 +10668,23 @@ var ReactFiberScheduler = function (config) {
// means that we don't need an additional field on the work in
// progress.
var current = workInProgress.alternate;
- var next = completeWork(current, workInProgress, nextPriorityLevel);
+ {
+ ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
+ }
+ var next = completeWork(current, workInProgress, nextRenderExpirationTime);
+ {
+ ReactDebugCurrentFiber.resetCurrentFiber();
+ }
var returnFiber = workInProgress['return'];
var siblingFiber = workInProgress.sibling;
- resetWorkPriority(workInProgress, nextPriorityLevel);
+ resetExpirationTime(workInProgress, nextRenderExpirationTime);
if (next !== null) {
- {
- stopWorkTimer(workInProgress);
- }
- if (true && ReactFiberInstrumentation$1.debugTool) {
- ReactFiberInstrumentation$1.debugTool.onCompleteWork(workInProgress);
+ 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.
@@ -13601,11 +10724,9 @@ var ReactFiberScheduler = function (config) {
}
}
- {
- stopWorkTimer(workInProgress);
- }
- if (true && ReactFiberInstrumentation$1.debugTool) {
- ReactFiberInstrumentation$1.debugTool.onCompleteWork(workInProgress);
+ stopWorkTimer(workInProgress);
+ if (true && ReactFiberInstrumentation_1.debugTool) {
+ ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress);
}
if (siblingFiber !== null) {
@@ -13616,10 +10737,9 @@ var ReactFiberScheduler = function (config) {
workInProgress = returnFiber;
continue;
} else {
- // We've reached the root. Mark the root as pending commit. Depending
- // on how much time we have left, we'll either commit it now or in
- // the next frame.
- pendingCommit = workInProgress;
+ // We've reached the root.
+ var root = workInProgress.stateNode;
+ root.isReadyForCommit = true;
return null;
}
}
@@ -13638,12 +10758,17 @@ var ReactFiberScheduler = function (config) {
var current = workInProgress.alternate;
// See if beginning this work spawns more work.
+ startWorkTimer(workInProgress);
+ {
+ ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
+ }
+
+ var next = beginWork(current, workInProgress, nextRenderExpirationTime);
{
- startWorkTimer(workInProgress);
+ ReactDebugCurrentFiber.resetCurrentFiber();
}
- var next = beginWork(current, workInProgress, nextPriorityLevel);
- if (true && ReactFiberInstrumentation$1.debugTool) {
- ReactFiberInstrumentation$1.debugTool.onBeginWork(workInProgress);
+ if (true && ReactFiberInstrumentation_1.debugTool) {
+ ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
}
if (next === null) {
@@ -13651,10 +10776,7 @@ var ReactFiberScheduler = function (config) {
next = completeUnitOfWork(workInProgress);
}
- ReactCurrentOwner$1.current = null;
- {
- ReactDebugCurrentFiber$3.resetCurrentFiber();
- }
+ ReactCurrentOwner.current = null;
return next;
}
@@ -13667,12 +10789,16 @@ var ReactFiberScheduler = function (config) {
var current = workInProgress.alternate;
// See if beginning this work spawns more work.
+ startWorkTimer(workInProgress);
+ {
+ ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
+ }
+ var next = beginFailedWork(current, workInProgress, nextRenderExpirationTime);
{
- startWorkTimer(workInProgress);
+ ReactDebugCurrentFiber.resetCurrentFiber();
}
- var next = beginFailedWork(current, workInProgress, nextPriorityLevel);
- if (true && ReactFiberInstrumentation$1.debugTool) {
- ReactFiberInstrumentation$1.debugTool.onBeginWork(workInProgress);
+ if (true && ReactFiberInstrumentation_1.debugTool) {
+ ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
}
if (next === null) {
@@ -13680,29 +10806,44 @@ var ReactFiberScheduler = function (config) {
next = completeUnitOfWork(workInProgress);
}
- ReactCurrentOwner$1.current = null;
- {
- ReactDebugCurrentFiber$3.resetCurrentFiber();
- }
+ ReactCurrentOwner.current = null;
return next;
}
- function performDeferredWork(deadline) {
- performWork(OffscreenPriority, deadline);
+ function workLoop(expirationTime) {
+ 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(expirationTime);
+ return;
+ }
+ if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
+ return;
+ }
+
+ if (nextRenderExpirationTime <= mostRecentCurrentTime) {
+ // 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 handleCommitPhaseErrors() {
- // This is a special work loop for handling commit phase errors. It's
- // similar to the syncrhonous work loop, but does an additional check on
- // each fiber to see if it's an error boundary with an unhandled error. If
- // so, it uses a forked version of performUnitOfWork that unmounts the
- // failed subtree.
- //
- // The loop stops once the children have unmounted and error lifecycles are
- // called. Then we return to the regular flow.
+ function slowWorkLoopThatChecksForFailedWork(expirationTime) {
+ if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
+ return;
+ }
- if (capturedErrors !== null && capturedErrors.size > 0 && nextPriorityLevel === TaskPriority$1) {
+ if (nextRenderExpirationTime <= mostRecentCurrentTime) {
+ // Flush all expired work.
while (nextUnitOfWork !== null) {
if (hasCapturedError(nextUnitOfWork)) {
// Use a forked version of performUnitOfWork
@@ -13710,133 +10851,21 @@ var ReactFiberScheduler = function (config) {
} else {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
}
- if (nextUnitOfWork === null) {
- !(pendingCommit !== null) ? invariant_1(false, 'Should have a pending commit. This error is likely caused by a bug in React. Please file an issue.') : void 0;
- // We just completed a root. Commit it now.
- priorityContext = TaskPriority$1;
- commitAllWork(pendingCommit);
- priorityContext = nextPriorityLevel;
-
- if (capturedErrors === null || capturedErrors.size === 0 || nextPriorityLevel !== TaskPriority$1) {
- // There are no more unhandled errors. We can exit this special
- // work loop. If there's still additional work, we'll perform it
- // using one of the normal work loops.
- break;
- }
- // The commit phase produced additional errors. Continue working.
- }
}
- }
- }
-
- function workLoop(minPriorityLevel, deadline) {
- if (pendingCommit !== null) {
- priorityContext = TaskPriority$1;
- commitAllWork(pendingCommit);
- handleCommitPhaseErrors();
- } else if (nextUnitOfWork === null) {
- resetNextUnitOfWork();
- }
-
- if (nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel) {
- return;
- }
-
- // During the render phase, updates should have the same priority at which
- // we're rendering.
- priorityContext = nextPriorityLevel;
-
- loop: do {
- if (nextPriorityLevel <= TaskPriority$1) {
- // Flush all synchronous and task work.
- while (nextUnitOfWork !== null) {
+ } 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);
- if (nextUnitOfWork === null) {
- !(pendingCommit !== null) ? invariant_1(false, 'Should have a pending commit. This error is likely caused by a bug in React. Please file an issue.') : void 0;
- // We just completed a root. Commit it now.
- priorityContext = TaskPriority$1;
- commitAllWork(pendingCommit);
- priorityContext = nextPriorityLevel;
- // Clear any errors that were scheduled during the commit phase.
- handleCommitPhaseErrors();
- // The priority level may have changed. Check again.
- if (nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel || nextPriorityLevel > TaskPriority$1) {
- // The priority level does not match.
- break;
- }
- }
- }
- } else if (deadline !== null) {
- // Flush asynchronous work until the deadline expires.
- while (nextUnitOfWork !== null && !deadlineHasExpired) {
- if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
- nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
- // In a deferred work batch, iff nextUnitOfWork returns null, we just
- // completed a root and a pendingCommit exists. Logically, we could
- // omit either of the checks in the following condition, but we need
- // both to satisfy Flow.
- if (nextUnitOfWork === null) {
- !(pendingCommit !== null) ? invariant_1(false, 'Should have a pending commit. This error is likely caused by a bug in React. Please file an issue.') : void 0;
- // We just completed a root. If we have time, commit it now.
- // Otherwise, we'll commit it in the next frame.
- if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
- priorityContext = TaskPriority$1;
- commitAllWork(pendingCommit);
- priorityContext = nextPriorityLevel;
- // Clear any errors that were scheduled during the commit phase.
- handleCommitPhaseErrors();
- // The priority level may have changed. Check again.
- if (nextPriorityLevel === NoWork$2 || nextPriorityLevel > minPriorityLevel || nextPriorityLevel < HighPriority) {
- // The priority level does not match.
- break;
- }
- } else {
- deadlineHasExpired = true;
- }
- }
- } else {
- deadlineHasExpired = true;
- }
}
}
-
- // There might be work left. Depending on the priority, we should
- // either perform it now or schedule a callback to perform it later.
- switch (nextPriorityLevel) {
- case SynchronousPriority$1:
- case TaskPriority$1:
- // We have remaining synchronous or task work. Keep performing it,
- // regardless of whether we're inside a callback.
- if (nextPriorityLevel <= minPriorityLevel) {
- continue loop;
- }
- break loop;
- case HighPriority:
- case LowPriority:
- case OffscreenPriority:
- // We have remaining async work.
- if (deadline === null) {
- // We're not inside a callback. Exit and perform the work during
- // the next callback.
- break loop;
- }
- // We are inside a callback.
- if (!deadlineHasExpired && nextPriorityLevel <= minPriorityLevel) {
- // We still have time. Keep working.
- continue loop;
- }
- // We've run out of time. Exit.
- break loop;
- case NoWork$2:
- // No work left. We can exit.
- break loop;
- default:
- invariant_1(false, 'Switch statement should be exhuastive. This error is likely caused by a bug in React. Please file an issue.');
- }
- } while (true);
+ }
}
- function performWorkCatchBlock(failedWork, boundary, minPriorityLevel, deadline) {
+ function renderRootCatchBlock(root, failedWork, boundary, expirationTime) {
// 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.
@@ -13850,25 +10879,33 @@ var ReactFiberScheduler = function (config) {
nextUnitOfWork = performFailedUnitOfWork(boundary);
// Continue working.
- workLoop(minPriorityLevel, deadline);
+ workLoop(expirationTime);
}
- function performWork(minPriorityLevel, deadline) {
- {
- startWorkLoopTimer();
- }
+ function renderRoot(root, expirationTime) {
+ !!isWorking ? invariant_1(false, 'renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+ isWorking = true;
- !!isPerformingWork ? invariant_1(false, 'performWork was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
- isPerformingWork = 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;
- // The priority context changes during the render phase. We'll need to
- // reset it at the end.
- var previousPriorityContext = priorityContext;
+ // 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$1(null, workLoop, null, minPriorityLevel, deadline);
+ invokeGuardedCallback$1(null, workLoop, null, expirationTime);
if (hasCaughtError()) {
didError = true;
error = clearCaughtError();
@@ -13905,7 +10942,7 @@ var ReactFiberScheduler = function (config) {
didError = false;
error = null;
{
- invokeGuardedCallback$1(null, performWorkCatchBlock, null, failedWork, boundary, minPriorityLevel, deadline);
+ invokeGuardedCallback$1(null, renderRootCatchBlock, null, root, failedWork, boundary, expirationTime);
if (hasCaughtError()) {
didError = true;
error = clearCaughtError();
@@ -13916,47 +10953,28 @@ var ReactFiberScheduler = function (config) {
break;
}
- // Reset the priority context to its previous value.
- priorityContext = previousPriorityContext;
-
- // If we're inside a callback, set this to false, since we just flushed it.
- if (deadline !== null) {
- isCallbackScheduled = false;
- }
- // If there's remaining async work, make sure we schedule another callback.
- if (nextPriorityLevel > TaskPriority$1 && !isCallbackScheduled) {
- scheduleDeferredCallback(performDeferredWork);
- isCallbackScheduled = true;
- }
-
- var errorToThrow = firstUncaughtError;
+ var uncaughtError = firstUncaughtError;
// We're done performing work. Time to clean up.
- isPerformingWork = false;
- deadlineHasExpired = false;
+ stopWorkLoopTimer(interruptedBy);
+ interruptedBy = null;
+ isWorking = false;
didFatal = false;
firstUncaughtError = null;
- capturedErrors = null;
- failedBoundaries = null;
- nextRenderedTree = null;
- nestedUpdateCount = 0;
- {
- stopWorkLoopTimer();
+ if (uncaughtError !== null) {
+ onUncaughtError(uncaughtError);
}
- // It's safe to throw any unhandled errors.
- if (errorToThrow !== null) {
- throw errorToThrow;
- }
+ 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$1.current = null;
+ ReactCurrentOwner.current = null;
{
- ReactDebugCurrentFiber$3.resetCurrentFiber();
+ ReactDebugCurrentFiber.resetCurrentFiber();
}
// Search for the nearest error boundary.
@@ -13970,7 +10988,7 @@ var ReactFiberScheduler = function (config) {
// 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$6) {
+ if (failedWork.tag === HostRoot) {
boundary = failedWork;
if (isFailedBoundary(failedWork)) {
@@ -13982,17 +11000,17 @@ var ReactFiberScheduler = function (config) {
} else {
var node = failedWork['return'];
while (node !== null && boundary === null) {
- if (node.tag === ClassComponent$5) {
+ if (node.tag === ClassComponent) {
var instance = node.stateNode;
if (typeof instance.componentDidCatch === 'function') {
errorBoundaryFound = true;
- errorBoundaryName = getComponentName_1(node);
+ errorBoundaryName = getComponentName(node);
// Found an error boundary!
boundary = node;
willRetry = true;
}
- } else if (node.tag === HostRoot$6) {
+ } else if (node.tag === HostRoot) {
// Treat the root like a no-op error boundary
boundary = node;
}
@@ -14037,8 +11055,8 @@ var ReactFiberScheduler = function (config) {
// 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$2(failedWork);
- var _componentName = getComponentName_1(failedWork);
+ 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
@@ -14065,7 +11083,10 @@ var ReactFiberScheduler = function (config) {
} catch (e) {
// Prevent cycle if logCapturedError() throws.
// A cycle may still occur if logCapturedError renders a component that throws.
- console.error(e);
+ var suppressLogging = e && e.suppressReactErrorLogging;
+ if (!suppressLogging) {
+ console.error(e);
+ }
}
// If we're in the commit phase, defer scheduling an update on the
@@ -14119,7 +11140,7 @@ var ReactFiberScheduler = function (config) {
!(capturedError != null) ? invariant_1(false, 'No error for given unit of work. This error is likely caused by a bug in React. Please file an issue.') : void 0;
switch (effectfulFiber.tag) {
- case ClassComponent$5:
+ case ClassComponent:
var instance = effectfulFiber.stateNode;
var info = {
@@ -14130,11 +11151,8 @@ var ReactFiberScheduler = function (config) {
// an update to itself
instance.componentDidCatch(capturedError.error, info);
return;
- case HostRoot$6:
+ case HostRoot:
if (firstUncaughtError === null) {
- // If this is the host container, we treat it as a no-op error
- // boundary. We'll throw the first uncaught error once it's safe to
- // do so, at the end of the batch.
firstUncaughtError = capturedError.error;
}
return;
@@ -14147,23 +11165,21 @@ var ReactFiberScheduler = function (config) {
var node = from;
while (node !== null) {
switch (node.tag) {
- case ClassComponent$5:
- popContextProvider$1(node);
+ case ClassComponent:
+ popContextProvider(node);
break;
- case HostComponent$6:
+ case HostComponent:
popHostContext(node);
break;
- case HostRoot$6:
+ case HostRoot:
popHostContainer(node);
break;
- case HostPortal$3:
+ case HostPortal:
popHostContainer(node);
break;
}
if (node === to || node.alternate === to) {
- {
- stopFailedWorkTimer(node);
- }
+ stopFailedWorkTimer(node);
break;
} else {
stopWorkTimer(node);
@@ -14172,105 +11188,95 @@ var ReactFiberScheduler = function (config) {
}
}
- function scheduleRoot(root, priorityLevel) {
- if (priorityLevel === NoWork$2) {
- 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);
+ }
- if (!root.isScheduled) {
- root.isScheduled = true;
- if (lastScheduledRoot) {
- // Schedule ourselves to the end.
- lastScheduledRoot.nextScheduledRoot = root;
- lastScheduledRoot = root;
+ 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 {
- // We're the only work scheduled.
- nextScheduledRoot = root;
- lastScheduledRoot = root;
+ // 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 (useSyncScheduling && !(fiber.internalContextTag & AsyncUpdates)) {
+ // This is a sync update
+ expirationTime = Sync;
+ } else {
+ // This is an async update
+ expirationTime = computeAsyncExpiration();
}
}
+ return expirationTime;
}
- function scheduleUpdate(fiber, priorityLevel) {
- return scheduleUpdateImpl(fiber, priorityLevel, false);
+ function scheduleWork(fiber, expirationTime) {
+ return scheduleWorkImpl(fiber, expirationTime, false);
}
- function scheduleUpdateImpl(fiber, priorityLevel, isErrorRecovery) {
- {
- recordScheduleUpdate();
- }
-
- if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
- didFatal = true;
- invariant_1(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.');
- }
-
- if (!isPerformingWork && priorityLevel <= nextPriorityLevel) {
- // We must reset the current unit of work pointer so that we restart the
- // search from the root during the next tick, in case there is now higher
- // priority work somewhere earlier than before.
+ 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$5) {
+ if (!isErrorRecovery && fiber.tag === ClassComponent) {
var instance = fiber.stateNode;
warnAboutInvalidUpdates(instance);
}
}
var node = fiber;
- var shouldContinue = true;
- while (node !== null && shouldContinue) {
- // Walk the parent path to the root and update each node's priority. Once
- // we reach a node whose priority matches (and whose alternate's priority
- // matches) we can exit safely knowing that the rest of the path is correct.
- shouldContinue = false;
- if (node.pendingWorkPriority === NoWork$2 || node.pendingWorkPriority > priorityLevel) {
- // Priority did not match. Update and keep going.
- shouldContinue = true;
- node.pendingWorkPriority = priorityLevel;
+ 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.pendingWorkPriority === NoWork$2 || node.alternate.pendingWorkPriority > priorityLevel) {
- // Priority did not match. Update and keep going.
- shouldContinue = true;
- node.alternate.pendingWorkPriority = priorityLevel;
+ if (node.alternate.expirationTime === NoWork || node.alternate.expirationTime > expirationTime) {
+ node.alternate.expirationTime = expirationTime;
}
}
if (node['return'] === null) {
- if (node.tag === HostRoot$6) {
+ if (node.tag === HostRoot) {
var root = node.stateNode;
- scheduleRoot(root, priorityLevel);
- if (!isPerformingWork) {
- switch (priorityLevel) {
- case SynchronousPriority$1:
- // Perform this update now.
- if (isUnbatchingUpdates) {
- // We're inside unbatchedUpdates, which is inside either
- // batchedUpdates or a lifecycle. We should only flush
- // synchronous work, not task work.
- performWork(SynchronousPriority$1, null);
- } else {
- // Flush both synchronous and task work.
- performWork(TaskPriority$1, null);
- }
- break;
- case TaskPriority$1:
- !isBatchingUpdates ? invariant_1(false, 'Task updates can only be scheduled as a nested update or inside batchedUpdates.') : void 0;
- break;
- default:
- // Schedule a callback to perform the work later.
- if (!isCallbackScheduled) {
- scheduleDeferredCallback(performDeferredWork);
- isCallbackScheduled = true;
- }
- }
- }
+
+ checkRootNeedsClearing(root, fiber, expirationTime);
+ requestWork(root, expirationTime);
+ checkRootNeedsClearing(root, fiber, expirationTime);
} else {
{
- if (!isErrorRecovery && fiber.tag === ClassComponent$5) {
- warnAboutUpdateOnUnmounted(fiber.stateNode);
+ if (!isErrorRecovery && fiber.tag === ClassComponent) {
+ warnAboutUpdateOnUnmounted(fiber);
}
}
return;
@@ -14280,28 +11286,337 @@ var ReactFiberScheduler = function (config) {
}
}
- function getPriorityContext(fiber, forceAsync) {
- var priorityLevel = priorityContext;
- if (priorityLevel === NoWork$2) {
- if (!useSyncScheduling || fiber.internalContextTag & AsyncUpdates || forceAsync) {
- priorityLevel = LowPriority;
+ 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) {
+ var previousExpirationContext = expirationContext;
+ expirationContext = Sync;
+ try {
+ return fn();
+ } 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 deadlineDidExpire = false;
+ var hasUnhandledError = false;
+ var unhandledError = null;
+ var deadline = null;
+
+ var isBatchingUpdates = false;
+ var isUnbatchingUpdates = false;
+
+ // 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_1(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 {
- priorityLevel = SynchronousPriority$1;
+ 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 we're in a batch, or if we're already performing work, downgrade sync
- // priority to task priority
- if (priorityLevel === SynchronousPriority$1 && (isPerformingWork || isBatchingUpdates)) {
- return TaskPriority$1;
+ if (isRendering) {
+ // Prevent reentrancy. Remaining work will be scheduled at the end of
+ // the currently rendering batch.
+ return;
+ }
+
+ if (isBatchingUpdates) {
+ // Flush work at the end of the batch.
+ if (isUnbatchingUpdates) {
+ // ...unless we're inside unbatchedUpdates, in which case we should
+ // flush it now.
+ nextFlushedRoot = root;
+ nextFlushedExpirationTime = Sync;
+ performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime);
+ }
+ return;
+ }
+
+ // TODO: Get rid of Sync and use current time?
+ if (expirationTime === Sync) {
+ performWork(Sync, null);
+ } else {
+ scheduleCallbackWithExpiration(expirationTime);
}
- return priorityLevel;
}
- function scheduleErrorRecovery(fiber) {
- scheduleUpdateImpl(fiber, TaskPriority$1, true);
+ 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.
+ !(previousScheduledRoot !== null && lastScheduledRoot !== null) ? invariant_1(false, 'Should have a previous and last root. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+ if (root === root.nextScheduledRoot) {
+ // This is the only root in the list.
+ root.nextScheduledRoot = null;
+ firstScheduledRoot = lastScheduledRoot = null;
+ break;
+ } else if (root === firstScheduledRoot) {
+ // This is the first root in the list.
+ var next = root.nextScheduledRoot;
+ firstScheduledRoot = next;
+ lastScheduledRoot.nextScheduledRoot = next;
+ root.nextScheduledRoot = null;
+ } else if (root === lastScheduledRoot) {
+ // This is the last root in the list.
+ lastScheduledRoot = previousScheduledRoot;
+ lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
+ root.nextScheduledRoot = null;
+ break;
+ } else {
+ previousScheduledRoot.nextScheduledRoot = root.nextScheduledRoot;
+ root.nextScheduledRoot = null;
+ }
+ root = previousScheduledRoot.nextScheduledRoot;
+ } else {
+ if (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, dl);
+ }
+
+ function performWork(minExpirationTime, 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);
+ }
+
+ while (nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && (minExpirationTime === NoWork || nextFlushedExpirationTime <= minExpirationTime) && !deadlineDidExpire) {
+ performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime);
+ // Find the next highest priority work.
+ 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;
+
+ if (hasUnhandledError) {
+ var _error4 = unhandledError;
+ unhandledError = null;
+ hasUnhandledError = false;
+ throw _error4;
+ }
+ }
+
+ function performWorkOnRoot(root, expirationTime) {
+ !!isRendering ? invariant_1(false, 'performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+
+ isRendering = true;
+
+ // Check if this is async work or sync/expired work.
+ // TODO: Pass current time as argument to renderRoot, commitRoot
+ if (expirationTime <= recalculateCurrentTime()) {
+ // Flush sync work.
+ var finishedWork = root.finishedWork;
+ if (finishedWork !== null) {
+ // This root is already complete. We can commit it.
+ root.finishedWork = null;
+ root.remainingExpirationTime = commitRoot(finishedWork);
+ } else {
+ root.finishedWork = null;
+ finishedWork = renderRoot(root, expirationTime);
+ if (finishedWork !== null) {
+ // We've completed the root. Commit it.
+ root.remainingExpirationTime = commitRoot(finishedWork);
+ }
+ }
+ } else {
+ // Flush async work.
+ var _finishedWork = root.finishedWork;
+ if (_finishedWork !== null) {
+ // This root is already complete. We can commit it.
+ root.finishedWork = null;
+ root.remainingExpirationTime = commitRoot(_finishedWork);
+ } else {
+ root.finishedWork = null;
+ _finishedWork = renderRoot(root, expirationTime);
+ if (_finishedWork !== null) {
+ // We've completed the root. Check the deadline one more time
+ // before committing.
+ if (!shouldYield()) {
+ // Still time left. Commit the root.
+ root.remainingExpirationTime = commitRoot(_finishedWork);
+ } else {
+ // There's no time left. Mark this root as complete. We'll come
+ // back and commit it later.
+ root.finishedWork = _finishedWork;
+ }
+ }
+ }
+ }
+
+ isRendering = false;
}
+ // 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) {
+ !(nextFlushedRoot !== null) ? invariant_1(false, 'Should be working on a root. This error is likely caused by a bug in React. Please file an issue.') : void 0;
+ // 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;
@@ -14309,57 +11624,44 @@ var ReactFiberScheduler = function (config) {
return fn(a);
} finally {
isBatchingUpdates = previousIsBatchingUpdates;
- // If we're not already inside a batch, we need to flush any task work
- // that was created by the user-provided function.
- if (!isPerformingWork && !isBatchingUpdates) {
- performWork(TaskPriority$1, null);
+ if (!isBatchingUpdates && !isRendering) {
+ performWork(Sync, null);
}
}
}
+ // TODO: Batching should be implemented at the renderer level, not inside
+ // the reconciler.
function unbatchedUpdates(fn) {
- var previousIsUnbatchingUpdates = isUnbatchingUpdates;
- var previousIsBatchingUpdates = isBatchingUpdates;
- // This is only true if we're nested inside batchedUpdates.
- isUnbatchingUpdates = isBatchingUpdates;
- isBatchingUpdates = false;
- try {
- return fn();
- } finally {
- isBatchingUpdates = previousIsBatchingUpdates;
- isUnbatchingUpdates = previousIsUnbatchingUpdates;
+ if (isBatchingUpdates && !isUnbatchingUpdates) {
+ isUnbatchingUpdates = true;
+ try {
+ return fn();
+ } finally {
+ isUnbatchingUpdates = false;
+ }
}
+ return fn();
}
- function flushSync(batch) {
+ // TODO: Batching should be implemented at the renderer level, not within
+ // the reconciler.
+ function flushSync(fn) {
var previousIsBatchingUpdates = isBatchingUpdates;
- var previousPriorityContext = priorityContext;
isBatchingUpdates = true;
- priorityContext = SynchronousPriority$1;
try {
- return batch();
+ return syncUpdates(fn);
} finally {
isBatchingUpdates = previousIsBatchingUpdates;
- priorityContext = previousPriorityContext;
-
- !!isPerformingWork ? invariant_1(false, 'flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.') : void 0;
- performWork(TaskPriority$1, null);
- }
- }
-
- function deferredUpdates(fn) {
- var previousPriorityContext = priorityContext;
- priorityContext = LowPriority;
- try {
- return fn();
- } finally {
- priorityContext = previousPriorityContext;
+ !!isRendering ? invariant_1(false, 'flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.') : void 0;
+ performWork(Sync, null);
}
}
return {
- scheduleUpdate: scheduleUpdate,
- getPriorityContext: getPriorityContext,
+ computeAsyncExpiration: computeAsyncExpiration,
+ computeExpirationForFiber: computeExpirationForFiber,
+ scheduleWork: scheduleWork,
batchedUpdates: batchedUpdates,
unbatchedUpdates: unbatchedUpdates,
flushSync: flushSync,
@@ -14367,79 +11669,31 @@ var ReactFiberScheduler = function (config) {
};
};
-/**
- * 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.
- *
- * @providesModule getContextForSubtree
- *
- */
-
-
-
-
+{
+ var didWarnAboutNestedUpdates = false;
+}
+// 0 is PROD, 1 is DEV.
+// Might add PROFILE later.
-var getContextFiber = function (arg) {
- invariant_1(false, 'Missing injection for fiber getContextForSubtree');
-};
function getContextForSubtree(parentComponent) {
if (!parentComponent) {
return emptyObject_1;
}
- var instance = ReactInstanceMap_1.get(parentComponent);
- if (typeof instance.tag === 'number') {
- return getContextFiber(instance);
- } else {
- return instance._processChildContext(instance._context);
- }
-}
-
-getContextForSubtree._injectFiber = function (fn) {
- getContextFiber = fn;
-};
-
-var getContextForSubtree_1 = getContextForSubtree;
-
-var addTopLevelUpdate = ReactFiberUpdateQueue.addTopLevelUpdate;
-
-var findCurrentUnmaskedContext = ReactFiberContext.findCurrentUnmaskedContext;
-var isContextProvider = ReactFiberContext.isContextProvider;
-var processChildContext = ReactFiberContext.processChildContext;
-
-var createFiberRoot = ReactFiberRoot.createFiberRoot;
-
-
-
-var HostComponent$3 = ReactTypeOfWork.HostComponent;
-
-{
- var warning$20 = warning_1;
- var ReactFiberInstrumentation = ReactFiberInstrumentation_1;
- var ReactDebugCurrentFiber$1 = ReactDebugCurrentFiber_1;
- var getComponentName$4 = getComponentName_1;
-}
-
-var findCurrentHostFiber$1 = ReactFiberTreeReflection.findCurrentHostFiber;
-var findCurrentHostFiberWithNoPortals$1 = ReactFiberTreeReflection.findCurrentHostFiberWithNoPortals;
-
-
-
-getContextForSubtree_1._injectFiber(function (fiber) {
+ var fiber = get(parentComponent);
var parentContext = findCurrentUnmaskedContext(fiber);
- return isContextProvider(fiber) ? processChildContext(fiber, parentContext, false) : parentContext;
-});
+ return isContextProvider(fiber) ? processChildContext(fiber, parentContext) : parentContext;
+}
-var ReactFiberReconciler = function (config) {
+var ReactFiberReconciler$1 = function (config) {
var getPublicInstance = config.getPublicInstance;
var _ReactFiberScheduler = ReactFiberScheduler(config),
- scheduleUpdate = _ReactFiberScheduler.scheduleUpdate,
- getPriorityContext = _ReactFiberScheduler.getPriorityContext,
+ computeAsyncExpiration = _ReactFiberScheduler.computeAsyncExpiration,
+ computeExpirationForFiber = _ReactFiberScheduler.computeExpirationForFiber,
+ scheduleWork = _ReactFiberScheduler.scheduleWork,
batchedUpdates = _ReactFiberScheduler.batchedUpdates,
unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates,
flushSync = _ReactFiberScheduler.flushSync,
@@ -14447,46 +11701,69 @@ var ReactFiberReconciler = function (config) {
function scheduleTopLevelUpdate(current, element, callback) {
{
- if (ReactDebugCurrentFiber$1.phase === 'render' && ReactDebugCurrentFiber$1.current !== null) {
- warning$20(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$4(ReactDebugCurrentFiber$1.current) || 'Unknown');
+ if (ReactDebugCurrentFiber.phase === 'render' && ReactDebugCurrentFiber.current !== null && !didWarnAboutNestedUpdates) {
+ didWarnAboutNestedUpdates = true;
+ warning_1(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');
}
}
- // Check if the top-level element is an async wrapper component. If so, treat
- // updates to the root as async. This is a bit weird but lets us avoid a separate
- // `renderAsync` API.
- var forceAsync = ReactFeatureFlags_1.enableAsyncSubtreeAPI && element != null && element.type != null && element.type.prototype != null && element.type.prototype.unstable_isAsyncReactComponent === true;
- var priorityLevel = getPriorityContext(current, forceAsync);
- var nextState = { element: element };
callback = callback === undefined ? null : callback;
{
- warning$20(callback === null || typeof callback === 'function', 'render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback);
+ warning_1(callback === null || typeof callback === 'function', 'render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback);
+ }
+
+ var expirationTime = void 0;
+ // Check if the top-level element is an async wrapper component. If so,
+ // treat updates to the root as async. This is a bit weird but lets us
+ // avoid a separate `renderAsync` API.
+ if (enableAsyncSubtreeAPI && element != null && element.type != null && element.type.prototype != null && element.type.prototype.unstable_isAsyncReactComponent === true) {
+ expirationTime = computeAsyncExpiration();
+ } else {
+ expirationTime = computeExpirationForFiber(current);
}
- addTopLevelUpdate(current, nextState, callback, priorityLevel);
- scheduleUpdate(current, priorityLevel);
+
+ var update = {
+ expirationTime: expirationTime,
+ partialState: { element: element },
+ callback: callback,
+ isReplace: false,
+ isForced: false,
+ nextCallback: null,
+ next: null
+ };
+ insertUpdateIntoFiber(current, update);
+ scheduleWork(current, expirationTime);
+ }
+
+ function findHostInstance(fiber) {
+ var hostFiber = findCurrentHostFiber(fiber);
+ if (hostFiber === null) {
+ return null;
+ }
+ return hostFiber.stateNode;
}
return {
- createContainer: function (containerInfo) {
- return createFiberRoot(containerInfo);
+ createContainer: function (containerInfo, hydrate) {
+ return createFiberRoot(containerInfo, hydrate);
},
updateContainer: function (element, container, parentComponent, callback) {
// TODO: If this is a nested container, this won't be the root.
var current = container.current;
{
- if (ReactFiberInstrumentation.debugTool) {
+ if (ReactFiberInstrumentation_1.debugTool) {
if (current.alternate === null) {
- ReactFiberInstrumentation.debugTool.onMountContainer(container);
+ ReactFiberInstrumentation_1.debugTool.onMountContainer(container);
} else if (element === null) {
- ReactFiberInstrumentation.debugTool.onUnmountContainer(container);
+ ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container);
} else {
- ReactFiberInstrumentation.debugTool.onUpdateContainer(container);
+ ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container);
}
}
}
- var context = getContextForSubtree_1(parentComponent);
+ var context = getContextForSubtree(parentComponent);
if (container.context === null) {
container.context = context;
} else {
@@ -14511,592 +11788,253 @@ var ReactFiberReconciler = function (config) {
return null;
}
switch (containerFiber.child.tag) {
- case HostComponent$3:
+ case HostComponent:
return getPublicInstance(containerFiber.child.stateNode);
default:
return containerFiber.child.stateNode;
}
},
- findHostInstance: function (fiber) {
- var hostFiber = findCurrentHostFiber$1(fiber);
- if (hostFiber === null) {
- return null;
- }
- return hostFiber.stateNode;
- },
+
+
+ findHostInstance: findHostInstance,
+
findHostInstanceWithNoPortals: function (fiber) {
- var hostFiber = findCurrentHostFiberWithNoPortals$1(fiber);
+ var hostFiber = findCurrentHostFiberWithNoPortals(fiber);
if (hostFiber === null) {
return null;
}
return hostFiber.stateNode;
+ },
+ injectIntoDevTools: function (devToolsConfig) {
+ var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance;
+
+ return injectInternals(_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 TEXT_NODE$3 = HTMLNodeType_1.TEXT_NODE;
-
-/**
- * Given any node return the first leaf node without children.
- *
- * @param {DOMElement|DOMTextNode} node
- * @return {DOMElement|DOMTextNode}
- */
-
-
-function getLeafNode(node) {
- while (node && node.firstChild) {
- node = node.firstChild;
- }
- return node;
-}
-
-/**
- * Get the next sibling within a container. This will walk up the
- * DOM if a node's siblings have been exhausted.
- *
- * @param {DOMElement|DOMTextNode} node
- * @return {?DOMElement|DOMTextNode}
- */
-function getSiblingNode(node) {
- while (node) {
- if (node.nextSibling) {
- return node.nextSibling;
- }
- node = node.parentNode;
- }
-}
-
-/**
- * Get object describing the nodes which contain characters at offset.
- *
- * @param {DOMElement|DOMTextNode} root
- * @param {number} offset
- * @return {?object}
- */
-function getNodeForCharacterOffset(root, offset) {
- var node = getLeafNode(root);
- var nodeStart = 0;
- var nodeEnd = 0;
-
- while (node) {
- if (node.nodeType === TEXT_NODE$3) {
- nodeEnd = nodeStart + node.textContent.length;
-
- if (nodeStart <= offset && nodeEnd >= offset) {
- return {
- node: node,
- offset: offset - nodeStart
- };
- }
-
- nodeStart = nodeEnd;
- }
-
- node = getLeafNode(getSiblingNode(node));
- }
-}
-
-var getNodeForCharacterOffset_1 = getNodeForCharacterOffset;
-
-var contentKey = null;
-
-/**
- * Gets the key used to access text content on a DOM node.
- *
- * @return {?string} Key used to access text content.
- * @internal
- */
-function getTextContentAccessor() {
- if (!contentKey && ExecutionEnvironment_1.canUseDOM) {
- // Prefer textContent to innerText because many browsers support both but
- // SVG <text> elements don't support innerText even when <div> does.
- contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';
- }
- return contentKey;
-}
-
-var getTextContentAccessor_1 = getTextContentAccessor;
-
-/**
- * While `isCollapsed` is available on the Selection object and `collapsed`
- * is available on the Range object, IE11 sometimes gets them wrong.
- * If the anchor/focus nodes and offsets are the same, the range is collapsed.
- */
-function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {
- return anchorNode === focusNode && anchorOffset === focusOffset;
-}
-
-/**
- * @param {DOMElement} node
- * @return {?object}
- */
-function getModernOffsets(node) {
- var selection = window.getSelection && window.getSelection();
-
- if (!selection || selection.rangeCount === 0) {
- return null;
- }
-
- var anchorNode = selection.anchorNode;
- var anchorOffset = selection.anchorOffset;
- var focusNode = selection.focusNode;
- var focusOffset = selection.focusOffset;
-
- var currentRange = selection.getRangeAt(0);
-
- // In Firefox, range.startContainer and range.endContainer can be "anonymous
- // divs", e.g. the up/down buttons on an <input type="number">. Anonymous
- // divs do not seem to expose properties, triggering a "Permission denied
- // error" if any of its properties are accessed. The only seemingly possible
- // way to avoid erroring is to access a property that typically works for
- // non-anonymous divs and catch any error that may otherwise arise. See
- // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
- try {
- /* eslint-disable no-unused-expressions */
- currentRange.startContainer.nodeType;
- currentRange.endContainer.nodeType;
- /* eslint-enable no-unused-expressions */
- } catch (e) {
- return null;
- }
+var ReactFiberReconciler$2 = Object.freeze({
+ default: ReactFiberReconciler$1
+});
- // If the node and offset values are the same, the selection is collapsed.
- // `Selection.isCollapsed` is available natively, but IE sometimes gets
- // this value wrong.
- var isSelectionCollapsed = isCollapsed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset);
+var ReactFiberReconciler$3 = ( ReactFiberReconciler$2 && ReactFiberReconciler$1 ) || ReactFiberReconciler$2;
- var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;
+// TODO: bundle Flow types with the package.
- var tempRange = currentRange.cloneRange();
- tempRange.selectNodeContents(node);
- tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);
- var isTempRangeCollapsed = isCollapsed(tempRange.startContainer, tempRange.startOffset, tempRange.endContainer, tempRange.endOffset);
- var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;
- var end = start + rangeLength;
+// 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;
- // Detect whether the selection is backward.
- var detectionRange = document.createRange();
- detectionRange.setStart(anchorNode, anchorOffset);
- detectionRange.setEnd(focusNode, focusOffset);
- var isBackward = detectionRange.collapsed;
+function createPortal$1(children, containerInfo,
+// TODO: figure out the API for cross-renderer implementation.
+implementation) {
+ var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
return {
- start: isBackward ? end : start,
- end: isBackward ? start : end
+ // 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
};
}
-/**
- * In modern non-IE browsers, we can support both forward and backward
- * selections.
- *
- * Note: IE10+ supports the Selection object, but it does not support
- * the `extend` method, which means that even in modern IE, it's not possible
- * to programmatically create a backward selection. Thus, for all IE
- * versions, we use the old IE API to create our selections.
- *
- * @param {DOMElement|DOMTextNode} node
- * @param {object} offsets
- */
-function setModernOffsets(node, offsets) {
- if (!window.getSelection) {
- return;
- }
+// TODO: this is special because it gets imported during build.
- var selection = window.getSelection();
- var length = node[getTextContentAccessor_1()].length;
- var start = Math.min(offsets.start, length);
- var end = offsets.end === undefined ? start : Math.min(offsets.end, length);
+var ReactVersion = '16.2.0';
- // IE 11 uses modern selection, but doesn't support the extend method.
- // Flip backward selections, so we can set with a single range.
- if (!selection.extend && start > end) {
- var temp = end;
- end = start;
- start = temp;
- }
-
- var startMarker = getNodeForCharacterOffset_1(node, start);
- var endMarker = getNodeForCharacterOffset_1(node, end);
-
- if (startMarker && endMarker) {
- var range = document.createRange();
- range.setStart(startMarker.node, startMarker.offset);
- selection.removeAllRanges();
+// a requestAnimationFrame, storing the time for the start of the frame, then
+// scheduling a postMessage which gets scheduled after paint. Within the
+// postMessage handler do as much work as possible until time + frame rate.
+// By separating the idle call into a separate event tick we ensure that
+// layout, paint and other browser work is counted against the available time.
+// The frame rate is dynamically adjusted.
- if (start > end) {
- selection.addRange(range);
- selection.extend(endMarker.node, endMarker.offset);
- } else {
- range.setEnd(endMarker.node, endMarker.offset);
- selection.addRange(range);
- }
+{
+ if (ExecutionEnvironment_1.canUseDOM && typeof requestAnimationFrame !== 'function') {
+ warning_1(false, 'React depends on requestAnimationFrame. Make sure that you load a ' + 'polyfill in older browsers. http://fb.me/react-polyfills');
}
}
-var ReactDOMSelection = {
- /**
- * @param {DOMElement} node
- */
- getOffsets: getModernOffsets,
-
- /**
- * @param {DOMElement|DOMTextNode} node
- * @param {object} offsets
- */
- setOffsets: setModernOffsets
-};
-
-var ReactDOMSelection_1 = ReactDOMSelection;
-
-/**
- * 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.
- *
- * @typechecks
- */
-
-/**
- * @param {*} object The object to check.
- * @return {boolean} Whether or not the object is a DOM node.
- */
-function isNode(object) {
- var doc = object ? object.ownerDocument || object : document;
- var defaultView = doc.defaultView || window;
- return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
-}
-
-var isNode_1 = isNode;
+var hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function';
-/**
- * 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.
- *
- * @typechecks
- */
-
-
-
-/**
- * @param {*} object The object to check.
- * @return {boolean} Whether or not the object is a DOM text node.
- */
-function isTextNode(object) {
- return isNode_1(object) && object.nodeType == 3;
+var now = void 0;
+if (hasNativePerformanceNow) {
+ now = function () {
+ return performance.now();
+ };
+} else {
+ now = function () {
+ return Date.now();
+ };
}
-var isTextNode_1 = isTextNode;
+// TODO: There's no way to cancel, because Fiber doesn't atm.
+var rIC = void 0;
+var cIC = void 0;
-/**
- * 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.
- *
- *
- */
+if (!ExecutionEnvironment_1.canUseDOM) {
+ rIC = function (frameCallback) {
+ return setTimeout(function () {
+ frameCallback({
+ timeRemaining: function () {
+ return Infinity;
+ }
+ });
+ });
+ };
+ cIC = function (timeoutID) {
+ clearTimeout(timeoutID);
+ };
+} else if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') {
+ // Polyfill requestIdleCallback and cancelIdleCallback
+ var scheduledRICCallback = null;
+ var isIdleScheduled = false;
+ var timeoutTime = -1;
+ var isAnimationFrameScheduled = false;
-/*eslint-disable no-bitwise */
+ var frameDeadline = 0;
+ // We start out assuming that we run at 30fps but then the heuristic tracking
+ // will adjust this value to a faster fps if we get more frequent animation
+ // frames.
+ var previousFrameTime = 33;
+ var activeFrameTime = 33;
-/**
- * Checks if a given DOM node contains or is another DOM node.
- */
-function containsNode(outerNode, innerNode) {
- if (!outerNode || !innerNode) {
- return false;
- } else if (outerNode === innerNode) {
- return true;
- } else if (isTextNode_1(outerNode)) {
- return false;
- } else if (isTextNode_1(innerNode)) {
- return containsNode(outerNode, innerNode.parentNode);
- } else if ('contains' in outerNode) {
- return outerNode.contains(innerNode);
- } else if (outerNode.compareDocumentPosition) {
- return !!(outerNode.compareDocumentPosition(innerNode) & 16);
+ var frameDeadlineObject;
+ if (hasNativePerformanceNow) {
+ frameDeadlineObject = {
+ didTimeout: false,
+ timeRemaining: function () {
+ // We assume that if we have a performance timer that the rAF callback
+ // gets a performance timer value. Not sure if this is always true.
+ var remaining = frameDeadline - performance.now();
+ return remaining > 0 ? remaining : 0;
+ }
+ };
} else {
- return false;
- }
-}
-
-var containsNode_1 = containsNode;
-
-/**
- * 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.
- *
- */
-
-/**
- * @param {DOMElement} node input/textarea to focus
- */
-
-function focusNode(node) {
- // IE8 can throw "Can't move focus to the control because it is invisible,
- // not enabled, or of a type that does not accept the focus." for all kinds of
- // reasons that are too expensive and fragile to test.
- try {
- node.focus();
- } catch (e) {}
-}
-
-var focusNode_1 = focusNode;
-
-/**
- * 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.
- *
- * @typechecks
- */
-
-/* eslint-disable fb-www/typeof-undefined */
-
-/**
- * Same as document.activeElement but wraps in a try-catch block. In IE it is
- * not safe to call document.activeElement if there is nothing focused.
- *
- * The activeElement will be null only if the document or document body is not
- * yet defined.
- *
- * @param {?DOMDocument} doc Defaults to current document.
- * @return {?DOMElement}
- */
-function getActiveElement(doc) /*?DOMElement*/{
- doc = doc || (typeof document !== 'undefined' ? document : undefined);
- if (typeof doc === 'undefined') {
- return null;
- }
- try {
- return doc.activeElement || doc.body;
- } catch (e) {
- return doc.body;
+ frameDeadlineObject = {
+ didTimeout: false,
+ timeRemaining: function () {
+ // Fallback to Date.now()
+ var remaining = frameDeadline - Date.now();
+ return remaining > 0 ? remaining : 0;
+ }
+ };
}
-}
-
-var getActiveElement_1 = getActiveElement;
-
-var ELEMENT_NODE$2 = HTMLNodeType_1.ELEMENT_NODE;
-
-
-
-
-
-function isInDocument(node) {
- return containsNode_1(document.documentElement, node);
-}
-/**
- * @ReactInputSelection: React input selection module. Based on Selection.js,
- * but modified to be suitable for react and has a couple of bug fixes (doesn't
- * assume buttons have range selections allowed).
- * Input selection module for React.
- */
-var ReactInputSelection = {
- hasSelectionCapabilities: function (elem) {
- var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
- return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');
- },
+ // We use the postMessage trick to defer idle work until after the repaint.
+ var messageKey = '__reactIdleCallback$' + Math.random().toString(36).slice(2);
+ var idleTick = function (event) {
+ if (event.source !== window || event.data !== messageKey) {
+ return;
+ }
- getSelectionInformation: function () {
- var focusedElem = getActiveElement_1();
- return {
- focusedElem: focusedElem,
- selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null
- };
- },
+ isIdleScheduled = false;
- /**
- * @restoreSelection: If any selection information was potentially lost,
- * restore it. This is useful when performing operations that could remove dom
- * nodes and place them back in, resulting in focus being lost.
- */
- restoreSelection: function (priorSelectionInformation) {
- var curFocusedElem = getActiveElement_1();
- var priorFocusedElem = priorSelectionInformation.focusedElem;
- var priorSelectionRange = priorSelectionInformation.selectionRange;
- if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
- if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
- ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);
- }
-
- // Focusing a node can change the scroll position, which is undesirable
- var ancestors = [];
- var ancestor = priorFocusedElem;
- while (ancestor = ancestor.parentNode) {
- if (ancestor.nodeType === ELEMENT_NODE$2) {
- ancestors.push({
- element: ancestor,
- left: ancestor.scrollLeft,
- top: ancestor.scrollTop
- });
+ var currentTime = now();
+ if (frameDeadline - currentTime <= 0) {
+ // There's no time left in this idle period. Check if the callback has
+ // a timeout and whether it's been exceeded.
+ if (timeoutTime !== -1 && timeoutTime <= currentTime) {
+ // Exceeded the timeout. Invoke the callback even though there's no
+ // time left.
+ frameDeadlineObject.didTimeout = true;
+ } else {
+ // No timeout.
+ if (!isAnimationFrameScheduled) {
+ // Schedule another animation callback so we retry later.
+ isAnimationFrameScheduled = true;
+ requestAnimationFrame(animationTick);
}
+ // Exit without invoking the callback.
+ return;
}
-
- focusNode_1(priorFocusedElem);
-
- for (var i = 0; i < ancestors.length; i++) {
- var info = ancestors[i];
- info.element.scrollLeft = info.left;
- info.element.scrollTop = info.top;
- }
- }
- },
-
- /**
- * @getSelection: Gets the selection bounds of a focused textarea, input or
- * contentEditable node.
- * -@input: Look up selection bounds of this input
- * -@return {start: selectionStart, end: selectionEnd}
- */
- getSelection: function (input) {
- var selection;
-
- if ('selectionStart' in input) {
- // Modern browser with input or textarea.
- selection = {
- start: input.selectionStart,
- end: input.selectionEnd
- };
} else {
- // Content editable or old IE textarea.
- selection = ReactDOMSelection_1.getOffsets(input);
+ // There's still time left in this idle period.
+ frameDeadlineObject.didTimeout = false;
}
- return selection || { start: 0, end: 0 };
- },
-
- /**
- * @setSelection: Sets the selection bounds of a textarea or input and focuses
- * the input.
- * -@input Set selection bounds of this input or textarea
- * -@offsets Object of same form that is returned from get*
- */
- setSelection: function (input, offsets) {
- var start = offsets.start;
- var end = offsets.end;
- if (end === undefined) {
- end = start;
+ timeoutTime = -1;
+ var callback = scheduledRICCallback;
+ scheduledRICCallback = null;
+ if (callback !== null) {
+ callback(frameDeadlineObject);
}
+ };
+ // Assumes that we have addEventListener in this environment. Might need
+ // something better for old IE.
+ window.addEventListener('message', idleTick, false);
- if ('selectionStart' in input) {
- input.selectionStart = start;
- input.selectionEnd = Math.min(end, input.value.length);
+ var animationTick = function (rafTime) {
+ isAnimationFrameScheduled = false;
+ var nextFrameTime = rafTime - frameDeadline + activeFrameTime;
+ if (nextFrameTime < activeFrameTime && previousFrameTime < activeFrameTime) {
+ if (nextFrameTime < 8) {
+ // Defensive coding. We don't support higher frame rates than 120hz.
+ // If we get lower than that, it is probably a bug.
+ nextFrameTime = 8;
+ }
+ // If one frame goes long, then the next one can be short to catch up.
+ // If two frames are short in a row, then that's an indication that we
+ // actually have a higher frame rate than what we're currently optimizing.
+ // We adjust our heuristic dynamically accordingly. For example, if we're
+ // running on 120hz display or 90hz VR display.
+ // Take the max of the two in case one of them was an anomaly due to
+ // missed frame deadlines.
+ activeFrameTime = nextFrameTime < previousFrameTime ? previousFrameTime : nextFrameTime;
} else {
- ReactDOMSelection_1.setOffsets(input, offsets);
+ previousFrameTime = nextFrameTime;
}
- }
-};
-
-var ReactInputSelection_1 = ReactInputSelection;
-
-/**
- * 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.
- *
- * @providesModule ReactVersion
- */
-
-var ReactVersion = '16.0.0';
-
-/**
- * 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.
- *
- * @providesModule findDOMNode
- *
- */
-
-
-
-var ELEMENT_NODE$3 = HTMLNodeType_1.ELEMENT_NODE;
-
-var ReactCurrentOwner$3 = ReactGlobalSharedState_1.ReactCurrentOwner;
-
-
-
-
-{
- var warning$29 = warning_1;
-}
-
-var findFiber = function (arg) {
- invariant_1(false, 'Missing injection for fiber findDOMNode');
-};
-var findStack = function (arg) {
- invariant_1(false, 'Missing injection for stack findDOMNode');
-};
-
-var findDOMNode = function (componentOrElement) {
- {
- var owner = ReactCurrentOwner$3.current;
- if (owner !== null) {
- var isFiber = typeof owner.tag === 'number';
- var warnedAboutRefsInRender = isFiber ? owner.stateNode._warnedAboutRefsInRender : owner._warnedAboutRefsInRender;
- warning$29(warnedAboutRefsInRender, '%s is accessing findDOMNode 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_1(owner) || 'A component');
- if (isFiber) {
- owner.stateNode._warnedAboutRefsInRender = true;
- } else {
- owner._warnedAboutRefsInRender = true;
- }
+ frameDeadline = rafTime + activeFrameTime;
+ if (!isIdleScheduled) {
+ isIdleScheduled = true;
+ window.postMessage(messageKey, '*');
}
- }
- if (componentOrElement == null) {
- return null;
- }
- if (componentOrElement.nodeType === ELEMENT_NODE$3) {
- return componentOrElement;
- }
+ };
- var inst = ReactInstanceMap_1.get(componentOrElement);
- if (inst) {
- if (typeof inst.tag === 'number') {
- return findFiber(inst);
- } else {
- return findStack(inst);
+ rIC = function (callback, options) {
+ // This assumes that we only schedule one callback at a time because that's
+ // how Fiber uses it.
+ scheduledRICCallback = callback;
+ if (options != null && typeof options.timeout === 'number') {
+ timeoutTime = now() + options.timeout;
}
- }
-
- if (typeof componentOrElement.render === 'function') {
- invariant_1(false, 'Unable to find node on an unmounted component.');
- } else {
- invariant_1(false, 'Element appears to be neither ReactComponent nor DOMNode. Keys: %s', Object.keys(componentOrElement));
- }
-};
-
-findDOMNode._injectFiber = function (fn) {
- findFiber = fn;
-};
-findDOMNode._injectStack = function (fn) {
- findStack = fn;
-};
-
-var findDOMNode_1 = findDOMNode;
+ if (!isAnimationFrameScheduled) {
+ // If rAF didn't already schedule one, we need to schedule a frame.
+ // TODO: If this rAF doesn't materialize because the browser throttles, we
+ // might want to still have setTimeout trigger rIC as a backup to ensure
+ // that we keep performing work.
+ isAnimationFrameScheduled = true;
+ requestAnimationFrame(animationTick);
+ }
+ return 0;
+ };
-/**
- * Copyright (c) 2014-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.
- *
- * @providesModule lowPriorityWarning
- */
+ cIC = function () {
+ scheduledRICCallback = null;
+ isIdleScheduled = false;
+ timeoutTime = -1;
+ };
+} else {
+ rIC = window.requestIdleCallback;
+ cIC = window.cancelIdleCallback;
+}
/**
* Forked from fbjs/warning:
@@ -15112,7 +12050,7 @@ var findDOMNode_1 = findDOMNode;
* same logic and follow the same code paths.
*/
-var lowPriorityWarning$1 = function () {};
+var lowPriorityWarning = function () {};
{
var printWarning$1 = function (format) {
@@ -15135,7 +12073,7 @@ var lowPriorityWarning$1 = function () {};
} catch (x) {}
};
- lowPriorityWarning$1 = function (condition, format) {
+ lowPriorityWarning = function (condition, format) {
if (format === undefined) {
throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
}
@@ -15149,1398 +12087,1141 @@ var lowPriorityWarning$1 = function () {};
};
}
-var lowPriorityWarning_1 = lowPriorityWarning$1;
-
-var validateDOMNesting$1 = emptyFunction_1;
+var lowPriorityWarning$1 = lowPriorityWarning;
-{
- var warning$30 = warning_1;
-
- var _require$13 = ReactDebugCurrentFiber_1,
- getCurrentFiberStackAddendum$6 = _require$13.getCurrentFiberStackAddendum;
-
- // This validation code was written based on the HTML5 parsing spec:
- // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
- //
- // Note: this does not catch all invalid nesting, nor does it try to (as it's
- // not clear what practical benefit doing so provides); instead, we warn only
- // for cases where the parser will give a parse tree differing from what React
- // intended. For example, <b><div></div></b> is invalid but we don't warn
- // because it still parses correctly; we do warn for other cases like nested
- // <p> tags where the beginning of the second element implicitly closes the
- // first, causing a confusing mess.
-
- // https://html.spec.whatwg.org/multipage/syntax.html#special
+// isAttributeNameSafe() is currently duplicated in DOMMarkupOperations.
+// TODO: Find a better place for this.
+var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$');
+var illegalAttributeNameCache = {};
+var validatedAttributeNameCache = {};
+function isAttributeNameSafe(attributeName) {
+ if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
+ return true;
+ }
+ if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
+ return false;
+ }
+ if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
+ validatedAttributeNameCache[attributeName] = true;
+ return true;
+ }
+ illegalAttributeNameCache[attributeName] = true;
+ {
+ warning_1(false, 'Invalid attribute name: `%s`', attributeName);
+ }
+ return false;
+}
+// shouldIgnoreValue() is currently duplicated in DOMMarkupOperations.
+// TODO: Find a better place for this.
+function shouldIgnoreValue(propertyInfo, value) {
+ return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;
+}
- var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];
+/**
+ * Operations for dealing with DOM properties.
+ */
- // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
- var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
- // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
- // TODO: Distinguish by namespace here -- for <title>, including it here
- // errs on the side of fewer warnings
- 'foreignObject', 'desc', 'title'];
- // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
- var buttonScopeTags = inScopeTags.concat(['button']);
- // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
- var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
- var emptyAncestorInfo = {
- current: null,
+/**
+ * Get the value for a property on a node. Only used in DEV for SSR validation.
+ * The "expected" argument is used as a hint of what the expected value is.
+ * Some properties have multiple equivalent values.
+ */
+function getValueForProperty(node, name, expected) {
+ {
+ var propertyInfo = getPropertyInfo(name);
+ if (propertyInfo) {
+ var mutationMethod = propertyInfo.mutationMethod;
+ if (mutationMethod || propertyInfo.mustUseProperty) {
+ return node[propertyInfo.propertyName];
+ } else {
+ var attributeName = propertyInfo.attributeName;
- formTag: null,
- aTagInScope: null,
- buttonTagInScope: null,
- nobrTagInScope: null,
- pTagInButtonScope: null,
+ var stringValue = null;
- listItemTagAutoclosing: null,
- dlItemTagAutoclosing: null
- };
+ if (propertyInfo.hasOverloadedBooleanValue) {
+ if (node.hasAttribute(attributeName)) {
+ var value = node.getAttribute(attributeName);
+ if (value === '') {
+ return true;
+ }
+ if (shouldIgnoreValue(propertyInfo, expected)) {
+ return value;
+ }
+ if (value === '' + expected) {
+ return expected;
+ }
+ return value;
+ }
+ } else if (node.hasAttribute(attributeName)) {
+ if (shouldIgnoreValue(propertyInfo, expected)) {
+ // We had an attribute but shouldn't have had one, so read it
+ // for the error message.
+ return node.getAttribute(attributeName);
+ }
+ if (propertyInfo.hasBooleanValue) {
+ // If this was a boolean, it doesn't matter what the value is
+ // the fact that we have it is the same as the expected.
+ return expected;
+ }
+ // Even if this property uses a namespace we use getAttribute
+ // because we assume its namespaced name is the same as our config.
+ // To use getAttributeNS we need the local name which we don't have
+ // in our config atm.
+ stringValue = node.getAttribute(attributeName);
+ }
- var updatedAncestorInfo$1 = function (oldInfo, tag, instance) {
- var ancestorInfo = assign({}, oldInfo || emptyAncestorInfo);
- var info = { tag: tag, instance: instance };
+ if (shouldIgnoreValue(propertyInfo, expected)) {
+ return stringValue === null ? expected : stringValue;
+ } else if (stringValue === '' + expected) {
+ return expected;
+ } else {
+ return stringValue;
+ }
+ }
+ }
+ }
+}
- if (inScopeTags.indexOf(tag) !== -1) {
- ancestorInfo.aTagInScope = null;
- ancestorInfo.buttonTagInScope = null;
- ancestorInfo.nobrTagInScope = null;
+/**
+ * Get the value for a attribute on a node. Only used in DEV for SSR validation.
+ * The third argument is used as a hint of what the expected value is. Some
+ * attributes have multiple equivalent values.
+ */
+function getValueForAttribute(node, name, expected) {
+ {
+ if (!isAttributeNameSafe(name)) {
+ return;
}
- if (buttonScopeTags.indexOf(tag) !== -1) {
- ancestorInfo.pTagInButtonScope = null;
+ if (!node.hasAttribute(name)) {
+ return expected === undefined ? undefined : null;
+ }
+ var value = node.getAttribute(name);
+ if (value === '' + expected) {
+ return expected;
}
+ return value;
+ }
+}
- // See rules for 'li', 'dd', 'dt' start tags in
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
- if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
- ancestorInfo.listItemTagAutoclosing = null;
- ancestorInfo.dlItemTagAutoclosing = null;
+/**
+ * Sets the value for a property on a node.
+ *
+ * @param {DOMElement} node
+ * @param {string} name
+ * @param {*} value
+ */
+function setValueForProperty(node, name, value) {
+ var propertyInfo = getPropertyInfo(name);
+
+ if (propertyInfo && shouldSetAttribute(name, value)) {
+ var mutationMethod = propertyInfo.mutationMethod;
+ if (mutationMethod) {
+ mutationMethod(node, value);
+ } else if (shouldIgnoreValue(propertyInfo, value)) {
+ deleteValueForProperty(node, name);
+ return;
+ } else if (propertyInfo.mustUseProperty) {
+ // Contrary to `setAttribute`, object properties are properly
+ // `toString`ed by IE8/9.
+ node[propertyInfo.propertyName] = value;
+ } else {
+ var attributeName = propertyInfo.attributeName;
+ var namespace = propertyInfo.attributeNamespace;
+ // `setAttribute` with objects becomes only `[object]` in IE8/9,
+ // ('' + value) makes it output the correct toString()-value.
+ if (namespace) {
+ node.setAttributeNS(namespace, attributeName, '' + value);
+ } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
+ node.setAttribute(attributeName, '');
+ } else {
+ node.setAttribute(attributeName, '' + value);
+ }
}
+ } else {
+ setValueForAttribute(node, name, shouldSetAttribute(name, value) ? value : null);
+ return;
+ }
- ancestorInfo.current = info;
+ {
+
+ }
+}
- if (tag === 'form') {
- ancestorInfo.formTag = info;
- }
- if (tag === 'a') {
- ancestorInfo.aTagInScope = info;
- }
- if (tag === 'button') {
- ancestorInfo.buttonTagInScope = info;
- }
- if (tag === 'nobr') {
- ancestorInfo.nobrTagInScope = info;
- }
- if (tag === 'p') {
- ancestorInfo.pTagInButtonScope = info;
- }
- if (tag === 'li') {
- ancestorInfo.listItemTagAutoclosing = info;
- }
- if (tag === 'dd' || tag === 'dt') {
- ancestorInfo.dlItemTagAutoclosing = info;
- }
+function setValueForAttribute(node, name, value) {
+ if (!isAttributeNameSafe(name)) {
+ return;
+ }
+ if (value == null) {
+ node.removeAttribute(name);
+ } else {
+ node.setAttribute(name, '' + value);
+ }
- return ancestorInfo;
- };
+ {
+
+ }
+}
- /**
- * Returns whether
- */
- var isTagValidWithParent = function (tag, parentTag) {
- // First, let's check if we're in an unusual parsing mode...
- switch (parentTag) {
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
- case 'select':
- return tag === 'option' || tag === 'optgroup' || tag === '#text';
- case 'optgroup':
- return tag === 'option' || tag === '#text';
- // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
- // but
- case 'option':
- return tag === '#text';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
- // No special behavior since these rules fall back to "in body" mode for
- // all except special table nodes which cause bad parsing behavior anyway.
+/**
+ * Deletes an attributes from a node.
+ *
+ * @param {DOMElement} node
+ * @param {string} name
+ */
+function deleteValueForAttribute(node, name) {
+ node.removeAttribute(name);
+}
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
- case 'tr':
- return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
- case 'tbody':
- case 'thead':
- case 'tfoot':
- return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
- case 'colgroup':
- return tag === 'col' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
- case 'table':
- return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
- case 'head':
- return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
- // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
- case 'html':
- return tag === 'head' || tag === 'body';
- case '#document':
- return tag === 'html';
+/**
+ * Deletes the value for a property on a node.
+ *
+ * @param {DOMElement} node
+ * @param {string} name
+ */
+function deleteValueForProperty(node, name) {
+ var propertyInfo = getPropertyInfo(name);
+ if (propertyInfo) {
+ var mutationMethod = propertyInfo.mutationMethod;
+ if (mutationMethod) {
+ mutationMethod(node, undefined);
+ } else if (propertyInfo.mustUseProperty) {
+ var propName = propertyInfo.propertyName;
+ if (propertyInfo.hasBooleanValue) {
+ node[propName] = false;
+ } else {
+ node[propName] = '';
+ }
+ } else {
+ node.removeAttribute(propertyInfo.attributeName);
}
+ } else {
+ node.removeAttribute(name);
+ }
+}
- // Probably in the "in body" parsing mode, so we outlaw only tag combos
- // where the parsing rules cause implicit opens or closes to be added.
- // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
- switch (tag) {
- case 'h1':
- case 'h2':
- case 'h3':
- case 'h4':
- case 'h5':
- case 'h6':
- return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
+var ReactControlledValuePropTypes = {
+ checkPropTypes: null
+};
- case 'rp':
- case 'rt':
- return impliedEndTags.indexOf(parentTag) === -1;
+{
+ var hasReadOnlyValue = {
+ button: true,
+ checkbox: true,
+ image: true,
+ hidden: true,
+ radio: true,
+ reset: true,
+ submit: true
+ };
- case 'body':
- case 'caption':
- case 'col':
- case 'colgroup':
- case 'frame':
- case 'head':
- case 'html':
- case 'tbody':
- case 'td':
- case 'tfoot':
- case 'th':
- case 'thead':
- case 'tr':
- // These tags are only valid with a few parents that have special child
- // parsing rules -- if we're down here, then none of those matched and
- // so we allow it only if we don't know what the parent is, as all other
- // cases are invalid.
- return parentTag == null;
+ var propTypes = {
+ value: function (props, propName, componentName) {
+ if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {
+ return null;
+ }
+ return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
+ },
+ checked: function (props, propName, componentName) {
+ if (!props[propName] || props.onChange || props.readOnly || props.disabled) {
+ return null;
+ }
+ return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
}
-
- return true;
};
/**
- * Returns whether
+ * Provide a linked `value` attribute for controlled forms. You should not use
+ * this outside of the ReactDOM controlled form components.
*/
- var findInvalidAncestorForTag = function (tag, ancestorInfo) {
- switch (tag) {
- case 'address':
- case 'article':
- case 'aside':
- case 'blockquote':
- case 'center':
- case 'details':
- case 'dialog':
- case 'dir':
- case 'div':
- case 'dl':
- case 'fieldset':
- case 'figcaption':
- case 'figure':
- case 'footer':
- case 'header':
- case 'hgroup':
- case 'main':
- case 'menu':
- case 'nav':
- case 'ol':
- case 'p':
- case 'section':
- case 'summary':
- case 'ul':
- case 'pre':
- case 'listing':
- case 'table':
- case 'hr':
- case 'xmp':
- case 'h1':
- case 'h2':
- case 'h3':
- case 'h4':
- case 'h5':
- case 'h6':
- return ancestorInfo.pTagInButtonScope;
+ ReactControlledValuePropTypes.checkPropTypes = function (tagName, props, getStack) {
+ checkPropTypes_1(propTypes, props, 'prop', tagName, getStack);
+ };
+}
- case 'form':
- return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+var getCurrentFiberOwnerName$2 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
+var getCurrentFiberStackAddendum$3 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
- case 'li':
- return ancestorInfo.listItemTagAutoclosing;
+var didWarnValueDefaultValue = false;
+var didWarnCheckedDefaultChecked = false;
+var didWarnControlledToUncontrolled = false;
+var didWarnUncontrolledToControlled = false;
- case 'dd':
- case 'dt':
- return ancestorInfo.dlItemTagAutoclosing;
+function isControlled(props) {
+ var usesChecked = props.type === 'checkbox' || props.type === 'radio';
+ return usesChecked ? props.checked != null : props.value != null;
+}
- case 'button':
- return ancestorInfo.buttonTagInScope;
+/**
+ * Implements an <input> host component that allows setting these optional
+ * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
+ *
+ * If `checked` or `value` are not supplied (or null/undefined), user actions
+ * that affect the checked state or value will trigger updates to the element.
+ *
+ * If they are supplied (and not null/undefined), the rendered element will not
+ * trigger updates to the element. Instead, the props must change in order for
+ * the rendered element to be updated.
+ *
+ * The rendered element will be initialized as unchecked (or `defaultChecked`)
+ * with an empty value (or `defaultValue`).
+ *
+ * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
+ */
- case 'a':
- // Spec says something about storing a list of markers, but it sounds
- // equivalent to this check.
- return ancestorInfo.aTagInScope;
+function getHostProps(element, props) {
+ var node = element;
+ var value = props.value;
+ var checked = props.checked;
+
+ var hostProps = _assign({
+ // Make sure we set .type before any other properties (setting .value
+ // before .type means .value is lost in IE11 and below)
+ type: undefined,
+ // Make sure we set .step before .value (setting .value before .step
+ // means .value is rounded on mount, based upon step precision)
+ step: undefined,
+ // Make sure we set .min & .max before .value (to ensure proper order
+ // in corner cases such as min or max deriving from value, e.g. Issue #7170)
+ min: undefined,
+ max: undefined
+ }, props, {
+ defaultChecked: undefined,
+ defaultValue: undefined,
+ value: value != null ? value : node._wrapperState.initialValue,
+ checked: checked != null ? checked : node._wrapperState.initialChecked
+ });
- case 'nobr':
- return ancestorInfo.nobrTagInScope;
- }
+ return hostProps;
+}
- return null;
- };
+function initWrapperState(element, props) {
+ {
+ ReactControlledValuePropTypes.checkPropTypes('input', props, getCurrentFiberStackAddendum$3);
- /**
- * Given a ReactCompositeComponent instance, return a list of its recursive
- * owners, starting at the root and ending with the instance itself.
- */
- var findOwnerStack = function (instance) {
- if (!instance) {
- return [];
+ if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
+ warning_1(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', getCurrentFiberOwnerName$2() || 'A component', props.type);
+ didWarnCheckedDefaultChecked = true;
}
-
- var stack = [];
- do {
- stack.push(instance);
- } while (instance = instance._currentElement._owner);
- stack.reverse();
- return stack;
- };
-
- var getOwnerInfo = function (childInstance, childTag, ancestorInstance, ancestorTag, isParent) {
- var childOwner = childInstance && childInstance._currentElement._owner;
- var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;
-
- var childOwners = findOwnerStack(childOwner);
- var ancestorOwners = findOwnerStack(ancestorOwner);
-
- var minStackLen = Math.min(childOwners.length, ancestorOwners.length);
- var i;
-
- var deepestCommon = -1;
- for (i = 0; i < minStackLen; i++) {
- if (childOwners[i] === ancestorOwners[i]) {
- deepestCommon = i;
- } else {
- break;
- }
+ if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
+ warning_1(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', getCurrentFiberOwnerName$2() || 'A component', props.type);
+ didWarnValueDefaultValue = true;
}
+ }
- var UNKNOWN = '(unknown)';
- var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {
- return getComponentName_1(inst) || UNKNOWN;
- });
- var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {
- return getComponentName_1(inst) || UNKNOWN;
- });
- var ownerInfo = [].concat(
- // If the parent and child instances have a common owner ancestor, start
- // with that -- otherwise we just start with the parent's owners.
- deepestCommon !== -1 ? getComponentName_1(childOwners[deepestCommon]) || UNKNOWN : [], ancestorOwnerNames, ancestorTag,
- // If we're warning about an invalid (non-parent) ancestry, add '...'
- isParent ? [] : ['...'], childOwnerNames, childTag).join(' > ');
-
- return ownerInfo;
+ var defaultValue = props.defaultValue;
+ var node = element;
+ node._wrapperState = {
+ initialChecked: props.checked != null ? props.checked : props.defaultChecked,
+ initialValue: props.value != null ? props.value : defaultValue,
+ controlled: isControlled(props)
};
+}
- var didWarn = {};
+function updateChecked(element, props) {
+ var node = element;
+ var checked = props.checked;
+ if (checked != null) {
+ setValueForProperty(node, 'checked', checked);
+ }
+}
- validateDOMNesting$1 = function (childTag, childText, childInstance, ancestorInfo) {
- ancestorInfo = ancestorInfo || emptyAncestorInfo;
- var parentInfo = ancestorInfo.current;
- var parentTag = parentInfo && parentInfo.tag;
+function updateWrapper(element, props) {
+ var node = element;
+ {
+ var controlled = isControlled(props);
- if (childText != null) {
- warning$30(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null');
- childTag = '#text';
+ if (!node._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
+ warning_1(false, 'A component is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components%s', props.type, getCurrentFiberStackAddendum$3());
+ didWarnUncontrolledToControlled = true;
}
-
- var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
- var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
- var invalidParentOrAncestor = invalidParent || invalidAncestor;
- if (!invalidParentOrAncestor) {
- return;
+ if (node._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
+ warning_1(false, 'A component is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components%s', props.type, getCurrentFiberStackAddendum$3());
+ didWarnControlledToUncontrolled = true;
}
+ }
- var ancestorInstance = invalidParentOrAncestor.instance;
- var ancestorTag = invalidParentOrAncestor.tag;
- var addendum;
-
- if (childInstance != null) {
- addendum = ' See ' + getOwnerInfo(childInstance, childTag, ancestorInstance, ancestorTag, !!invalidParent) + '.';
- } else {
- addendum = getCurrentFiberStackAddendum$6();
- }
+ updateChecked(element, props);
- var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + addendum;
- if (didWarn[warnKey]) {
- return;
- }
- didWarn[warnKey] = true;
+ var value = props.value;
+ if (value != null) {
+ if (value === 0 && node.value === '') {
+ node.value = '0';
+ // Note: IE9 reports a number inputs as 'text', so check props instead.
+ } else if (props.type === 'number') {
+ // Simulate `input.valueAsNumber`. IE9 does not support it
+ var valueAsNumber = parseFloat(node.value) || 0;
- var tagDisplayName = childTag;
- var whitespaceInfo = '';
- if (childTag === '#text') {
- if (/\S/.test(childText)) {
- tagDisplayName = 'Text nodes';
- } else {
- tagDisplayName = 'Whitespace text nodes';
- whitespaceInfo = " Make sure you don't have any extra whitespace between tags on " + 'each line of your source code.';
+ if (
+ // eslint-disable-next-line
+ value != valueAsNumber ||
+ // eslint-disable-next-line
+ value == valueAsNumber && node.value != value) {
+ // Cast `value` to a string to ensure the value is set correctly. While
+ // browsers typically do this as necessary, jsdom doesn't.
+ node.value = '' + value;
}
- } else {
- tagDisplayName = '<' + childTag + '>';
+ } else if (node.value !== '' + value) {
+ // Cast `value` to a string to ensure the value is set correctly. While
+ // browsers typically do this as necessary, jsdom doesn't.
+ node.value = '' + value;
}
-
- if (invalidParent) {
- var info = '';
- if (ancestorTag === 'table' && childTag === 'tr') {
- info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
+ } else {
+ if (props.value == null && props.defaultValue != null) {
+ // In Chrome, assigning defaultValue to certain input types triggers input validation.
+ // For number inputs, the display value loses trailing decimal points. For email inputs,
+ // Chrome raises "The specified value <x> is not a valid email address".
+ //
+ // Here we check to see if the defaultValue has actually changed, avoiding these problems
+ // when the user is inputting text
+ //
+ // https://github.com/facebook/react/issues/7253
+ if (node.defaultValue !== '' + props.defaultValue) {
+ node.defaultValue = '' + props.defaultValue;
}
- warning$30(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>.%s%s%s', tagDisplayName, ancestorTag, whitespaceInfo, info, addendum);
- } else {
- warning$30(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>.%s', tagDisplayName, ancestorTag, addendum);
}
- };
-
- validateDOMNesting$1.updatedAncestorInfo = updatedAncestorInfo$1;
-
- // For testing
- validateDOMNesting$1.isTagValidInContext = function (tag, ancestorInfo) {
- ancestorInfo = ancestorInfo || emptyAncestorInfo;
- var parentInfo = ancestorInfo.current;
- var parentTag = parentInfo && parentInfo.tag;
- return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);
- };
+ if (props.checked == null && props.defaultChecked != null) {
+ node.defaultChecked = !!props.defaultChecked;
+ }
+ }
}
-var validateDOMNesting_1 = validateDOMNesting$1;
+function postMountWrapper(element, props) {
+ var node = element;
-var HostComponent$11 = ReactTypeOfWork.HostComponent;
+ // Detach value from defaultValue. We won't do anything if we're working on
+ // submit or reset inputs as those values & defaultValues are linked. They
+ // are not resetable nodes so this operation doesn't matter and actually
+ // removes browser-default values (eg "Submit Query") when no value is
+ // provided.
-function getParent(inst) {
- if (inst._hostParent !== undefined) {
- return inst._hostParent;
- }
- if (typeof inst.tag === 'number') {
- 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$11);
- if (inst) {
- return inst;
- }
+ switch (props.type) {
+ case 'submit':
+ case 'reset':
+ break;
+ case 'color':
+ case 'date':
+ case 'datetime':
+ case 'datetime-local':
+ case 'month':
+ case 'time':
+ case 'week':
+ // This fixes the no-show issue on iOS Safari and Android Chrome:
+ // https://github.com/facebook/react/issues/7233
+ node.value = '';
+ node.value = node.defaultValue;
+ break;
+ default:
+ node.value = node.value;
+ break;
}
- 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++;
+ // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
+ // this is needed to work around a chrome bug where setting defaultChecked
+ // will sometimes influence the value of checked (even after detachment).
+ // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
+ // We need to temporarily unset name to avoid disrupting radio button groups.
+ var name = node.name;
+ if (name !== '') {
+ node.name = '';
}
- var depthB = 0;
- for (var tempB = instB; tempB; tempB = getParent(tempB)) {
- depthB++;
+ node.defaultChecked = !node.defaultChecked;
+ node.defaultChecked = !node.defaultChecked;
+ if (name !== '') {
+ node.name = name;
}
+}
- // If A is deeper, crawl up.
- while (depthA - depthB > 0) {
- instA = getParent(instA);
- depthA--;
- }
+function restoreControlledState$1(element, props) {
+ var node = element;
+ updateWrapper(node, props);
+ updateNamedCousins(node, props);
+}
- // If B is deeper, crawl up.
- while (depthB - depthA > 0) {
- instB = getParent(instB);
- depthB--;
- }
+function updateNamedCousins(rootNode, props) {
+ var name = props.name;
+ if (props.type === 'radio' && name != null) {
+ var queryRoot = rootNode;
- // Walk in lockstep until we find a match.
- var depth = depthA;
- while (depth--) {
- if (instA === instB || instA === instB.alternate) {
- return instA;
+ while (queryRoot.parentNode) {
+ queryRoot = queryRoot.parentNode;
}
- 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;
-}
+ // If `rootNode.form` was non-null, then we could try `form.elements`,
+ // but that sometimes behaves strangely in IE8. We could also try using
+ // `form.getElementsByName`, but that will only return direct children
+ // and won't include inputs that use the HTML5 `form=` attribute. Since
+ // the input might not even be in a form. It might not even be in the
+ // document. Let's just use the local `querySelectorAll` to ensure we don't
+ // miss anything.
+ var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
-/**
- * Return the parent instance of the passed-in instance.
- */
-function getParentInstance(inst) {
- return getParent(inst);
-}
+ for (var i = 0; i < group.length; i++) {
+ var otherNode = group[i];
+ if (otherNode === rootNode || otherNode.form !== rootNode.form) {
+ continue;
+ }
+ // This will throw if radio buttons rendered by different copies of React
+ // and the same name are rendered into the same form (same as #1939).
+ // That's probably okay; we don't support it just as we don't support
+ // mixing React radio buttons with non-React ones.
+ var otherProps = getFiberCurrentPropsFromNode$1(otherNode);
+ !otherProps ? invariant_1(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : void 0;
-/**
- * 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;
- for (i = path.length; i-- > 0;) {
- fn(path[i], 'captured', arg);
- }
- for (i = 0; i < path.length; i++) {
- fn(path[i], 'bubbled', arg);
- }
-}
+ // We need update the tracked value on the named cousin since the value
+ // was changed but the input saw no event or value set
+ updateValueIfChanged(otherNode);
-/**
- * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
- * should would receive a `mouseEnter` or `mouseLeave` event.
- *
- * Does not invoke the callback on the nearest common ancestor because nothing
- * "entered" or "left" that element.
- */
-function traverseEnterLeave(from, to, fn, argFrom, argTo) {
- var common = from && to ? getLowestCommonAncestor(from, to) : null;
- var pathFrom = [];
- while (from && from !== common) {
- pathFrom.push(from);
- from = getParent(from);
- }
- var pathTo = [];
- while (to && to !== common) {
- pathTo.push(to);
- to = getParent(to);
- }
- var i;
- for (i = 0; i < pathFrom.length; i++) {
- fn(pathFrom[i], 'bubbled', argFrom);
- }
- for (i = pathTo.length; i-- > 0;) {
- fn(pathTo[i], 'captured', argTo);
+ // If this is a controlled radio button group, forcing the input that
+ // was previously checked to update will cause it to be come re-checked
+ // as appropriate.
+ updateWrapper(otherNode, otherProps);
+ }
}
}
-var ReactTreeTraversal = {
- isAncestor: isAncestor,
- getLowestCommonAncestor: getLowestCommonAncestor,
- getParentInstance: getParentInstance,
- traverseTwoPhase: traverseTwoPhase,
- traverseEnterLeave: traverseEnterLeave
-};
+function flattenChildren(children) {
+ var content = '';
-var getListener = EventPluginHub_1.getListener;
+ // Flatten children and warn if they aren't strings or numbers;
+ // invalid types are ignored.
+ // We can silently skip them because invalid DOM nesting warning
+ // catches these cases in Fiber.
+ React.Children.forEach(children, function (child) {
+ if (child == null) {
+ return;
+ }
+ if (typeof child === 'string' || typeof child === 'number') {
+ content += child;
+ }
+ });
-{
- var warning$31 = warning_1;
+ return content;
}
/**
- * Some event types have a notion of different registration names for different
- * "phases" of propagation. This finds listeners by a given phase.
+ * Implements an <option> host component that warns when `selected` is set.
*/
-function listenerAtPhase(inst, event, propagationPhase) {
- var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
- return getListener(inst, registrationName);
-}
-/**
- * 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) {
+function validateProps(element, props) {
+ // TODO (yungsters): Remove support for `selected` in <option>.
{
- warning$31(inst, 'Dispatching inst must not be null');
- }
- var listener = listenerAtPhase(inst, event, phase);
- if (listener) {
- event._dispatchListeners = accumulateInto_1(event._dispatchListeners, listener);
- event._dispatchInstances = accumulateInto_1(event._dispatchInstances, inst);
+ warning_1(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.');
}
}
-/**
- * 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) {
- ReactTreeTraversal.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
+function postMountWrapper$1(element, props) {
+ // value="" should make a value attribute (#6219)
+ if (props.value != null) {
+ element.setAttribute('value', props.value);
}
}
-/**
- * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
- */
-function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
- if (event && event.dispatchConfig.phasedRegistrationNames) {
- var targetInst = event._targetInst;
- var parentInst = targetInst ? ReactTreeTraversal.getParentInstance(targetInst) : null;
- ReactTreeTraversal.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
- }
-}
+function getHostProps$1(element, props) {
+ var hostProps = _assign({ children: undefined }, props);
+ var content = flattenChildren(props.children);
-/**
- * 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_1(event._dispatchListeners, listener);
- event._dispatchInstances = accumulateInto_1(event._dispatchInstances, inst);
- }
+ if (content) {
+ hostProps.children = content;
}
-}
-/**
- * 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);
- }
+ return hostProps;
}
-function accumulateTwoPhaseDispatches(events) {
- forEachAccumulated_1(events, accumulateTwoPhaseDispatchesSingle);
-}
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+var getCurrentFiberOwnerName$3 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
+var getCurrentFiberStackAddendum$4 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
-function accumulateTwoPhaseDispatchesSkipTarget(events) {
- forEachAccumulated_1(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
-}
-function accumulateEnterLeaveDispatches(leave, enter, from, to) {
- ReactTreeTraversal.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
+{
+ var didWarnValueDefaultValue$1 = false;
}
-function accumulateDirectDispatches(events) {
- forEachAccumulated_1(events, accumulateDirectDispatchesSingle);
+function getDeclarationErrorAddendum() {
+ var ownerName = getCurrentFiberOwnerName$3();
+ if (ownerName) {
+ return '\n\nCheck the render method of `' + ownerName + '`.';
+ }
+ return '';
}
-/**
- * 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.
- *
- * @constructor EventPropagators
- */
-var EventPropagators = {
- accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
- accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
- accumulateDirectDispatches: accumulateDirectDispatches,
- accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches
-};
-
-var EventPropagators_1 = EventPropagators;
+var valuePropNames = ['value', 'defaultValue'];
/**
- * This helper object stores information about text content of a target node,
- * allowing comparison of content before and after a given event.
- *
- * Identify the node where selection currently begins, then observe
- * both its text content and its current position in the DOM. Since the
- * browser may natively replace the target node during composition, we can
- * use its position to find its replacement.
- *
- *
+ * Validation function for `value` and `defaultValue`.
*/
-var compositionState = {
- _root: null,
- _startText: null,
- _fallbackText: null
-};
+function checkSelectPropTypes(props) {
+ ReactControlledValuePropTypes.checkPropTypes('select', props, getCurrentFiberStackAddendum$4);
-var FallbackCompositionState = {
- initialize: function (nativeEventTarget) {
- compositionState._root = nativeEventTarget;
- compositionState._startText = FallbackCompositionState.getText();
- return true;
- },
- reset: function () {
- compositionState._root = null;
- compositionState._startText = null;
- compositionState._fallbackText = null;
- },
- getData: function () {
- if (compositionState._fallbackText) {
- return compositionState._fallbackText;
+ for (var i = 0; i < valuePropNames.length; i++) {
+ var propName = valuePropNames[i];
+ if (props[propName] == null) {
+ continue;
}
+ var isArray = Array.isArray(props[propName]);
+ if (props.multiple && !isArray) {
+ warning_1(false, 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum());
+ } else if (!props.multiple && isArray) {
+ warning_1(false, 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum());
+ }
+ }
+}
- var start;
- var startValue = compositionState._startText;
- var startLength = startValue.length;
- var end;
- var endValue = FallbackCompositionState.getText();
- var endLength = endValue.length;
+function updateOptions(node, multiple, propValue, setDefaultSelected) {
+ var options = node.options;
- for (start = 0; start < startLength; start++) {
- if (startValue[start] !== endValue[start]) {
- break;
+ if (multiple) {
+ var selectedValues = propValue;
+ var selectedValue = {};
+ for (var i = 0; i < selectedValues.length; i++) {
+ // Prefix to avoid chaos with special keys.
+ selectedValue['$' + selectedValues[i]] = true;
+ }
+ for (var _i = 0; _i < options.length; _i++) {
+ var selected = selectedValue.hasOwnProperty('$' + options[_i].value);
+ if (options[_i].selected !== selected) {
+ options[_i].selected = selected;
+ }
+ if (selected && setDefaultSelected) {
+ options[_i].defaultSelected = true;
}
}
-
- var minEnd = startLength - start;
- for (end = 1; end <= minEnd; end++) {
- if (startValue[startLength - end] !== endValue[endLength - end]) {
- break;
+ } else {
+ // Do not set `select.value` as exact behavior isn't consistent across all
+ // browsers for all cases.
+ var _selectedValue = '' + propValue;
+ var defaultSelected = null;
+ for (var _i2 = 0; _i2 < options.length; _i2++) {
+ if (options[_i2].value === _selectedValue) {
+ options[_i2].selected = true;
+ if (setDefaultSelected) {
+ options[_i2].defaultSelected = true;
+ }
+ return;
+ }
+ if (defaultSelected === null && !options[_i2].disabled) {
+ defaultSelected = options[_i2];
}
}
-
- var sliceTail = end > 1 ? 1 - end : undefined;
- compositionState._fallbackText = endValue.slice(start, sliceTail);
- return compositionState._fallbackText;
- },
- getText: function () {
- if ('value' in compositionState._root) {
- return compositionState._root.value;
+ if (defaultSelected !== null) {
+ defaultSelected.selected = true;
}
- return compositionState._root[getTextContentAccessor_1()];
}
-};
-
-var FallbackCompositionState_1 = FallbackCompositionState;
-
-var didWarnForAddedNewProperty = false;
-var isProxySupported = typeof Proxy === 'function';
-var EVENT_POOL_SIZE = 10;
-
-{
- var warning$32 = warning_1;
}
-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_1.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.
+ * Implements a <select> host component that allows optionally setting the
+ * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
+ * stringable. If `multiple` is true, the prop must be an array of stringables.
*
- * 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`.
+ * If `value` is not supplied (or null/undefined), user actions that change the
+ * selected option will trigger updates to the rendered options.
*
- * 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.
+ * If it is supplied (and not null/undefined), the rendered options will not
+ * update in response to user actions. Instead, the `value` prop must change in
+ * order for the rendered options to update.
*
- * @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.
+ * If `defaultValue` is provided, any options with the supplied values will be
+ * selected.
*/
-function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
+
+function getHostProps$2(element, props) {
+ return _assign({}, props, {
+ value: undefined
+ });
+}
+
+function initWrapperState$1(element, props) {
+ var node = element;
{
- // these have a getter/setter for warnings
- delete this.nativeEvent;
- delete this.preventDefault;
- delete this.stopPropagation;
+ checkSelectPropTypes(props);
}
- this.dispatchConfig = dispatchConfig;
- this._targetInst = targetInst;
- this.nativeEvent = nativeEvent;
+ var value = props.value;
+ node._wrapperState = {
+ initialValue: value != null ? value : props.defaultValue,
+ wasMultiple: !!props.multiple
+ };
- 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];
- }
+ {
+ if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) {
+ warning_1(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components');
+ didWarnValueDefaultValue$1 = true;
}
}
+}
- var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
- if (defaultPrevented) {
- this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue;
- } else {
- this.isDefaultPrevented = emptyFunction_1.thatReturnsFalse;
+function postMountWrapper$2(element, props) {
+ var node = element;
+ node.multiple = !!props.multiple;
+ var value = props.value;
+ if (value != null) {
+ updateOptions(node, !!props.multiple, value, false);
+ } else if (props.defaultValue != null) {
+ updateOptions(node, !!props.multiple, props.defaultValue, true);
}
- this.isPropagationStopped = emptyFunction_1.thatReturnsFalse;
- return this;
}
-assign(SyntheticEvent.prototype, {
- preventDefault: function () {
- this.defaultPrevented = true;
- var event = this.nativeEvent;
- if (!event) {
- return;
- }
+function postUpdateWrapper(element, props) {
+ var node = element;
+ // After the initial mount, we control selected-ness manually so don't pass
+ // this value down
+ node._wrapperState.initialValue = undefined;
- if (event.preventDefault) {
- event.preventDefault();
- } else if (typeof event.returnValue !== 'unknown') {
- event.returnValue = false;
- }
- this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue;
- },
+ var wasMultiple = node._wrapperState.wasMultiple;
+ node._wrapperState.wasMultiple = !!props.multiple;
- 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;
+ var value = props.value;
+ if (value != null) {
+ updateOptions(node, !!props.multiple, value, false);
+ } else if (wasMultiple !== !!props.multiple) {
+ // For simplicity, reapply `defaultValue` if `multiple` is toggled.
+ if (props.defaultValue != null) {
+ updateOptions(node, !!props.multiple, props.defaultValue, true);
+ } else {
+ // Revert the select back to its default unselected state.
+ updateOptions(node, !!props.multiple, props.multiple ? [] : '', false);
}
+ }
+}
- this.isPropagationStopped = emptyFunction_1.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_1.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_1.thatReturnsFalse,
+function restoreControlledState$2(element, props) {
+ var node = element;
+ var value = props.value;
- /**
- * `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_1));
- Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction_1));
- }
+ if (value != null) {
+ updateOptions(node, !!props.multiple, value, false);
}
-});
+}
-SyntheticEvent.Interface = EventInterface;
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+var getCurrentFiberStackAddendum$5 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
+
+var didWarnValDefaultVal = false;
/**
- * Helper to reduce boilerplate when creating subclasses.
+ * Implements a <textarea> host component that allows setting `value`, and
+ * `defaultValue`. This differs from the traditional DOM API because value is
+ * usually set as PCDATA children.
*
- * @param {function} Class
- * @param {?object} Interface
+ * If `value` is not supplied (or null/undefined), user actions that affect the
+ * value will trigger updates to the element.
+ *
+ * If `value` is supplied (and not null/undefined), the rendered element will
+ * not trigger updates to the element. Instead, the `value` prop must change in
+ * order for the rendered element to be updated.
+ *
+ * The rendered element will be initialized with an empty value, the prop
+ * `defaultValue` if specified, or the children content (deprecated).
*/
-SyntheticEvent.augmentClass = function (Class, Interface) {
- var Super = this;
- var E = function () {};
- E.prototype = Super.prototype;
- var prototype = new E();
-
- assign(prototype, Class.prototype);
- Class.prototype = prototype;
- Class.prototype.constructor = Class;
+function getHostProps$3(element, props) {
+ var node = element;
+ !(props.dangerouslySetInnerHTML == null) ? invariant_1(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : void 0;
+
+ // Always set children to the same thing. In IE9, the selection range will
+ // get reset if `textContent` is mutated. We could add a check in setTextContent
+ // to only set the value if/when the value differs from the node value (which would
+ // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this
+ // solution. The value can be a boolean or object so that's why it's forced
+ // to be a string.
+ var hostProps = _assign({}, props, {
+ value: undefined,
+ defaultValue: undefined,
+ children: '' + node._wrapperState.initialValue
+ });
- Class.Interface = assign({}, Super.Interface, Interface);
- Class.augmentClass = Super.augmentClass;
- addEventPoolingTo(Class);
-};
+ return hostProps;
+}
-/** 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)
- */
-{
- 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$32(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 */
+function initWrapperState$2(element, props) {
+ var node = element;
+ {
+ ReactControlledValuePropTypes.checkPropTypes('textarea', props, getCurrentFiberStackAddendum$5);
+ if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
+ warning_1(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components');
+ didWarnValDefaultVal = true;
+ }
}
-}
-addEventPoolingTo(SyntheticEvent);
+ var initialValue = props.value;
-var SyntheticEvent_1 = SyntheticEvent;
+ // Only bother fetching default value if we're going to use it
+ if (initialValue == null) {
+ var defaultValue = props.defaultValue;
+ // TODO (yungsters): Remove support for children content in <textarea>.
+ var children = props.children;
+ if (children != null) {
+ {
+ warning_1(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.');
+ }
+ !(defaultValue == null) ? invariant_1(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : void 0;
+ if (Array.isArray(children)) {
+ !(children.length <= 1) ? invariant_1(false, '<textarea> can only have at most one child.') : void 0;
+ children = children[0];
+ }
-/**
- * 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
+ defaultValue = '' + children;
+ }
+ if (defaultValue == null) {
+ defaultValue = '';
+ }
+ initialValue = defaultValue;
+ }
+
+ node._wrapperState = {
+ initialValue: '' + initialValue
};
+}
- function set(val) {
- var action = isFunction ? 'setting the method' : 'setting the property';
- warn(action, 'This is effectively a no-op');
- return val;
- }
+function updateWrapper$1(element, props) {
+ var node = element;
+ var value = props.value;
+ if (value != null) {
+ // Cast `value` to a string to ensure the value is set correctly. While
+ // browsers typically do this as necessary, jsdom doesn't.
+ var newValue = '' + value;
- 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;
+ // To avoid side effects (such as losing text selection), only set value if changed
+ if (newValue !== node.value) {
+ node.value = newValue;
+ }
+ if (props.defaultValue == null) {
+ node.defaultValue = newValue;
+ }
}
-
- function warn(action, result) {
- var warningCondition = false;
- warning$32(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);
+ if (props.defaultValue != null) {
+ node.defaultValue = props.defaultValue;
}
}
-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 postMountWrapper$3(element, props) {
+ var node = element;
+ // This is in postMount because we need access to the DOM node, which is not
+ // available until after the component has mounted.
+ var textContent = node.textContent;
-function releasePooledEvent(event) {
- var EventConstructor = this;
- !(event instanceof EventConstructor) ? invariant_1(false, 'Trying to release an event instance into a pool of a different type.') : void 0;
- event.destructor();
- if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
- EventConstructor.eventPool.push(event);
+ // Only set node.value if textContent is equal to the expected
+ // initial value. In IE10/IE11 there is a bug where the placeholder attribute
+ // will populate textContent as well.
+ // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
+ if (textContent === node._wrapperState.initialValue) {
+ node.value = textContent;
}
}
-function addEventPoolingTo(EventConstructor) {
- EventConstructor.eventPool = [];
- EventConstructor.getPooled = getPooledEvent;
- EventConstructor.release = releasePooledEvent;
+function restoreControlledState$3(element, props) {
+ // DOM component is still mounted; update
+ updateWrapper$1(element, props);
}
-/**
- * @interface Event
- * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents
- */
-var CompositionEventInterface = {
- data: null
-};
-
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticUIEvent}
- */
-function SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
-}
-
-SyntheticEvent_1.augmentClass(SyntheticCompositionEvent, CompositionEventInterface);
-
-var SyntheticCompositionEvent_1 = SyntheticCompositionEvent;
+var HTML_NAMESPACE$1 = 'http://www.w3.org/1999/xhtml';
+var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
+var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
-/**
- * @interface Event
- * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
- * /#events-inputevents
- */
-var InputEventInterface = {
- data: null
+var Namespaces = {
+ html: HTML_NAMESPACE$1,
+ mathml: MATH_NAMESPACE,
+ svg: SVG_NAMESPACE
};
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticUIEvent}
- */
-function SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+// Assumes there is no parent namespace.
+function getIntrinsicNamespace(type) {
+ switch (type) {
+ case 'svg':
+ return SVG_NAMESPACE;
+ case 'math':
+ return MATH_NAMESPACE;
+ default:
+ return HTML_NAMESPACE$1;
+ }
}
-SyntheticEvent_1.augmentClass(SyntheticInputEvent, InputEventInterface);
-
-var SyntheticInputEvent_1 = SyntheticInputEvent;
-
-var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
-var START_KEYCODE = 229;
-
-var canUseCompositionEvent = ExecutionEnvironment_1.canUseDOM && 'CompositionEvent' in window;
-
-var documentMode = null;
-if (ExecutionEnvironment_1.canUseDOM && 'documentMode' in document) {
- documentMode = document.documentMode;
+function getChildNamespace(parentNamespace, type) {
+ if (parentNamespace == null || parentNamespace === HTML_NAMESPACE$1) {
+ // No (or default) parent namespace: potential entry point.
+ return getIntrinsicNamespace(type);
+ }
+ if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') {
+ // We're leaving SVG.
+ return HTML_NAMESPACE$1;
+ }
+ // By default, pass namespace below.
+ return parentNamespace;
}
-// Webkit offers a very useful `textInput` event that can be used to
-// directly represent `beforeInput`. The IE `textinput` event is not as
-// useful, so we don't use it.
-var canUseTextInputEvent = ExecutionEnvironment_1.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto();
-
-// In IE9+, we have access to composition events, but the data supplied
-// by the native compositionend event may be incorrect. Japanese ideographic
-// spaces, for instance (\u3000) are not recorded correctly.
-var useFallbackCompositionData = ExecutionEnvironment_1.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);
+/* globals MSApp */
/**
- * Opera <= 12 includes TextEvent in window, but does not fire
- * text input events. Rely on keypress instead.
+ * Create a function which has 'unsafe' privileges (required by windows8 apps)
*/
-function isPresto() {
- var opera = window.opera;
- return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12;
-}
-
-var SPACEBAR_CODE = 32;
-var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
-
-// Events and their corresponding property names.
-var eventTypes = {
- beforeInput: {
- phasedRegistrationNames: {
- bubbled: 'onBeforeInput',
- captured: 'onBeforeInputCapture'
- },
- dependencies: ['topCompositionEnd', 'topKeyPress', 'topTextInput', 'topPaste']
- },
- compositionEnd: {
- phasedRegistrationNames: {
- bubbled: 'onCompositionEnd',
- captured: 'onCompositionEndCapture'
- },
- dependencies: ['topBlur', 'topCompositionEnd', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
- },
- compositionStart: {
- phasedRegistrationNames: {
- bubbled: 'onCompositionStart',
- captured: 'onCompositionStartCapture'
- },
- dependencies: ['topBlur', 'topCompositionStart', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
- },
- compositionUpdate: {
- phasedRegistrationNames: {
- bubbled: 'onCompositionUpdate',
- captured: 'onCompositionUpdateCapture'
- },
- dependencies: ['topBlur', 'topCompositionUpdate', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
+var createMicrosoftUnsafeLocalFunction = function (func) {
+ if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
+ return function (arg0, arg1, arg2, arg3) {
+ MSApp.execUnsafeLocalFunction(function () {
+ return func(arg0, arg1, arg2, arg3);
+ });
+ };
+ } else {
+ return func;
}
};
-// Track whether we've ever handled a keypress on the space key.
-var hasSpaceKeypress = false;
+// SVG temp container for IE lacking innerHTML
+var reusableSVGContainer = void 0;
/**
- * Return whether a native keypress event is assumed to be a command.
- * This is required because Firefox fires `keypress` events for key commands
- * (cut, copy, select-all, etc.) even though no character is inserted.
+ * Set the innerHTML property of a node
+ *
+ * @param {DOMElement} node
+ * @param {string} html
+ * @internal
*/
-function isKeypressCommand(nativeEvent) {
- return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
- // ctrlKey && altKey is equivalent to AltGr, and is not a command.
- !(nativeEvent.ctrlKey && nativeEvent.altKey);
-}
+var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
+ // IE does not have innerHTML for SVG nodes, so instead we inject the
+ // new markup in a temp node and then move the child nodes across into
+ // the target node
+
+ if (node.namespaceURI === Namespaces.svg && !('innerHTML' in node)) {
+ reusableSVGContainer = reusableSVGContainer || document.createElement('div');
+ reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
+ var svgNode = reusableSVGContainer.firstChild;
+ while (node.firstChild) {
+ node.removeChild(node.firstChild);
+ }
+ while (svgNode.firstChild) {
+ node.appendChild(svgNode.firstChild);
+ }
+ } else {
+ node.innerHTML = html;
+ }
+});
/**
- * Translate native top level events into event types.
+ * Set the textContent property of a node, ensuring that whitespace is preserved
+ * even in IE8. innerText is a poor substitute for textContent and, among many
+ * issues, inserts <br> instead of the literal newline chars. innerHTML behaves
+ * as it should.
*
- * @param {string} topLevelType
- * @return {object}
+ * @param {DOMElement} node
+ * @param {string} text
+ * @internal
*/
-function getCompositionEventType(topLevelType) {
- switch (topLevelType) {
- case 'topCompositionStart':
- return eventTypes.compositionStart;
- case 'topCompositionEnd':
- return eventTypes.compositionEnd;
- case 'topCompositionUpdate':
- return eventTypes.compositionUpdate;
+var setTextContent = function (node, text) {
+ if (text) {
+ var firstChild = node.firstChild;
+
+ if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) {
+ firstChild.nodeValue = text;
+ return;
+ }
}
-}
+ node.textContent = text;
+};
/**
- * Does our fallback best-guess model think this event signifies that
- * composition has begun?
- *
- * @param {string} topLevelType
- * @param {object} nativeEvent
- * @return {boolean}
+ * CSS properties which accept numbers but are not in units of "px".
*/
-function isFallbackCompositionStart(topLevelType, nativeEvent) {
- return topLevelType === 'topKeyDown' && nativeEvent.keyCode === START_KEYCODE;
-}
+var isUnitlessNumber = {
+ animationIterationCount: true,
+ borderImageOutset: true,
+ borderImageSlice: true,
+ borderImageWidth: true,
+ boxFlex: true,
+ boxFlexGroup: true,
+ boxOrdinalGroup: true,
+ columnCount: true,
+ columns: true,
+ flex: true,
+ flexGrow: true,
+ flexPositive: true,
+ flexShrink: true,
+ flexNegative: true,
+ flexOrder: true,
+ gridRow: true,
+ gridRowEnd: true,
+ gridRowSpan: true,
+ gridRowStart: true,
+ gridColumn: true,
+ gridColumnEnd: true,
+ gridColumnSpan: true,
+ gridColumnStart: true,
+ fontWeight: true,
+ lineClamp: true,
+ lineHeight: true,
+ opacity: true,
+ order: true,
+ orphans: true,
+ tabSize: true,
+ widows: true,
+ zIndex: true,
+ zoom: true,
+
+ // SVG-related properties
+ fillOpacity: true,
+ floodOpacity: true,
+ stopOpacity: true,
+ strokeDasharray: true,
+ strokeDashoffset: true,
+ strokeMiterlimit: true,
+ strokeOpacity: true,
+ strokeWidth: true
+};
/**
- * Does our fallback mode think that this event is the end of composition?
- *
- * @param {string} topLevelType
- * @param {object} nativeEvent
- * @return {boolean}
+ * @param {string} prefix vendor-specific prefix, eg: Webkit
+ * @param {string} key style name, eg: transitionDuration
+ * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
+ * WebkitTransitionDuration
*/
-function isFallbackCompositionEnd(topLevelType, nativeEvent) {
- switch (topLevelType) {
- case 'topKeyUp':
- // Command keys insert or clear IME input.
- return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
- case 'topKeyDown':
- // Expect IME keyCode on each keydown. If we get any other
- // code we must have exited earlier.
- return nativeEvent.keyCode !== START_KEYCODE;
- case 'topKeyPress':
- case 'topMouseDown':
- case 'topBlur':
- // Events are not possible without cancelling IME.
- return true;
- default:
- return false;
- }
+function prefixKey(prefix, key) {
+ return prefix + key.charAt(0).toUpperCase() + key.substring(1);
}
/**
- * Google Input Tools provides composition data via a CustomEvent,
- * with the `data` property populated in the `detail` object. If this
- * is available on the event object, use it. If not, this is a plain
- * composition event and we have nothing special to extract.
- *
- * @param {object} nativeEvent
- * @return {?string}
+ * Support style names that may come passed in prefixed by adding permutations
+ * of vendor prefixes.
*/
-function getDataFromCustomEvent(nativeEvent) {
- var detail = nativeEvent.detail;
- if (typeof detail === 'object' && 'data' in detail) {
- return detail.data;
- }
- return null;
-}
+var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
-// Track the current IME composition status, if any.
-var isComposing = false;
+// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
+// infinite loop, because it iterates over the newly added props too.
+Object.keys(isUnitlessNumber).forEach(function (prop) {
+ prefixes.forEach(function (prefix) {
+ isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
+ });
+});
/**
- * @return {?object} A SyntheticCompositionEvent.
+ * Convert a value into the proper css writable value. The style name `name`
+ * should be logical (no hyphens), as specified
+ * in `CSSProperty.isUnitlessNumber`.
+ *
+ * @param {string} name CSS property name such as `topMargin`.
+ * @param {*} value CSS property value such as `10px`.
+ * @return {string} Normalized style value with dimensions applied.
*/
-function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- var eventType;
- var fallbackData;
+function dangerousStyleValue(name, value, isCustomProperty) {
+ // Note that we've removed escapeTextForBrowser() calls here since the
+ // whole string will be escaped when the attribute is injected into
+ // the markup. If you provide unsafe user data here they can inject
+ // arbitrary CSS which may be problematic (I couldn't repro this):
+ // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
+ // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
+ // This is not an XSS hole but instead a potential CSS injection issue
+ // which has lead to a greater discussion about how we're going to
+ // trust URLs moving forward. See #2115901
- if (canUseCompositionEvent) {
- eventType = getCompositionEventType(topLevelType);
- } else if (!isComposing) {
- if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
- eventType = eventTypes.compositionStart;
- }
- } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
- eventType = eventTypes.compositionEnd;
+ var isEmpty = value == null || typeof value === 'boolean' || value === '';
+ if (isEmpty) {
+ return '';
}
- if (!eventType) {
- return null;
+ if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) {
+ return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
}
- if (useFallbackCompositionData) {
- // The current composition is stored statically and must not be
- // overwritten while composition continues.
- if (!isComposing && eventType === eventTypes.compositionStart) {
- isComposing = FallbackCompositionState_1.initialize(nativeEventTarget);
- } else if (eventType === eventTypes.compositionEnd) {
- if (isComposing) {
- fallbackData = FallbackCompositionState_1.getData();
- }
- }
- }
+ return ('' + value).trim();
+}
- var event = SyntheticCompositionEvent_1.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);
+/**
+ * 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.
+ *
+ * @typechecks
+ */
- if (fallbackData) {
- // Inject data generated from fallback path into the synthetic event.
- // This matches the property of native CompositionEventInterface.
- event.data = fallbackData;
- } else {
- var customData = getDataFromCustomEvent(nativeEvent);
- if (customData !== null) {
- event.data = customData;
- }
- }
+var _uppercasePattern = /([A-Z])/g;
- EventPropagators_1.accumulateTwoPhaseDispatches(event);
- return event;
+/**
+ * Hyphenates a camelcased string, for example:
+ *
+ * > hyphenate('backgroundColor')
+ * < "background-color"
+ *
+ * For CSS style names, use `hyphenateStyleName` instead which works properly
+ * with all vendor prefixes, including `ms`.
+ *
+ * @param {string} string
+ * @return {string}
+ */
+function hyphenate(string) {
+ return string.replace(_uppercasePattern, '-$1').toLowerCase();
}
+var hyphenate_1 = hyphenate;
+
/**
- * @param {TopLevelTypes} topLevelType Record from `BrowserEventConstants`.
- * @param {object} nativeEvent Native browser event.
- * @return {?string} The string corresponding to this `beforeInput` event.
+ * 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.
+ *
+ * @typechecks
*/
-function getNativeBeforeInputChars(topLevelType, nativeEvent) {
- switch (topLevelType) {
- case 'topCompositionEnd':
- return getDataFromCustomEvent(nativeEvent);
- case 'topKeyPress':
- /**
- * If native `textInput` events are available, our goal is to make
- * use of them. However, there is a special case: the spacebar key.
- * In Webkit, preventing default on a spacebar `textInput` event
- * cancels character insertion, but it *also* causes the browser
- * to fall back to its default spacebar behavior of scrolling the
- * page.
- *
- * Tracking at:
- * https://code.google.com/p/chromium/issues/detail?id=355103
- *
- * To avoid this issue, use the keypress event as if no `textInput`
- * event is available.
- */
- var which = nativeEvent.which;
- if (which !== SPACEBAR_CODE) {
- return null;
- }
- hasSpaceKeypress = true;
- return SPACEBAR_CHAR;
- case 'topTextInput':
- // Record the characters to be added to the DOM.
- var chars = nativeEvent.data;
- // If it's a spacebar character, assume that we have already handled
- // it at the keypress level and bail immediately. Android Chrome
- // doesn't give us keycodes, so we need to blacklist it.
- if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
- return null;
- }
- return chars;
- default:
- // For other native event types, do nothing.
- return null;
- }
-}
+var msPattern = /^ms-/;
/**
- * For browsers that do not provide the `textInput` event, extract the
- * appropriate string to use for SyntheticInputEvent.
+ * Hyphenates a camelcased CSS property name, for example:
*
- * @param {string} topLevelType Record from `BrowserEventConstants`.
- * @param {object} nativeEvent Native browser event.
- * @return {?string} The fallback string for this `beforeInput` event.
+ * > hyphenateStyleName('backgroundColor')
+ * < "background-color"
+ * > hyphenateStyleName('MozTransition')
+ * < "-moz-transition"
+ * > hyphenateStyleName('msTransition')
+ * < "-ms-transition"
+ *
+ * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
+ * is converted to `-ms-`.
+ *
+ * @param {string} string
+ * @return {string}
*/
-function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
- // If we are currently composing (IME) and using a fallback to do so,
- // try to extract the composed characters from the fallback object.
- // If composition event is available, we extract a string only at
- // compositionevent, otherwise extract it at fallback events.
- if (isComposing) {
- if (topLevelType === 'topCompositionEnd' || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) {
- var chars = FallbackCompositionState_1.getData();
- FallbackCompositionState_1.reset();
- isComposing = false;
- return chars;
- }
- return null;
- }
-
- switch (topLevelType) {
- case 'topPaste':
- // If a paste event occurs after a keypress, throw out the input
- // chars. Paste events should not lead to BeforeInput events.
- return null;
- case 'topKeyPress':
- /**
- * As of v27, Firefox may fire keypress events even when no character
- * will be inserted. A few possibilities:
- *
- * - `which` is `0`. Arrow keys, Esc key, etc.
- *
- * - `which` is the pressed key code, but no char is available.
- * Ex: 'AltGr + d` in Polish. There is no modified character for
- * this key combination and no character is inserted into the
- * document, but FF fires the keypress for char code `100` anyway.
- * No `input` event will occur.
- *
- * - `which` is the pressed key code, but a command combination is
- * being used. Ex: `Cmd+C`. No character is inserted, and no
- * `input` event will occur.
- */
- if (!isKeypressCommand(nativeEvent)) {
- // IE fires the `keypress` event when a user types an emoji via
- // Touch keyboard of Windows. In such a case, the `char` property
- // holds an emoji character like `\uD83D\uDE0A`. Because its length
- // is 2, the property `which` does not represent an emoji correctly.
- // In such a case, we directly return the `char` property instead of
- // using `which`.
- if (nativeEvent.char && nativeEvent.char.length > 1) {
- return nativeEvent.char;
- } else if (nativeEvent.which) {
- return String.fromCharCode(nativeEvent.which);
- }
- }
- return null;
- case 'topCompositionEnd':
- return useFallbackCompositionData ? null : nativeEvent.data;
- default:
- return null;
- }
+function hyphenateStyleName(string) {
+ return hyphenate_1(string).replace(msPattern, '-ms-');
}
+var hyphenateStyleName_1 = hyphenateStyleName;
+
/**
- * Extract a SyntheticInputEvent for `beforeInput`, based on either native
- * `textInput` or fallback behavior.
+ * Copyright (c) 2013-present, Facebook, Inc.
*
- * @return {?object} A SyntheticInputEvent.
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @typechecks
*/
-function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- var chars;
-
- if (canUseTextInputEvent) {
- chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
- } else {
- chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
- }
-
- // If no characters are being inserted, no BeforeInput event should
- // be fired.
- if (!chars) {
- return null;
- }
- var event = SyntheticInputEvent_1.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);
-
- event.data = chars;
- EventPropagators_1.accumulateTwoPhaseDispatches(event);
- return event;
-}
+var _hyphenPattern = /-(.)/g;
/**
- * Create an `onBeforeInput` event to match
- * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
- *
- * This event plugin is based on the native `textInput` event
- * available in Chrome, Safari, Opera, and IE. This event fires after
- * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
+ * Camelcases a hyphenated string, for example:
*
- * `beforeInput` is spec'd but not implemented in any browsers, and
- * the `input` event does not provide any useful information about what has
- * actually been added, contrary to the spec. Thus, `textInput` is the best
- * available event to identify the characters that have actually been inserted
- * into the target node.
+ * > camelize('background-color')
+ * < "backgroundColor"
*
- * This plugin is also responsible for emitting `composition` events, thus
- * allowing us to share composition fallback code for both `beforeInput` and
- * `composition` event types.
+ * @param {string} string
+ * @return {string}
*/
-var BeforeInputEventPlugin = {
- eventTypes: eventTypes,
-
- extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];
- }
-};
+function camelize(string) {
+ return string.replace(_hyphenPattern, function (_, character) {
+ return character.toUpperCase();
+ });
+}
-var BeforeInputEventPlugin_1 = BeforeInputEventPlugin;
+var camelize_1 = camelize;
/**
* Copyright (c) 2013-present, Facebook, Inc.
@@ -16548,1469 +13229,2318 @@ var BeforeInputEventPlugin_1 = BeforeInputEventPlugin;
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
- * @providesModule isTextInputElement
- *
+ * @typechecks
*/
+
+
+
+
+var msPattern$1 = /^-ms-/;
+
/**
- * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
+ * Camelcases a hyphenated CSS property name, for example:
+ *
+ * > camelizeStyleName('background-color')
+ * < "backgroundColor"
+ * > camelizeStyleName('-moz-transition')
+ * < "MozTransition"
+ * > camelizeStyleName('-ms-transition')
+ * < "msTransition"
+ *
+ * As Andi Smith suggests
+ * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
+ * is converted to lowercase `ms`.
+ *
+ * @param {string} string
+ * @return {string}
*/
+function camelizeStyleName(string) {
+ return camelize_1(string.replace(msPattern$1, 'ms-'));
+}
-var supportedInputTypes = {
- color: true,
- date: true,
- datetime: true,
- 'datetime-local': true,
- email: true,
- month: true,
- number: true,
- password: true,
- range: true,
- search: true,
- tel: true,
- text: true,
- time: true,
- url: true,
- week: true
-};
+var camelizeStyleName_1 = camelizeStyleName;
-function isTextInputElement(elem) {
- var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
+var warnValidStyle = emptyFunction_1;
- if (nodeName === 'input') {
- return !!supportedInputTypes[elem.type];
- }
+{
+ // 'msTransform' is correct, but the other prefixes should be capitalized
+ var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
- if (nodeName === 'textarea') {
- return true;
- }
+ // style values shouldn't contain a semicolon
+ var badStyleValueWithSemicolonPattern = /;\s*$/;
- return false;
-}
+ var warnedStyleNames = {};
+ var warnedStyleValues = {};
+ var warnedForNaNValue = false;
+ var warnedForInfinityValue = false;
-var isTextInputElement_1 = isTextInputElement;
+ var warnHyphenatedStyleName = function (name, getStack) {
+ if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
+ return;
+ }
-var eventTypes$1 = {
- change: {
- phasedRegistrationNames: {
- bubbled: 'onChange',
- captured: 'onChangeCapture'
- },
- dependencies: ['topBlur', 'topChange', 'topClick', 'topFocus', 'topInput', 'topKeyDown', 'topKeyUp', 'topSelectionChange']
- }
-};
+ warnedStyleNames[name] = true;
+ warning_1(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName_1(name), getStack());
+ };
-function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
- var event = SyntheticEvent_1.getPooled(eventTypes$1.change, inst, nativeEvent, target);
- event.type = 'change';
- // Flag this event loop as needing state restore.
- ReactControlledComponent_1.enqueueStateRestore(target);
- EventPropagators_1.accumulateTwoPhaseDispatches(event);
- return event;
-}
-/**
- * For IE shims
- */
-var activeElement = null;
-var activeElementInst = null;
+ var warnBadVendoredStyleName = function (name, getStack) {
+ if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
+ return;
+ }
-/**
- * SECTION: handle `change` event
- */
-function shouldUseChangeEvent(elem) {
- var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
- return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
-}
+ warnedStyleNames[name] = true;
+ warning_1(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), getStack());
+ };
-function manualDispatchChangeEvent(nativeEvent) {
- var event = createAndAccumulateChangeEvent(activeElementInst, nativeEvent, getEventTarget_1(nativeEvent));
+ var warnStyleValueWithSemicolon = function (name, value, getStack) {
+ if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
+ return;
+ }
- // If change and propertychange bubbled, we'd just bind to it like all the
- // other events and have it go through ReactBrowserEventEmitter. Since it
- // doesn't, we manually listen for the events and so we have to enqueue and
- // process the abstract event manually.
- //
- // Batching is necessary here in order to ensure that all event handlers run
- // before the next rerender (including event handlers attached to ancestor
- // elements instead of directly on the input). Without this, controlled
- // components don't work properly in conjunction with event bubbling because
- // the component is rerendered and the value reverted before all the event
- // handlers can run. See https://github.com/facebook/react/issues/708.
- ReactGenericBatching_1.batchedUpdates(runEventInBatch, event);
-}
+ warnedStyleValues[value] = true;
+ warning_1(false, "Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.%s', name, value.replace(badStyleValueWithSemicolonPattern, ''), getStack());
+ };
-function runEventInBatch(event) {
- EventPluginHub_1.enqueueEvents(event);
- EventPluginHub_1.processEventQueue(false);
-}
+ var warnStyleValueIsNaN = function (name, value, getStack) {
+ if (warnedForNaNValue) {
+ return;
+ }
-function getInstIfValueChanged(targetInst) {
- var targetNode = ReactDOMComponentTree_1.getNodeFromInstance(targetInst);
- if (inputValueTracking_1.updateValueIfChanged(targetNode)) {
- return targetInst;
- }
-}
+ warnedForNaNValue = true;
+ warning_1(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, getStack());
+ };
-function getTargetInstForChangeEvent(topLevelType, targetInst) {
- if (topLevelType === 'topChange') {
- return targetInst;
- }
+ var warnStyleValueIsInfinity = function (name, value, getStack) {
+ if (warnedForInfinityValue) {
+ return;
+ }
+
+ warnedForInfinityValue = true;
+ warning_1(false, '`Infinity` is an invalid value for the `%s` css style property.%s', name, getStack());
+ };
+
+ warnValidStyle = function (name, value, getStack) {
+ if (name.indexOf('-') > -1) {
+ warnHyphenatedStyleName(name, getStack);
+ } else if (badVendoredStyleNamePattern.test(name)) {
+ warnBadVendoredStyleName(name, getStack);
+ } else if (badStyleValueWithSemicolonPattern.test(value)) {
+ warnStyleValueWithSemicolon(name, value, getStack);
+ }
+
+ if (typeof value === 'number') {
+ if (isNaN(value)) {
+ warnStyleValueIsNaN(name, value, getStack);
+ } else if (!isFinite(value)) {
+ warnStyleValueIsInfinity(name, value, getStack);
+ }
+ }
+ };
}
+var warnValidStyle$1 = warnValidStyle;
+
/**
- * SECTION: handle `input` event
+ * Operations for dealing with CSS properties.
*/
-var isInputEventSupported = false;
-if (ExecutionEnvironment_1.canUseDOM) {
- // IE9 claims to support the input event but fails to trigger it when
- // deleting text, so we ignore its input events.
- isInputEventSupported = isEventSupported_1('input') && (!document.documentMode || document.documentMode > 9);
-}
/**
- * (For IE <=9) Starts tracking propertychange events on the passed-in element
- * and override the value property so that we can distinguish user events from
- * value changes in JS.
+ * This creates a string that is expected to be equivalent to the style
+ * attribute generated by server-side rendering. It by-passes warnings and
+ * security checks so it's not safe to use this value for anything other than
+ * comparison. It is only used in DEV for SSR validation.
*/
-function startWatchingForValueChange(target, targetInst) {
- activeElement = target;
- activeElementInst = targetInst;
- activeElement.attachEvent('onpropertychange', handlePropertyChange);
+function createDangerousStringForStyles(styles) {
+ {
+ var serialized = '';
+ var delimiter = '';
+ for (var styleName in styles) {
+ if (!styles.hasOwnProperty(styleName)) {
+ continue;
+ }
+ var styleValue = styles[styleName];
+ if (styleValue != null) {
+ var isCustomProperty = styleName.indexOf('--') === 0;
+ serialized += delimiter + hyphenateStyleName_1(styleName) + ':';
+ serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty);
+
+ delimiter = ';';
+ }
+ }
+ return serialized || null;
+ }
}
/**
- * (For IE <=9) Removes the event listeners from the currently-tracked element,
- * if any exists.
+ * Sets the value for multiple styles on a node. If a value is specified as
+ * '' (empty string), the corresponding style property will be unset.
+ *
+ * @param {DOMElement} node
+ * @param {object} styles
*/
-function stopWatchingForValueChange() {
- if (!activeElement) {
- return;
+function setValueForStyles(node, styles, getStack) {
+ var style = node.style;
+ for (var styleName in styles) {
+ if (!styles.hasOwnProperty(styleName)) {
+ continue;
+ }
+ var isCustomProperty = styleName.indexOf('--') === 0;
+ {
+ if (!isCustomProperty) {
+ warnValidStyle$1(styleName, styles[styleName], getStack);
+ }
+ }
+ var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty);
+ if (styleName === 'float') {
+ styleName = 'cssFloat';
+ }
+ if (isCustomProperty) {
+ style.setProperty(styleName, styleValue);
+ } else {
+ style[styleName] = styleValue;
+ }
}
- activeElement.detachEvent('onpropertychange', handlePropertyChange);
- activeElement = null;
- activeElementInst = null;
}
-/**
- * (For IE <=9) Handles a propertychange event, sending a `change` event if
- * the value of the active element has changed.
- */
-function handlePropertyChange(nativeEvent) {
- if (nativeEvent.propertyName !== 'value') {
+// For HTML, certain tags should omit their close tag. We keep a whitelist for
+// those special-case tags.
+
+var omittedCloseTags = {
+ area: true,
+ base: true,
+ br: true,
+ col: true,
+ embed: true,
+ hr: true,
+ img: true,
+ input: true,
+ keygen: true,
+ link: true,
+ meta: true,
+ param: true,
+ source: true,
+ track: true,
+ wbr: true
+};
+
+// For HTML, certain tags cannot have children. This has the same purpose as
+// `omittedCloseTags` except that `menuitem` should still have its closing tag.
+
+var voidElementTags = _assign({
+ menuitem: true
+}, omittedCloseTags);
+
+var HTML$1 = '__html';
+
+function assertValidProps(tag, props, getStack) {
+ if (!props) {
return;
}
- if (getInstIfValueChanged(activeElementInst)) {
- manualDispatchChangeEvent(nativeEvent);
+ // Note the use of `==` which checks for null or undefined.
+ if (voidElementTags[tag]) {
+ !(props.children == null && props.dangerouslySetInnerHTML == null) ? invariant_1(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', tag, getStack()) : void 0;
}
-}
-
-function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) {
- if (topLevelType === 'topFocus') {
- // In IE9, propertychange fires for most input events but is buggy and
- // doesn't fire when text is deleted, but conveniently, selectionchange
- // appears to fire in all of the remaining cases so we catch those and
- // forward the event if the value has changed
- // In either case, we don't want to call the event handler if the value
- // is changed from JS so we redefine a setter for `.value` that updates
- // our activeElementValue variable, allowing us to ignore those changes
- //
- // stopWatching() should be a noop here but we call it just in case we
- // missed a blur event somehow.
- stopWatchingForValueChange();
- startWatchingForValueChange(target, targetInst);
- } else if (topLevelType === 'topBlur') {
- stopWatchingForValueChange();
+ if (props.dangerouslySetInnerHTML != null) {
+ !(props.children == null) ? invariant_1(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : void 0;
+ !(typeof props.dangerouslySetInnerHTML === 'object' && HTML$1 in props.dangerouslySetInnerHTML) ? invariant_1(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.') : void 0;
+ }
+ {
+ warning_1(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.%s', getStack());
}
+ !(props.style == null || typeof props.style === 'object') ? invariant_1(false, 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \'em\'}} when using JSX.%s', getStack()) : void 0;
}
-// For IE8 and IE9.
-function getTargetInstForInputEventPolyfill(topLevelType, targetInst) {
- if (topLevelType === 'topSelectionChange' || topLevelType === 'topKeyUp' || topLevelType === 'topKeyDown') {
- // On the selectionchange event, the target is just document which isn't
- // helpful for us so just check activeElement instead.
- //
- // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
- // propertychange on the first input event after setting `value` from a
- // script and fires only keydown, keypress, keyup. Catching keyup usually
- // gets it and catching keydown lets us fire an event for the first
- // keystroke if user does a key repeat (it'll be a little delayed: right
- // before the second keystroke). Other input methods (e.g., paste) seem to
- // fire selectionchange normally.
- return getInstIfValueChanged(activeElementInst);
+function isCustomComponent(tagName, props) {
+ if (tagName.indexOf('-') === -1) {
+ return typeof props.is === 'string';
+ }
+ switch (tagName) {
+ // These are reserved SVG and MathML elements.
+ // We don't mind this whitelist too much because we expect it to never grow.
+ // The alternative is to track the namespace in a few places which is convoluted.
+ // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
+ case 'annotation-xml':
+ case 'color-profile':
+ case 'font-face':
+ case 'font-face-src':
+ case 'font-face-uri':
+ case 'font-face-format':
+ case 'font-face-name':
+ case 'missing-glyph':
+ return false;
+ default:
+ return true;
}
}
-/**
- * SECTION: handle `click` event
- */
-function shouldUseClickEvent(elem) {
- // Use the `click` event to detect changes to checkbox and radio inputs.
- // This approach works across all browsers, whereas `change` does not fire
- // until `blur` in IE8.
- var nodeName = elem.nodeName;
- return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
+var ariaProperties = {
+ 'aria-current': 0, // state
+ 'aria-details': 0,
+ 'aria-disabled': 0, // state
+ 'aria-hidden': 0, // state
+ 'aria-invalid': 0, // state
+ 'aria-keyshortcuts': 0,
+ 'aria-label': 0,
+ 'aria-roledescription': 0,
+ // Widget Attributes
+ 'aria-autocomplete': 0,
+ 'aria-checked': 0,
+ 'aria-expanded': 0,
+ 'aria-haspopup': 0,
+ 'aria-level': 0,
+ 'aria-modal': 0,
+ 'aria-multiline': 0,
+ 'aria-multiselectable': 0,
+ 'aria-orientation': 0,
+ 'aria-placeholder': 0,
+ 'aria-pressed': 0,
+ 'aria-readonly': 0,
+ 'aria-required': 0,
+ 'aria-selected': 0,
+ 'aria-sort': 0,
+ 'aria-valuemax': 0,
+ 'aria-valuemin': 0,
+ 'aria-valuenow': 0,
+ 'aria-valuetext': 0,
+ // Live Region Attributes
+ 'aria-atomic': 0,
+ 'aria-busy': 0,
+ 'aria-live': 0,
+ 'aria-relevant': 0,
+ // Drag-and-Drop Attributes
+ 'aria-dropeffect': 0,
+ 'aria-grabbed': 0,
+ // Relationship Attributes
+ 'aria-activedescendant': 0,
+ 'aria-colcount': 0,
+ 'aria-colindex': 0,
+ 'aria-colspan': 0,
+ 'aria-controls': 0,
+ 'aria-describedby': 0,
+ 'aria-errormessage': 0,
+ 'aria-flowto': 0,
+ 'aria-labelledby': 0,
+ 'aria-owns': 0,
+ 'aria-posinset': 0,
+ 'aria-rowcount': 0,
+ 'aria-rowindex': 0,
+ 'aria-rowspan': 0,
+ 'aria-setsize': 0
+};
+
+var warnedProperties = {};
+var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
+var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
+
+var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
+
+function getStackAddendum() {
+ var stack = ReactDebugCurrentFrame.getStackAddendum();
+ return stack != null ? stack : '';
}
-function getTargetInstForClickEvent(topLevelType, targetInst) {
- if (topLevelType === 'topClick') {
- return getInstIfValueChanged(targetInst);
+function validateProperty(tagName, name) {
+ if (hasOwnProperty$1.call(warnedProperties, name) && warnedProperties[name]) {
+ return true;
+ }
+
+ if (rARIACamel.test(name)) {
+ var ariaName = 'aria-' + name.slice(4).toLowerCase();
+ var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null;
+
+ // If this is an aria-* attribute, but is not listed in the known DOM
+ // DOM properties, then it is an invalid aria-* attribute.
+ if (correctName == null) {
+ warning_1(false, 'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.%s', name, getStackAddendum());
+ warnedProperties[name] = true;
+ return true;
+ }
+ // aria-* attributes should be lowercase; suggest the lowercase version.
+ if (name !== correctName) {
+ warning_1(false, 'Invalid ARIA attribute `%s`. Did you mean `%s`?%s', name, correctName, getStackAddendum());
+ warnedProperties[name] = true;
+ return true;
+ }
}
+
+ if (rARIA.test(name)) {
+ var lowerCasedName = name.toLowerCase();
+ var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null;
+
+ // If this is an aria-* attribute, but is not listed in the known DOM
+ // DOM properties, then it is an invalid aria-* attribute.
+ if (standardName == null) {
+ warnedProperties[name] = true;
+ return false;
+ }
+ // aria-* attributes should be lowercase; suggest the lowercase version.
+ if (name !== standardName) {
+ warning_1(false, 'Unknown ARIA attribute `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum());
+ warnedProperties[name] = true;
+ return true;
+ }
+ }
+
+ return true;
}
-function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) {
- if (topLevelType === 'topInput' || topLevelType === 'topChange') {
- return getInstIfValueChanged(targetInst);
+function warnInvalidARIAProps(type, props) {
+ var invalidProps = [];
+
+ for (var key in props) {
+ var isValid = validateProperty(type, key);
+ if (!isValid) {
+ invalidProps.push(key);
+ }
+ }
+
+ var unknownPropString = invalidProps.map(function (prop) {
+ return '`' + prop + '`';
+ }).join(', ');
+
+ if (invalidProps.length === 1) {
+ warning_1(false, 'Invalid aria prop %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum());
+ } else if (invalidProps.length > 1) {
+ warning_1(false, 'Invalid aria props %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum());
}
}
-function handleControlledInputBlur(inst, node) {
- // TODO: In IE, inst is occasionally null. Why?
- if (inst == null) {
+function validateProperties(type, props) {
+ if (isCustomComponent(type, props)) {
return;
}
+ warnInvalidARIAProps(type, props);
+}
- // Fiber and ReactDOM keep wrapper state in separate places
- var state = inst._wrapperState || node._wrapperState;
+var didWarnValueNull = false;
- if (!state || !state.controlled || node.type !== 'number') {
+function getStackAddendum$1() {
+ var stack = ReactDebugCurrentFrame.getStackAddendum();
+ return stack != null ? stack : '';
+}
+
+function validateProperties$1(type, props) {
+ if (type !== 'input' && type !== 'textarea' && type !== 'select') {
return;
}
- // If controlled, assign the value attribute to the current value on blur
- var value = '' + node.value;
- if (node.getAttribute('value') !== value) {
- node.setAttribute('value', value);
+ if (props != null && props.value === null && !didWarnValueNull) {
+ didWarnValueNull = true;
+ if (type === 'select' && props.multiple) {
+ warning_1(false, '`value` prop on `%s` should not be null. ' + 'Consider using an empty array when `multiple` is set to `true` ' + 'to clear the component or `undefined` for uncontrolled components.%s', type, getStackAddendum$1());
+ } else {
+ warning_1(false, '`value` prop on `%s` should not be null. ' + 'Consider using an empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s', type, getStackAddendum$1());
+ }
}
}
-/**
- * This plugin creates an `onChange` event that normalizes change events
- * across form elements. This event fires at a time when it's possible to
- * change the element's value without seeing a flicker.
- *
- * Supported elements are:
- * - input (see `isTextInputElement`)
- * - textarea
- * - select
- */
-var ChangeEventPlugin = {
- eventTypes: eventTypes$1,
+// When adding attributes to the HTML or SVG whitelist, be sure to
+// also add them to this module to ensure casing and incorrect name
+// warnings.
+var possibleStandardNames = {
+ // HTML
+ accept: 'accept',
+ acceptcharset: 'acceptCharset',
+ 'accept-charset': 'acceptCharset',
+ accesskey: 'accessKey',
+ action: 'action',
+ allowfullscreen: 'allowFullScreen',
+ alt: 'alt',
+ as: 'as',
+ async: 'async',
+ autocapitalize: 'autoCapitalize',
+ autocomplete: 'autoComplete',
+ autocorrect: 'autoCorrect',
+ autofocus: 'autoFocus',
+ autoplay: 'autoPlay',
+ autosave: 'autoSave',
+ capture: 'capture',
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing',
+ challenge: 'challenge',
+ charset: 'charSet',
+ checked: 'checked',
+ children: 'children',
+ cite: 'cite',
+ 'class': 'className',
+ classid: 'classID',
+ classname: 'className',
+ cols: 'cols',
+ colspan: 'colSpan',
+ content: 'content',
+ contenteditable: 'contentEditable',
+ contextmenu: 'contextMenu',
+ controls: 'controls',
+ controlslist: 'controlsList',
+ coords: 'coords',
+ crossorigin: 'crossOrigin',
+ dangerouslysetinnerhtml: 'dangerouslySetInnerHTML',
+ data: 'data',
+ datetime: 'dateTime',
+ 'default': 'default',
+ defaultchecked: 'defaultChecked',
+ defaultvalue: 'defaultValue',
+ defer: 'defer',
+ dir: 'dir',
+ disabled: 'disabled',
+ download: 'download',
+ draggable: 'draggable',
+ enctype: 'encType',
+ 'for': 'htmlFor',
+ form: 'form',
+ formmethod: 'formMethod',
+ formaction: 'formAction',
+ formenctype: 'formEncType',
+ formnovalidate: 'formNoValidate',
+ formtarget: 'formTarget',
+ frameborder: 'frameBorder',
+ headers: 'headers',
+ height: 'height',
+ hidden: 'hidden',
+ high: 'high',
+ href: 'href',
+ hreflang: 'hrefLang',
+ htmlfor: 'htmlFor',
+ httpequiv: 'httpEquiv',
+ 'http-equiv': 'httpEquiv',
+ icon: 'icon',
+ id: 'id',
+ innerhtml: 'innerHTML',
+ inputmode: 'inputMode',
+ integrity: 'integrity',
+ is: 'is',
+ itemid: 'itemID',
+ itemprop: 'itemProp',
+ itemref: 'itemRef',
+ itemscope: 'itemScope',
+ itemtype: 'itemType',
+ keyparams: 'keyParams',
+ keytype: 'keyType',
+ kind: 'kind',
+ label: 'label',
+ lang: 'lang',
+ list: 'list',
+ loop: 'loop',
+ low: 'low',
+ manifest: 'manifest',
+ marginwidth: 'marginWidth',
+ marginheight: 'marginHeight',
+ max: 'max',
+ maxlength: 'maxLength',
+ media: 'media',
+ mediagroup: 'mediaGroup',
+ method: 'method',
+ min: 'min',
+ minlength: 'minLength',
+ multiple: 'multiple',
+ muted: 'muted',
+ name: 'name',
+ nonce: 'nonce',
+ novalidate: 'noValidate',
+ open: 'open',
+ optimum: 'optimum',
+ pattern: 'pattern',
+ placeholder: 'placeholder',
+ playsinline: 'playsInline',
+ poster: 'poster',
+ preload: 'preload',
+ profile: 'profile',
+ radiogroup: 'radioGroup',
+ readonly: 'readOnly',
+ referrerpolicy: 'referrerPolicy',
+ rel: 'rel',
+ required: 'required',
+ reversed: 'reversed',
+ role: 'role',
+ rows: 'rows',
+ rowspan: 'rowSpan',
+ sandbox: 'sandbox',
+ scope: 'scope',
+ scoped: 'scoped',
+ scrolling: 'scrolling',
+ seamless: 'seamless',
+ selected: 'selected',
+ shape: 'shape',
+ size: 'size',
+ sizes: 'sizes',
+ span: 'span',
+ spellcheck: 'spellCheck',
+ src: 'src',
+ srcdoc: 'srcDoc',
+ srclang: 'srcLang',
+ srcset: 'srcSet',
+ start: 'start',
+ step: 'step',
+ style: 'style',
+ summary: 'summary',
+ tabindex: 'tabIndex',
+ target: 'target',
+ title: 'title',
+ type: 'type',
+ usemap: 'useMap',
+ value: 'value',
+ width: 'width',
+ wmode: 'wmode',
+ wrap: 'wrap',
- _isInputEventSupported: isInputEventSupported,
+ // SVG
+ about: 'about',
+ accentheight: 'accentHeight',
+ 'accent-height': 'accentHeight',
+ accumulate: 'accumulate',
+ additive: 'additive',
+ alignmentbaseline: 'alignmentBaseline',
+ 'alignment-baseline': 'alignmentBaseline',
+ allowreorder: 'allowReorder',
+ alphabetic: 'alphabetic',
+ amplitude: 'amplitude',
+ arabicform: 'arabicForm',
+ 'arabic-form': 'arabicForm',
+ ascent: 'ascent',
+ attributename: 'attributeName',
+ attributetype: 'attributeType',
+ autoreverse: 'autoReverse',
+ azimuth: 'azimuth',
+ basefrequency: 'baseFrequency',
+ baselineshift: 'baselineShift',
+ 'baseline-shift': 'baselineShift',
+ baseprofile: 'baseProfile',
+ bbox: 'bbox',
+ begin: 'begin',
+ bias: 'bias',
+ by: 'by',
+ calcmode: 'calcMode',
+ capheight: 'capHeight',
+ 'cap-height': 'capHeight',
+ clip: 'clip',
+ clippath: 'clipPath',
+ 'clip-path': 'clipPath',
+ clippathunits: 'clipPathUnits',
+ cliprule: 'clipRule',
+ 'clip-rule': 'clipRule',
+ color: 'color',
+ colorinterpolation: 'colorInterpolation',
+ 'color-interpolation': 'colorInterpolation',
+ colorinterpolationfilters: 'colorInterpolationFilters',
+ 'color-interpolation-filters': 'colorInterpolationFilters',
+ colorprofile: 'colorProfile',
+ 'color-profile': 'colorProfile',
+ colorrendering: 'colorRendering',
+ 'color-rendering': 'colorRendering',
+ contentscripttype: 'contentScriptType',
+ contentstyletype: 'contentStyleType',
+ cursor: 'cursor',
+ cx: 'cx',
+ cy: 'cy',
+ d: 'd',
+ datatype: 'datatype',
+ decelerate: 'decelerate',
+ descent: 'descent',
+ diffuseconstant: 'diffuseConstant',
+ direction: 'direction',
+ display: 'display',
+ divisor: 'divisor',
+ dominantbaseline: 'dominantBaseline',
+ 'dominant-baseline': 'dominantBaseline',
+ dur: 'dur',
+ dx: 'dx',
+ dy: 'dy',
+ edgemode: 'edgeMode',
+ elevation: 'elevation',
+ enablebackground: 'enableBackground',
+ 'enable-background': 'enableBackground',
+ end: 'end',
+ exponent: 'exponent',
+ externalresourcesrequired: 'externalResourcesRequired',
+ fill: 'fill',
+ fillopacity: 'fillOpacity',
+ 'fill-opacity': 'fillOpacity',
+ fillrule: 'fillRule',
+ 'fill-rule': 'fillRule',
+ filter: 'filter',
+ filterres: 'filterRes',
+ filterunits: 'filterUnits',
+ floodopacity: 'floodOpacity',
+ 'flood-opacity': 'floodOpacity',
+ floodcolor: 'floodColor',
+ 'flood-color': 'floodColor',
+ focusable: 'focusable',
+ fontfamily: 'fontFamily',
+ 'font-family': 'fontFamily',
+ fontsize: 'fontSize',
+ 'font-size': 'fontSize',
+ fontsizeadjust: 'fontSizeAdjust',
+ 'font-size-adjust': 'fontSizeAdjust',
+ fontstretch: 'fontStretch',
+ 'font-stretch': 'fontStretch',
+ fontstyle: 'fontStyle',
+ 'font-style': 'fontStyle',
+ fontvariant: 'fontVariant',
+ 'font-variant': 'fontVariant',
+ fontweight: 'fontWeight',
+ 'font-weight': 'fontWeight',
+ format: 'format',
+ from: 'from',
+ fx: 'fx',
+ fy: 'fy',
+ g1: 'g1',
+ g2: 'g2',
+ glyphname: 'glyphName',
+ 'glyph-name': 'glyphName',
+ glyphorientationhorizontal: 'glyphOrientationHorizontal',
+ 'glyph-orientation-horizontal': 'glyphOrientationHorizontal',
+ glyphorientationvertical: 'glyphOrientationVertical',
+ 'glyph-orientation-vertical': 'glyphOrientationVertical',
+ glyphref: 'glyphRef',
+ gradienttransform: 'gradientTransform',
+ gradientunits: 'gradientUnits',
+ hanging: 'hanging',
+ horizadvx: 'horizAdvX',
+ 'horiz-adv-x': 'horizAdvX',
+ horizoriginx: 'horizOriginX',
+ 'horiz-origin-x': 'horizOriginX',
+ ideographic: 'ideographic',
+ imagerendering: 'imageRendering',
+ 'image-rendering': 'imageRendering',
+ in2: 'in2',
+ 'in': 'in',
+ inlist: 'inlist',
+ intercept: 'intercept',
+ k1: 'k1',
+ k2: 'k2',
+ k3: 'k3',
+ k4: 'k4',
+ k: 'k',
+ kernelmatrix: 'kernelMatrix',
+ kernelunitlength: 'kernelUnitLength',
+ kerning: 'kerning',
+ keypoints: 'keyPoints',
+ keysplines: 'keySplines',
+ keytimes: 'keyTimes',
+ lengthadjust: 'lengthAdjust',
+ letterspacing: 'letterSpacing',
+ 'letter-spacing': 'letterSpacing',
+ lightingcolor: 'lightingColor',
+ 'lighting-color': 'lightingColor',
+ limitingconeangle: 'limitingConeAngle',
+ local: 'local',
+ markerend: 'markerEnd',
+ 'marker-end': 'markerEnd',
+ markerheight: 'markerHeight',
+ markermid: 'markerMid',
+ 'marker-mid': 'markerMid',
+ markerstart: 'markerStart',
+ 'marker-start': 'markerStart',
+ markerunits: 'markerUnits',
+ markerwidth: 'markerWidth',
+ mask: 'mask',
+ maskcontentunits: 'maskContentUnits',
+ maskunits: 'maskUnits',
+ mathematical: 'mathematical',
+ mode: 'mode',
+ numoctaves: 'numOctaves',
+ offset: 'offset',
+ opacity: 'opacity',
+ operator: 'operator',
+ order: 'order',
+ orient: 'orient',
+ orientation: 'orientation',
+ origin: 'origin',
+ overflow: 'overflow',
+ overlineposition: 'overlinePosition',
+ 'overline-position': 'overlinePosition',
+ overlinethickness: 'overlineThickness',
+ 'overline-thickness': 'overlineThickness',
+ paintorder: 'paintOrder',
+ 'paint-order': 'paintOrder',
+ panose1: 'panose1',
+ 'panose-1': 'panose1',
+ pathlength: 'pathLength',
+ patterncontentunits: 'patternContentUnits',
+ patterntransform: 'patternTransform',
+ patternunits: 'patternUnits',
+ pointerevents: 'pointerEvents',
+ 'pointer-events': 'pointerEvents',
+ points: 'points',
+ pointsatx: 'pointsAtX',
+ pointsaty: 'pointsAtY',
+ pointsatz: 'pointsAtZ',
+ prefix: 'prefix',
+ preservealpha: 'preserveAlpha',
+ preserveaspectratio: 'preserveAspectRatio',
+ primitiveunits: 'primitiveUnits',
+ property: 'property',
+ r: 'r',
+ radius: 'radius',
+ refx: 'refX',
+ refy: 'refY',
+ renderingintent: 'renderingIntent',
+ 'rendering-intent': 'renderingIntent',
+ repeatcount: 'repeatCount',
+ repeatdur: 'repeatDur',
+ requiredextensions: 'requiredExtensions',
+ requiredfeatures: 'requiredFeatures',
+ resource: 'resource',
+ restart: 'restart',
+ result: 'result',
+ results: 'results',
+ rotate: 'rotate',
+ rx: 'rx',
+ ry: 'ry',
+ scale: 'scale',
+ security: 'security',
+ seed: 'seed',
+ shaperendering: 'shapeRendering',
+ 'shape-rendering': 'shapeRendering',
+ slope: 'slope',
+ spacing: 'spacing',
+ specularconstant: 'specularConstant',
+ specularexponent: 'specularExponent',
+ speed: 'speed',
+ spreadmethod: 'spreadMethod',
+ startoffset: 'startOffset',
+ stddeviation: 'stdDeviation',
+ stemh: 'stemh',
+ stemv: 'stemv',
+ stitchtiles: 'stitchTiles',
+ stopcolor: 'stopColor',
+ 'stop-color': 'stopColor',
+ stopopacity: 'stopOpacity',
+ 'stop-opacity': 'stopOpacity',
+ strikethroughposition: 'strikethroughPosition',
+ 'strikethrough-position': 'strikethroughPosition',
+ strikethroughthickness: 'strikethroughThickness',
+ 'strikethrough-thickness': 'strikethroughThickness',
+ string: 'string',
+ stroke: 'stroke',
+ strokedasharray: 'strokeDasharray',
+ 'stroke-dasharray': 'strokeDasharray',
+ strokedashoffset: 'strokeDashoffset',
+ 'stroke-dashoffset': 'strokeDashoffset',
+ strokelinecap: 'strokeLinecap',
+ 'stroke-linecap': 'strokeLinecap',
+ strokelinejoin: 'strokeLinejoin',
+ 'stroke-linejoin': 'strokeLinejoin',
+ strokemiterlimit: 'strokeMiterlimit',
+ 'stroke-miterlimit': 'strokeMiterlimit',
+ strokewidth: 'strokeWidth',
+ 'stroke-width': 'strokeWidth',
+ strokeopacity: 'strokeOpacity',
+ 'stroke-opacity': 'strokeOpacity',
+ suppresscontenteditablewarning: 'suppressContentEditableWarning',
+ suppresshydrationwarning: 'suppressHydrationWarning',
+ surfacescale: 'surfaceScale',
+ systemlanguage: 'systemLanguage',
+ tablevalues: 'tableValues',
+ targetx: 'targetX',
+ targety: 'targetY',
+ textanchor: 'textAnchor',
+ 'text-anchor': 'textAnchor',
+ textdecoration: 'textDecoration',
+ 'text-decoration': 'textDecoration',
+ textlength: 'textLength',
+ textrendering: 'textRendering',
+ 'text-rendering': 'textRendering',
+ to: 'to',
+ transform: 'transform',
+ 'typeof': 'typeof',
+ u1: 'u1',
+ u2: 'u2',
+ underlineposition: 'underlinePosition',
+ 'underline-position': 'underlinePosition',
+ underlinethickness: 'underlineThickness',
+ 'underline-thickness': 'underlineThickness',
+ unicode: 'unicode',
+ unicodebidi: 'unicodeBidi',
+ 'unicode-bidi': 'unicodeBidi',
+ unicoderange: 'unicodeRange',
+ 'unicode-range': 'unicodeRange',
+ unitsperem: 'unitsPerEm',
+ 'units-per-em': 'unitsPerEm',
+ unselectable: 'unselectable',
+ valphabetic: 'vAlphabetic',
+ 'v-alphabetic': 'vAlphabetic',
+ values: 'values',
+ vectoreffect: 'vectorEffect',
+ 'vector-effect': 'vectorEffect',
+ version: 'version',
+ vertadvy: 'vertAdvY',
+ 'vert-adv-y': 'vertAdvY',
+ vertoriginx: 'vertOriginX',
+ 'vert-origin-x': 'vertOriginX',
+ vertoriginy: 'vertOriginY',
+ 'vert-origin-y': 'vertOriginY',
+ vhanging: 'vHanging',
+ 'v-hanging': 'vHanging',
+ videographic: 'vIdeographic',
+ 'v-ideographic': 'vIdeographic',
+ viewbox: 'viewBox',
+ viewtarget: 'viewTarget',
+ visibility: 'visibility',
+ vmathematical: 'vMathematical',
+ 'v-mathematical': 'vMathematical',
+ vocab: 'vocab',
+ widths: 'widths',
+ wordspacing: 'wordSpacing',
+ 'word-spacing': 'wordSpacing',
+ writingmode: 'writingMode',
+ 'writing-mode': 'writingMode',
+ x1: 'x1',
+ x2: 'x2',
+ x: 'x',
+ xchannelselector: 'xChannelSelector',
+ xheight: 'xHeight',
+ 'x-height': 'xHeight',
+ xlinkactuate: 'xlinkActuate',
+ 'xlink:actuate': 'xlinkActuate',
+ xlinkarcrole: 'xlinkArcrole',
+ 'xlink:arcrole': 'xlinkArcrole',
+ xlinkhref: 'xlinkHref',
+ 'xlink:href': 'xlinkHref',
+ xlinkrole: 'xlinkRole',
+ 'xlink:role': 'xlinkRole',
+ xlinkshow: 'xlinkShow',
+ 'xlink:show': 'xlinkShow',
+ xlinktitle: 'xlinkTitle',
+ 'xlink:title': 'xlinkTitle',
+ xlinktype: 'xlinkType',
+ 'xlink:type': 'xlinkType',
+ xmlbase: 'xmlBase',
+ 'xml:base': 'xmlBase',
+ xmllang: 'xmlLang',
+ 'xml:lang': 'xmlLang',
+ xmlns: 'xmlns',
+ 'xml:space': 'xmlSpace',
+ xmlnsxlink: 'xmlnsXlink',
+ 'xmlns:xlink': 'xmlnsXlink',
+ xmlspace: 'xmlSpace',
+ y1: 'y1',
+ y2: 'y2',
+ y: 'y',
+ ychannelselector: 'yChannelSelector',
+ z: 'z',
+ zoomandpan: 'zoomAndPan'
+};
- extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- var targetNode = targetInst ? ReactDOMComponentTree_1.getNodeFromInstance(targetInst) : window;
+function getStackAddendum$2() {
+ var stack = ReactDebugCurrentFrame.getStackAddendum();
+ return stack != null ? stack : '';
+}
- var getTargetInstFunc, handleEventFunc;
- if (shouldUseChangeEvent(targetNode)) {
- getTargetInstFunc = getTargetInstForChangeEvent;
- } else if (isTextInputElement_1(targetNode)) {
- if (isInputEventSupported) {
- getTargetInstFunc = getTargetInstForInputOrChangeEvent;
- } else {
- getTargetInstFunc = getTargetInstForInputEventPolyfill;
- handleEventFunc = handleEventsForInputEventPolyfill;
- }
- } else if (shouldUseClickEvent(targetNode)) {
- getTargetInstFunc = getTargetInstForClickEvent;
+{
+ var warnedProperties$1 = {};
+ var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
+ var EVENT_NAME_REGEX = /^on./;
+ var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;
+ var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
+ var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
+
+ var validateProperty$1 = function (tagName, name, value, canUseEventSystem) {
+ if (hasOwnProperty$2.call(warnedProperties$1, name) && warnedProperties$1[name]) {
+ return true;
}
- if (getTargetInstFunc) {
- var inst = getTargetInstFunc(topLevelType, targetInst);
- if (inst) {
- var event = createAndAccumulateChangeEvent(inst, nativeEvent, nativeEventTarget);
- return event;
+ var lowerCasedName = name.toLowerCase();
+ if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') {
+ warning_1(false, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.');
+ warnedProperties$1[name] = true;
+ return true;
+ }
+
+ // We can't rely on the event system being injected on the server.
+ if (canUseEventSystem) {
+ if (registrationNameModules.hasOwnProperty(name)) {
+ return true;
+ }
+ var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null;
+ if (registrationName != null) {
+ warning_1(false, 'Invalid event handler property `%s`. Did you mean `%s`?%s', name, registrationName, getStackAddendum$2());
+ warnedProperties$1[name] = true;
+ return true;
+ }
+ if (EVENT_NAME_REGEX.test(name)) {
+ warning_1(false, 'Unknown event handler property `%s`. It will be ignored.%s', name, getStackAddendum$2());
+ warnedProperties$1[name] = true;
+ return true;
}
+ } else if (EVENT_NAME_REGEX.test(name)) {
+ // If no event plugins have been injected, we are in a server environment.
+ // So we can't tell if the event name is correct for sure, but we can filter
+ // out known bad ones like `onclick`. We can't suggest a specific replacement though.
+ if (INVALID_EVENT_NAME_REGEX.test(name)) {
+ warning_1(false, 'Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.%s', name, getStackAddendum$2());
+ }
+ warnedProperties$1[name] = true;
+ return true;
}
- if (handleEventFunc) {
- handleEventFunc(topLevelType, targetNode, targetInst);
+ // Let the ARIA attribute hook validate ARIA attributes
+ if (rARIA$1.test(name) || rARIACamel$1.test(name)) {
+ return true;
}
- // When blurring, set the value attribute for number inputs
- if (topLevelType === 'topBlur') {
- handleControlledInputBlur(targetInst, targetNode);
+ if (lowerCasedName === 'innerhtml') {
+ warning_1(false, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.');
+ warnedProperties$1[name] = true;
+ return true;
}
- }
-};
-var ChangeEventPlugin_1 = ChangeEventPlugin;
+ if (lowerCasedName === 'aria') {
+ warning_1(false, 'The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.');
+ warnedProperties$1[name] = true;
+ return true;
+ }
-/**
- * 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.
- *
- * @providesModule DOMEventPluginOrder
- */
+ if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') {
+ warning_1(false, 'Received a `%s` for a string attribute `is`. If this is expected, cast ' + 'the value to a string.%s', typeof value, getStackAddendum$2());
+ warnedProperties$1[name] = true;
+ return true;
+ }
-/**
- * Module that is injectable into `EventPluginHub`, that specifies a
- * deterministic ordering of `EventPlugin`s. A convenient way to reason about
- * plugins, without having to package every one of them. This is better than
- * having plugins be ordered in the same order that they are injected because
- * that ordering would be influenced by the packaging order.
- * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
- * preventing default on events is convenient in `SimpleEventPlugin` handlers.
- */
+ if (typeof value === 'number' && isNaN(value)) {
+ warning_1(false, 'Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.%s', name, getStackAddendum$2());
+ warnedProperties$1[name] = true;
+ return true;
+ }
-var DOMEventPluginOrder = ['ResponderEventPlugin', 'SimpleEventPlugin', 'TapEventPlugin', 'EnterLeaveEventPlugin', 'ChangeEventPlugin', 'SelectEventPlugin', 'BeforeInputEventPlugin'];
+ var isReserved = isReservedProp(name);
-var DOMEventPluginOrder_1 = DOMEventPluginOrder;
+ // Known attributes should match the casing specified in the property config.
+ if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
+ var standardName = possibleStandardNames[lowerCasedName];
+ if (standardName !== name) {
+ warning_1(false, 'Invalid DOM property `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum$2());
+ warnedProperties$1[name] = true;
+ return true;
+ }
+ } else if (!isReserved && name !== lowerCasedName) {
+ // Unknown attributes should have lowercase casing since that's how they
+ // will be cased anyway with server rendering.
+ warning_1(false, 'React does not recognize the `%s` prop on a DOM element. If you ' + 'intentionally want it to appear in the DOM as a custom ' + 'attribute, spell it as lowercase `%s` instead. ' + 'If you accidentally passed it from a parent component, remove ' + 'it from the DOM element.%s', name, lowerCasedName, getStackAddendum$2());
+ warnedProperties$1[name] = true;
+ return true;
+ }
-/**
- * @interface UIEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
-var UIEventInterface = {
- view: function (event) {
- if (event.view) {
- return event.view;
+ if (typeof value === 'boolean' && !shouldAttributeAcceptBooleanValue(name)) {
+ if (value) {
+ warning_1(false, 'Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.%s', value, name, name, value, name, getStackAddendum$2());
+ } else {
+ warning_1(false, 'Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.%s', value, name, name, value, name, name, name, getStackAddendum$2());
+ }
+ warnedProperties$1[name] = true;
+ return true;
}
- var target = getEventTarget_1(event);
- if (target.window === target) {
- // target is a window object
- return target;
+ // Now that we've validated casing, do not validate
+ // data types for reserved props
+ if (isReserved) {
+ return true;
}
- var doc = target.ownerDocument;
- // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
- if (doc) {
- return doc.defaultView || doc.parentWindow;
- } else {
- return window;
+ // Warn when a known attribute is a bad type
+ if (!shouldSetAttribute(name, value)) {
+ warnedProperties$1[name] = true;
+ return false;
}
- },
- detail: function (event) {
- return event.detail || 0;
- }
-};
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticEvent}
- */
-function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+ return true;
+ };
}
-SyntheticEvent_1.augmentClass(SyntheticUIEvent, UIEventInterface);
-
-var SyntheticUIEvent_1 = SyntheticUIEvent;
-
-/**
- * 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.
- *
- * @providesModule getEventModifierState
- */
-
-/**
- * Translation from modifier key to the associated property in the event.
- * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
- */
+var warnUnknownProperties = function (type, props, canUseEventSystem) {
+ var unknownProps = [];
+ for (var key in props) {
+ var isValid = validateProperty$1(type, key, props[key], canUseEventSystem);
+ if (!isValid) {
+ unknownProps.push(key);
+ }
+ }
-var modifierKeyToProp = {
- Alt: 'altKey',
- Control: 'ctrlKey',
- Meta: 'metaKey',
- Shift: 'shiftKey'
+ var unknownPropString = unknownProps.map(function (prop) {
+ return '`' + prop + '`';
+ }).join(', ');
+ if (unknownProps.length === 1) {
+ warning_1(false, 'Invalid value for prop %s on <%s> tag. Either remove it from the element, ' + 'or pass a string or number value to keep it in the DOM. ' + 'For details, see https://fb.me/react-attribute-behavior%s', unknownPropString, type, getStackAddendum$2());
+ } else if (unknownProps.length > 1) {
+ warning_1(false, 'Invalid values for props %s on <%s> tag. Either remove them from the element, ' + 'or pass a string or number value to keep them in the DOM. ' + 'For details, see https://fb.me/react-attribute-behavior%s', unknownPropString, type, getStackAddendum$2());
+ }
};
-// IE8 does not implement getModifierState so we simply map it to the only
-// modifier keys exposed by the event itself, does not support Lock-keys.
-// Currently, all major browsers except Chrome seems to support Lock-keys.
-function modifierStateGetter(keyArg) {
- var syntheticEvent = this;
- var nativeEvent = syntheticEvent.nativeEvent;
- if (nativeEvent.getModifierState) {
- return nativeEvent.getModifierState(keyArg);
+function validateProperties$2(type, props, canUseEventSystem) {
+ if (isCustomComponent(type, props)) {
+ return;
}
- var keyProp = modifierKeyToProp[keyArg];
- return keyProp ? !!nativeEvent[keyProp] : false;
+ warnUnknownProperties(type, props, canUseEventSystem);
}
-function getEventModifierState(nativeEvent) {
- return modifierStateGetter;
-}
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+var getCurrentFiberOwnerName$1 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
+var getCurrentFiberStackAddendum$2 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
-var getEventModifierState_1 = getEventModifierState;
+var didWarnInvalidHydration = false;
+var didWarnShadyDOM = false;
-/**
- * @interface MouseEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
-var MouseEventInterface = {
- screenX: null,
- screenY: null,
- clientX: null,
- clientY: null,
- pageX: null,
- pageY: null,
- ctrlKey: null,
- shiftKey: null,
- altKey: null,
- metaKey: null,
- getModifierState: getEventModifierState_1,
- button: null,
- buttons: null,
- relatedTarget: function (event) {
- return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);
- }
-};
+var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
+var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
+var SUPPRESS_HYDRATION_WARNING$1 = 'suppressHydrationWarning';
+var AUTOFOCUS = 'autoFocus';
+var CHILDREN = 'children';
+var STYLE = 'style';
+var HTML = '__html';
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticUIEvent}
- */
-function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticUIEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
-}
+var HTML_NAMESPACE = Namespaces.html;
-SyntheticUIEvent_1.augmentClass(SyntheticMouseEvent, MouseEventInterface);
-var SyntheticMouseEvent_1 = SyntheticMouseEvent;
+var getStack = emptyFunction_1.thatReturns('');
-var eventTypes$2 = {
- mouseEnter: {
- registrationName: 'onMouseEnter',
- dependencies: ['topMouseOut', 'topMouseOver']
- },
- mouseLeave: {
- registrationName: 'onMouseLeave',
- dependencies: ['topMouseOut', 'topMouseOver']
- }
-};
+{
+ getStack = getCurrentFiberStackAddendum$2;
-var EnterLeaveEventPlugin = {
- eventTypes: eventTypes$2,
+ var warnedUnknownTags = {
+ // Chrome is the only major browser not shipping <time>. But as of July
+ // 2017 it intends to ship it due to widespread usage. We intentionally
+ // *don't* warn for <time> even if it's unrecognized by Chrome because
+ // it soon will be, and many apps have been using it anyway.
+ time: true,
+ // There are working polyfills for <dialog>. Let people use it.
+ dialog: true
+ };
- /**
- * For almost every interaction we care about, there will be both a top-level
- * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
- * we do not extract duplicate events. However, moving the mouse into the
- * browser from outside will not fire a `mouseout` event. In this case, we use
- * the `mouseover` top-level event.
- */
- extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
- return null;
+ var validatePropertiesInDevelopment = function (type, props) {
+ validateProperties(type, props);
+ validateProperties$1(type, props);
+ validateProperties$2(type, props, /* canUseEventSystem */true);
+ };
+
+ // HTML parsing normalizes CR and CRLF to LF.
+ // It also can turn \u0000 into \uFFFD inside attributes.
+ // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream
+ // If we have a mismatch, it might be caused by that.
+ // We will still patch up in this case but not fire the warning.
+ var NORMALIZE_NEWLINES_REGEX = /\r\n?/g;
+ var NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g;
+
+ var normalizeMarkupForTextOrAttribute = function (markup) {
+ var markupString = typeof markup === 'string' ? markup : '' + markup;
+ return markupString.replace(NORMALIZE_NEWLINES_REGEX, '\n').replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, '');
+ };
+
+ var warnForTextDifference = function (serverText, clientText) {
+ if (didWarnInvalidHydration) {
+ return;
}
- if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') {
- // Must not be a mouse in or mouse out - ignoring.
- return null;
+ var normalizedClientText = normalizeMarkupForTextOrAttribute(clientText);
+ var normalizedServerText = normalizeMarkupForTextOrAttribute(serverText);
+ if (normalizedServerText === normalizedClientText) {
+ return;
}
+ didWarnInvalidHydration = true;
+ warning_1(false, 'Text content did not match. Server: "%s" Client: "%s"', normalizedServerText, normalizedClientText);
+ };
- var win;
- if (nativeEventTarget.window === nativeEventTarget) {
- // `nativeEventTarget` is probably a window object.
- win = nativeEventTarget;
- } else {
- // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
- var doc = nativeEventTarget.ownerDocument;
- if (doc) {
- win = doc.defaultView || doc.parentWindow;
- } else {
- win = window;
- }
+ var warnForPropDifference = function (propName, serverValue, clientValue) {
+ if (didWarnInvalidHydration) {
+ return;
}
-
- var from;
- var to;
- if (topLevelType === 'topMouseOut') {
- from = targetInst;
- var related = nativeEvent.relatedTarget || nativeEvent.toElement;
- to = related ? ReactDOMComponentTree_1.getClosestInstanceFromNode(related) : null;
- } else {
- // Moving to a node from outside the window.
- from = null;
- to = targetInst;
+ var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue);
+ var normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);
+ if (normalizedServerValue === normalizedClientValue) {
+ return;
}
+ didWarnInvalidHydration = true;
+ warning_1(false, 'Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue));
+ };
- if (from === to) {
- // Nothing pertains to our managed components.
- return null;
+ var warnForExtraAttributes = function (attributeNames) {
+ if (didWarnInvalidHydration) {
+ return;
}
+ didWarnInvalidHydration = true;
+ var names = [];
+ attributeNames.forEach(function (name) {
+ names.push(name);
+ });
+ warning_1(false, 'Extra attributes from the server: %s', names);
+ };
- var fromNode = from == null ? win : ReactDOMComponentTree_1.getNodeFromInstance(from);
- var toNode = to == null ? win : ReactDOMComponentTree_1.getNodeFromInstance(to);
+ var warnForInvalidEventListener = function (registrationName, listener) {
+ if (listener === false) {
+ warning_1(false, 'Expected `%s` listener to be a function, instead got `false`.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.%s', registrationName, registrationName, registrationName, getCurrentFiberStackAddendum$2());
+ } else {
+ warning_1(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.%s', registrationName, typeof listener, getCurrentFiberStackAddendum$2());
+ }
+ };
- var leave = SyntheticMouseEvent_1.getPooled(eventTypes$2.mouseLeave, from, nativeEvent, nativeEventTarget);
- leave.type = 'mouseleave';
- leave.target = fromNode;
- leave.relatedTarget = toNode;
+ // Parse the HTML and read it back to normalize the HTML string so that it
+ // can be used for comparison.
+ var normalizeHTML = function (parent, html) {
+ // We could have created a separate document here to avoid
+ // re-initializing custom elements if they exist. But this breaks
+ // how <noscript> is being handled. So we use the same document.
+ // See the discussion in https://github.com/facebook/react/pull/11157.
+ var testElement = parent.namespaceURI === HTML_NAMESPACE ? parent.ownerDocument.createElement(parent.tagName) : parent.ownerDocument.createElementNS(parent.namespaceURI, parent.tagName);
+ testElement.innerHTML = html;
+ return testElement.innerHTML;
+ };
+}
- var enter = SyntheticMouseEvent_1.getPooled(eventTypes$2.mouseEnter, to, nativeEvent, nativeEventTarget);
- enter.type = 'mouseenter';
- enter.target = toNode;
- enter.relatedTarget = fromNode;
+function ensureListeningTo(rootContainerElement, registrationName) {
+ var isDocumentOrFragment = rootContainerElement.nodeType === DOCUMENT_NODE || rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE;
+ var doc = isDocumentOrFragment ? rootContainerElement : rootContainerElement.ownerDocument;
+ listenTo(registrationName, doc);
+}
- EventPropagators_1.accumulateEnterLeaveDispatches(leave, enter, from, to);
+function getOwnerDocumentFromRootContainer(rootContainerElement) {
+ return rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument;
+}
- return [leave, enter];
- }
+// There are so many media events, it makes sense to just
+// maintain a list rather than create a `trapBubbledEvent` for each
+var mediaEvents = {
+ topAbort: 'abort',
+ topCanPlay: 'canplay',
+ topCanPlayThrough: 'canplaythrough',
+ topDurationChange: 'durationchange',
+ topEmptied: 'emptied',
+ topEncrypted: 'encrypted',
+ topEnded: 'ended',
+ topError: 'error',
+ topLoadedData: 'loadeddata',
+ topLoadedMetadata: 'loadedmetadata',
+ topLoadStart: 'loadstart',
+ topPause: 'pause',
+ topPlay: 'play',
+ topPlaying: 'playing',
+ topProgress: 'progress',
+ topRateChange: 'ratechange',
+ topSeeked: 'seeked',
+ topSeeking: 'seeking',
+ topStalled: 'stalled',
+ topSuspend: 'suspend',
+ topTimeUpdate: 'timeupdate',
+ topVolumeChange: 'volumechange',
+ topWaiting: 'waiting'
};
-var EnterLeaveEventPlugin_1 = EnterLeaveEventPlugin;
+function trapClickOnNonInteractiveElement(node) {
+ // Mobile Safari does not fire properly bubble click events on
+ // non-interactive elements, which means delegated click listeners do not
+ // fire. The workaround for this bug involves attaching an empty click
+ // listener on the target node.
+ // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
+ // Just set it using the onclick property so that we don't have to manage any
+ // bookkeeping for it. Not sure if we need to clear it when the listener is
+ // removed.
+ // TODO: Only do this for the relevant Safaris maybe?
+ node.onclick = emptyFunction_1;
+}
-var DOCUMENT_NODE$2 = HTMLNodeType_1.DOCUMENT_NODE;
+function setInitialDOMProperties(tag, domElement, rootContainerElement, nextProps, isCustomComponentTag) {
+ for (var propKey in nextProps) {
+ if (!nextProps.hasOwnProperty(propKey)) {
+ continue;
+ }
+ var nextProp = nextProps[propKey];
+ if (propKey === STYLE) {
+ {
+ if (nextProp) {
+ // Freeze the next style object so that we can assume it won't be
+ // mutated. We have already warned for this in the past.
+ Object.freeze(nextProp);
+ }
+ }
+ // Relies on `updateStylesByID` not mutating `styleUpdates`.
+ setValueForStyles(domElement, nextProp, getStack);
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
+ var nextHtml = nextProp ? nextProp[HTML] : undefined;
+ if (nextHtml != null) {
+ setInnerHTML(domElement, nextHtml);
+ }
+ } else if (propKey === CHILDREN) {
+ if (typeof nextProp === 'string') {
+ // Avoid setting initial textContent when the text is empty. In IE11 setting
+ // textContent on a <textarea> will cause the placeholder to not
+ // show within the <textarea> until it has been focused and blurred again.
+ // https://github.com/facebook/react/issues/6731#issuecomment-254874553
+ var canSetTextContent = tag !== 'textarea' || nextProp !== '';
+ if (canSetTextContent) {
+ setTextContent(domElement, nextProp);
+ }
+ } else if (typeof nextProp === 'number') {
+ setTextContent(domElement, '' + nextProp);
+ }
+ } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
+ // Noop
+ } else if (propKey === AUTOFOCUS) {
+ // We polyfill it separately on the client during commit.
+ // We blacklist it here rather than in the property list because we emit it in SSR.
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
+ if (nextProp != null) {
+ if (true && typeof nextProp !== 'function') {
+ warnForInvalidEventListener(propKey, nextProp);
+ }
+ ensureListeningTo(rootContainerElement, propKey);
+ }
+ } else if (isCustomComponentTag) {
+ setValueForAttribute(domElement, propKey, nextProp);
+ } else if (nextProp != null) {
+ // If we're updating to null or undefined, we should remove the property
+ // from the DOM node instead of inadvertently setting to a string. This
+ // brings us in line with the same behavior we have on initial render.
+ setValueForProperty(domElement, propKey, nextProp);
+ }
+ }
+}
+function updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag) {
+ // TODO: Handle wasCustomComponentTag
+ for (var i = 0; i < updatePayload.length; i += 2) {
+ var propKey = updatePayload[i];
+ var propValue = updatePayload[i + 1];
+ if (propKey === STYLE) {
+ setValueForStyles(domElement, propValue, getStack);
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
+ setInnerHTML(domElement, propValue);
+ } else if (propKey === CHILDREN) {
+ setTextContent(domElement, propValue);
+ } else if (isCustomComponentTag) {
+ if (propValue != null) {
+ setValueForAttribute(domElement, propKey, propValue);
+ } else {
+ deleteValueForAttribute(domElement, propKey);
+ }
+ } else if (propValue != null) {
+ setValueForProperty(domElement, propKey, propValue);
+ } else {
+ // If we're updating to null or undefined, we should remove the property
+ // from the DOM node instead of inadvertently setting to a string. This
+ // brings us in line with the same behavior we have on initial render.
+ deleteValueForProperty(domElement, propKey);
+ }
+ }
+}
+function createElement$1(type, props, rootContainerElement, parentNamespace) {
+ // We create tags in the namespace of their parent container, except HTML
+ var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement);
+ var domElement;
+ var namespaceURI = parentNamespace;
+ if (namespaceURI === HTML_NAMESPACE) {
+ namespaceURI = getIntrinsicNamespace(type);
+ }
+ if (namespaceURI === HTML_NAMESPACE) {
+ {
+ var isCustomComponentTag = isCustomComponent(type, props);
+ // Should this check be gated by parent namespace? Not sure we want to
+ // allow <SVG> or <mATH>.
+ warning_1(isCustomComponentTag || type === type.toLowerCase(), '<%s /> is using uppercase HTML. Always use lowercase HTML tags ' + 'in React.', type);
+ }
+
+ if (type === 'script') {
+ // Create the script via .innerHTML so its "parser-inserted" flag is
+ // set to true and it does not execute
+ var div = ownerDocument.createElement('div');
+ div.innerHTML = '<script><' + '/script>'; // eslint-disable-line
+ // This is guaranteed to yield a script element.
+ var firstChild = div.firstChild;
+ domElement = div.removeChild(firstChild);
+ } else if (typeof props.is === 'string') {
+ // $FlowIssue `createElement` should be updated for Web Components
+ domElement = ownerDocument.createElement(type, { is: props.is });
+ } else {
+ // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
+ // See discussion in https://github.com/facebook/react/pull/6896
+ // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
+ domElement = ownerDocument.createElement(type);
+ }
+ } else {
+ domElement = ownerDocument.createElementNS(namespaceURI, type);
+ }
+ {
+ if (namespaceURI === HTML_NAMESPACE) {
+ if (!isCustomComponentTag && Object.prototype.toString.call(domElement) === '[object HTMLUnknownElement]' && !Object.prototype.hasOwnProperty.call(warnedUnknownTags, type)) {
+ warnedUnknownTags[type] = true;
+ warning_1(false, 'The tag <%s> is unrecognized in this browser. ' + 'If you meant to render a React component, start its name with ' + 'an uppercase letter.', type);
+ }
+ }
+ }
+ return domElement;
+}
-var skipSelectionChangeEvent = ExecutionEnvironment_1.canUseDOM && 'documentMode' in document && document.documentMode <= 11;
+function createTextNode$1(text, rootContainerElement) {
+ return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(text);
+}
-var eventTypes$3 = {
- select: {
- phasedRegistrationNames: {
- bubbled: 'onSelect',
- captured: 'onSelectCapture'
- },
- dependencies: ['topBlur', 'topContextMenu', 'topFocus', 'topKeyDown', 'topKeyUp', 'topMouseDown', 'topMouseUp', 'topSelectionChange']
+function setInitialProperties$1(domElement, tag, rawProps, rootContainerElement) {
+ var isCustomComponentTag = isCustomComponent(tag, rawProps);
+ {
+ validatePropertiesInDevelopment(tag, rawProps);
+ if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
+ warning_1(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName$1() || 'A component');
+ didWarnShadyDOM = true;
+ }
}
-};
-var activeElement$1 = null;
-var activeElementInst$1 = null;
-var lastSelection = null;
-var mouseDown = false;
+ // TODO: Make sure that we check isMounted before firing any of these events.
+ var props;
+ switch (tag) {
+ case 'iframe':
+ case 'object':
+ trapBubbledEvent('topLoad', 'load', domElement);
+ props = rawProps;
+ break;
+ case 'video':
+ case 'audio':
+ // Create listener for each media event
+ for (var event in mediaEvents) {
+ if (mediaEvents.hasOwnProperty(event)) {
+ trapBubbledEvent(event, mediaEvents[event], domElement);
+ }
+ }
+ props = rawProps;
+ break;
+ case 'source':
+ trapBubbledEvent('topError', 'error', domElement);
+ props = rawProps;
+ break;
+ case 'img':
+ case 'image':
+ trapBubbledEvent('topError', 'error', domElement);
+ trapBubbledEvent('topLoad', 'load', domElement);
+ props = rawProps;
+ break;
+ case 'form':
+ trapBubbledEvent('topReset', 'reset', domElement);
+ trapBubbledEvent('topSubmit', 'submit', domElement);
+ props = rawProps;
+ break;
+ case 'details':
+ trapBubbledEvent('topToggle', 'toggle', domElement);
+ props = rawProps;
+ break;
+ case 'input':
+ initWrapperState(domElement, rawProps);
+ props = getHostProps(domElement, rawProps);
+ trapBubbledEvent('topInvalid', 'invalid', domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ case 'option':
+ validateProps(domElement, rawProps);
+ props = getHostProps$1(domElement, rawProps);
+ break;
+ case 'select':
+ initWrapperState$1(domElement, rawProps);
+ props = getHostProps$2(domElement, rawProps);
+ trapBubbledEvent('topInvalid', 'invalid', domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ case 'textarea':
+ initWrapperState$2(domElement, rawProps);
+ props = getHostProps$3(domElement, rawProps);
+ trapBubbledEvent('topInvalid', 'invalid', domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ default:
+ props = rawProps;
+ }
-// Track whether all listeners exists for this plugin. If none exist, we do
-// not extract events. See #3639.
-var isListeningToAllDependencies = ReactBrowserEventEmitter_1.isListeningToAllDependencies;
+ assertValidProps(tag, props, getStack);
-/**
- * Get an object which is a unique representation of the current selection.
- *
- * The return value will not be consistent across nodes or browsers, but
- * two identical selections on the same node will return identical objects.
- *
- * @param {DOMElement} node
- * @return {object}
- */
-function getSelection(node) {
- if ('selectionStart' in node && ReactInputSelection_1.hasSelectionCapabilities(node)) {
- return {
- start: node.selectionStart,
- end: node.selectionEnd
- };
- } else if (window.getSelection) {
- var selection = window.getSelection();
- return {
- anchorNode: selection.anchorNode,
- anchorOffset: selection.anchorOffset,
- focusNode: selection.focusNode,
- focusOffset: selection.focusOffset
- };
+ setInitialDOMProperties(tag, domElement, rootContainerElement, props, isCustomComponentTag);
+
+ switch (tag) {
+ case 'input':
+ // TODO: Make sure we check if this is still unmounted or do any clean
+ // up necessary since we never stop tracking anymore.
+ track(domElement);
+ postMountWrapper(domElement, rawProps);
+ break;
+ case 'textarea':
+ // TODO: Make sure we check if this is still unmounted or do any clean
+ // up necessary since we never stop tracking anymore.
+ track(domElement);
+ postMountWrapper$3(domElement, rawProps);
+ break;
+ case 'option':
+ postMountWrapper$1(domElement, rawProps);
+ break;
+ case 'select':
+ postMountWrapper$2(domElement, rawProps);
+ break;
+ default:
+ if (typeof props.onClick === 'function') {
+ // TODO: This cast may not be sound for SVG, MathML or custom elements.
+ trapClickOnNonInteractiveElement(domElement);
+ }
+ break;
}
}
-/**
- * Poll selection to see whether it's changed.
- *
- * @param {object} nativeEvent
- * @return {?SyntheticEvent}
- */
-function constructSelectEvent(nativeEvent, nativeEventTarget) {
- // Ensure we have the right element, and that the user is not dragging a
- // selection (this matches native `select` event behavior). In HTML5, select
- // fires only on input and textarea thus if there's no focused element we
- // won't dispatch.
- if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement_1()) {
- return null;
+// Calculate the diff between the two objects.
+function diffProperties$1(domElement, tag, lastRawProps, nextRawProps, rootContainerElement) {
+ {
+ validatePropertiesInDevelopment(tag, nextRawProps);
}
- // Only fire when selection has actually changed.
- var currentSelection = getSelection(activeElement$1);
- if (!lastSelection || !shallowEqual_1(lastSelection, currentSelection)) {
- lastSelection = currentSelection;
-
- var syntheticEvent = SyntheticEvent_1.getPooled(eventTypes$3.select, activeElementInst$1, nativeEvent, nativeEventTarget);
-
- syntheticEvent.type = 'select';
- syntheticEvent.target = activeElement$1;
+ var updatePayload = null;
- EventPropagators_1.accumulateTwoPhaseDispatches(syntheticEvent);
-
- return syntheticEvent;
+ var lastProps;
+ var nextProps;
+ switch (tag) {
+ case 'input':
+ lastProps = getHostProps(domElement, lastRawProps);
+ nextProps = getHostProps(domElement, nextRawProps);
+ updatePayload = [];
+ break;
+ case 'option':
+ lastProps = getHostProps$1(domElement, lastRawProps);
+ nextProps = getHostProps$1(domElement, nextRawProps);
+ updatePayload = [];
+ break;
+ case 'select':
+ lastProps = getHostProps$2(domElement, lastRawProps);
+ nextProps = getHostProps$2(domElement, nextRawProps);
+ updatePayload = [];
+ break;
+ case 'textarea':
+ lastProps = getHostProps$3(domElement, lastRawProps);
+ nextProps = getHostProps$3(domElement, nextRawProps);
+ updatePayload = [];
+ break;
+ default:
+ lastProps = lastRawProps;
+ nextProps = nextRawProps;
+ if (typeof lastProps.onClick !== 'function' && typeof nextProps.onClick === 'function') {
+ // TODO: This cast may not be sound for SVG, MathML or custom elements.
+ trapClickOnNonInteractiveElement(domElement);
+ }
+ break;
}
- return null;
-}
-
-/**
- * This plugin creates an `onSelect` event that normalizes select events
- * across form elements.
- *
- * Supported elements are:
- * - input (see `isTextInputElement`)
- * - textarea
- * - contentEditable
- *
- * This differs from native browser implementations in the following ways:
- * - Fires on contentEditable fields as well as inputs.
- * - Fires for collapsed selection.
- * - Fires after user input.
- */
-var SelectEventPlugin = {
- eventTypes: eventTypes$3,
+ assertValidProps(tag, nextProps, getStack);
- extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- var doc = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget.document : nativeEventTarget.nodeType === DOCUMENT_NODE$2 ? nativeEventTarget : nativeEventTarget.ownerDocument;
- if (!doc || !isListeningToAllDependencies('onSelect', doc)) {
- return null;
+ var propKey;
+ var styleName;
+ var styleUpdates = null;
+ for (propKey in lastProps) {
+ if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
+ continue;
}
-
- var targetNode = targetInst ? ReactDOMComponentTree_1.getNodeFromInstance(targetInst) : window;
-
- switch (topLevelType) {
- // Track the input node that has focus.
- case 'topFocus':
- if (isTextInputElement_1(targetNode) || targetNode.contentEditable === 'true') {
- activeElement$1 = targetNode;
- activeElementInst$1 = targetInst;
- lastSelection = null;
+ if (propKey === STYLE) {
+ var lastStyle = lastProps[propKey];
+ for (styleName in lastStyle) {
+ if (lastStyle.hasOwnProperty(styleName)) {
+ if (!styleUpdates) {
+ styleUpdates = {};
+ }
+ styleUpdates[styleName] = '';
}
- break;
- case 'topBlur':
- activeElement$1 = null;
- activeElementInst$1 = null;
- lastSelection = null;
- break;
- // Don't fire the event while the user is dragging. This matches the
- // semantics of the native select event.
- case 'topMouseDown':
- mouseDown = true;
- break;
- case 'topContextMenu':
- case 'topMouseUp':
- mouseDown = false;
- return constructSelectEvent(nativeEvent, nativeEventTarget);
- // Chrome and IE fire non-standard event when selection is changed (and
- // sometimes when it hasn't). IE's event fires out of order with respect
- // to key and input events on deletion, so we discard it.
- //
- // Firefox doesn't support selectionchange, so check selection status
- // after each key entry. The selection changes after keydown and before
- // keyup, but we check on keydown as well in the case of holding down a
- // key, when multiple keydown events are fired but only one keyup is.
- // This is also our approach for IE handling, for the reason above.
- case 'topSelectionChange':
- if (skipSelectionChangeEvent) {
- break;
+ }
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN) {
+ // Noop. This is handled by the clear text mechanism.
+ } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
+ // Noop
+ } else if (propKey === AUTOFOCUS) {
+ // Noop. It doesn't work on updates anyway.
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
+ // This is a special case. If any listener updates we need to ensure
+ // that the "current" fiber pointer gets updated so we need a commit
+ // to update this element.
+ if (!updatePayload) {
+ updatePayload = [];
+ }
+ } else {
+ // For all other deleted properties we add it to the queue. We use
+ // the whitelist in the commit phase instead.
+ (updatePayload = updatePayload || []).push(propKey, null);
+ }
+ }
+ for (propKey in nextProps) {
+ var nextProp = nextProps[propKey];
+ var lastProp = lastProps != null ? lastProps[propKey] : undefined;
+ if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
+ continue;
+ }
+ if (propKey === STYLE) {
+ {
+ if (nextProp) {
+ // Freeze the next style object so that we can assume it won't be
+ // mutated. We have already warned for this in the past.
+ Object.freeze(nextProp);
}
- // falls through
- case 'topKeyDown':
- case 'topKeyUp':
- return constructSelectEvent(nativeEvent, nativeEventTarget);
+ }
+ if (lastProp) {
+ // Unset styles on `lastProp` but not on `nextProp`.
+ for (styleName in lastProp) {
+ if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
+ if (!styleUpdates) {
+ styleUpdates = {};
+ }
+ styleUpdates[styleName] = '';
+ }
+ }
+ // Update styles that changed since `lastProp`.
+ for (styleName in nextProp) {
+ if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
+ if (!styleUpdates) {
+ styleUpdates = {};
+ }
+ styleUpdates[styleName] = nextProp[styleName];
+ }
+ }
+ } else {
+ // Relies on `updateStylesByID` not mutating `styleUpdates`.
+ if (!styleUpdates) {
+ if (!updatePayload) {
+ updatePayload = [];
+ }
+ updatePayload.push(propKey, styleUpdates);
+ }
+ styleUpdates = nextProp;
+ }
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
+ var nextHtml = nextProp ? nextProp[HTML] : undefined;
+ var lastHtml = lastProp ? lastProp[HTML] : undefined;
+ if (nextHtml != null) {
+ if (lastHtml !== nextHtml) {
+ (updatePayload = updatePayload || []).push(propKey, '' + nextHtml);
+ }
+ } else {
+ // TODO: It might be too late to clear this if we have children
+ // inserted already.
+ }
+ } else if (propKey === CHILDREN) {
+ if (lastProp !== nextProp && (typeof nextProp === 'string' || typeof nextProp === 'number')) {
+ (updatePayload = updatePayload || []).push(propKey, '' + nextProp);
+ }
+ } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
+ // Noop
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
+ if (nextProp != null) {
+ // We eagerly listen to this even though we haven't committed yet.
+ if (true && typeof nextProp !== 'function') {
+ warnForInvalidEventListener(propKey, nextProp);
+ }
+ ensureListeningTo(rootContainerElement, propKey);
+ }
+ if (!updatePayload && lastProp !== nextProp) {
+ // This is a special case. If any listener updates we need to ensure
+ // that the "current" props pointer gets updated so we need a commit
+ // to update this element.
+ updatePayload = [];
+ }
+ } else {
+ // For any other property we always add it to the queue and then we
+ // filter it out using the whitelist during the commit.
+ (updatePayload = updatePayload || []).push(propKey, nextProp);
}
-
- return null;
}
-};
-
-var SelectEventPlugin_1 = SelectEventPlugin;
-
-/**
- * @interface Event
- * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
- * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
- */
-var AnimationEventInterface = {
- animationName: null,
- elapsedTime: null,
- pseudoElement: null
-};
-
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticEvent}
- */
-function SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+ if (styleUpdates) {
+ (updatePayload = updatePayload || []).push(STYLE, styleUpdates);
+ }
+ return updatePayload;
}
-SyntheticEvent_1.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);
+// Apply the diff.
+function updateProperties$1(domElement, updatePayload, tag, lastRawProps, nextRawProps) {
+ // Update checked *before* name.
+ // In the middle of an update, it is possible to have multiple checked.
+ // When a checked radio tries to change name, browser makes another radio's checked false.
+ if (tag === 'input' && nextRawProps.type === 'radio' && nextRawProps.name != null) {
+ updateChecked(domElement, nextRawProps);
+ }
-var SyntheticAnimationEvent_1 = SyntheticAnimationEvent;
+ var wasCustomComponentTag = isCustomComponent(tag, lastRawProps);
+ var isCustomComponentTag = isCustomComponent(tag, nextRawProps);
+ // Apply the diff.
+ updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag);
-/**
- * @interface Event
- * @see http://www.w3.org/TR/clipboard-apis/
- */
-var ClipboardEventInterface = {
- clipboardData: function (event) {
- return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
+ // TODO: Ensure that an update gets scheduled if any of the special props
+ // changed.
+ switch (tag) {
+ case 'input':
+ // Update the wrapper around inputs *after* updating props. This has to
+ // happen after `updateDOMProperties`. Otherwise HTML5 input validations
+ // raise warnings and prevent the new value from being assigned.
+ updateWrapper(domElement, nextRawProps);
+ break;
+ case 'textarea':
+ updateWrapper$1(domElement, nextRawProps);
+ break;
+ case 'select':
+ // <select> value update needs to occur after <option> children
+ // reconciliation
+ postUpdateWrapper(domElement, nextRawProps);
+ break;
}
-};
-
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticUIEvent}
- */
-function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}
-SyntheticEvent_1.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);
-
-var SyntheticClipboardEvent_1 = SyntheticClipboardEvent;
-
-/**
- * @interface FocusEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
-var FocusEventInterface = {
- relatedTarget: null
-};
-
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticUIEvent}
- */
-function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticUIEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
-}
+function diffHydratedProperties$1(domElement, tag, rawProps, parentNamespace, rootContainerElement) {
+ {
+ var suppressHydrationWarning = rawProps[SUPPRESS_HYDRATION_WARNING$1] === true;
+ var isCustomComponentTag = isCustomComponent(tag, rawProps);
+ validatePropertiesInDevelopment(tag, rawProps);
+ if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
+ warning_1(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName$1() || 'A component');
+ didWarnShadyDOM = true;
+ }
+ }
-SyntheticUIEvent_1.augmentClass(SyntheticFocusEvent, FocusEventInterface);
+ // TODO: Make sure that we check isMounted before firing any of these events.
+ switch (tag) {
+ case 'iframe':
+ case 'object':
+ trapBubbledEvent('topLoad', 'load', domElement);
+ break;
+ case 'video':
+ case 'audio':
+ // Create listener for each media event
+ for (var event in mediaEvents) {
+ if (mediaEvents.hasOwnProperty(event)) {
+ trapBubbledEvent(event, mediaEvents[event], domElement);
+ }
+ }
+ break;
+ case 'source':
+ trapBubbledEvent('topError', 'error', domElement);
+ break;
+ case 'img':
+ case 'image':
+ trapBubbledEvent('topError', 'error', domElement);
+ trapBubbledEvent('topLoad', 'load', domElement);
+ break;
+ case 'form':
+ trapBubbledEvent('topReset', 'reset', domElement);
+ trapBubbledEvent('topSubmit', 'submit', domElement);
+ break;
+ case 'details':
+ trapBubbledEvent('topToggle', 'toggle', domElement);
+ break;
+ case 'input':
+ initWrapperState(domElement, rawProps);
+ trapBubbledEvent('topInvalid', 'invalid', domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ case 'option':
+ validateProps(domElement, rawProps);
+ break;
+ case 'select':
+ initWrapperState$1(domElement, rawProps);
+ trapBubbledEvent('topInvalid', 'invalid', domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ case 'textarea':
+ initWrapperState$2(domElement, rawProps);
+ trapBubbledEvent('topInvalid', 'invalid', domElement);
+ // For controlled components we always need to ensure we're listening
+ // to onChange. Even if there is no listener.
+ ensureListeningTo(rootContainerElement, 'onChange');
+ break;
+ }
-var SyntheticFocusEvent_1 = SyntheticFocusEvent;
+ assertValidProps(tag, rawProps, getStack);
-/**
- * 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.
- *
- * @providesModule getEventCharCode
- */
+ {
+ var extraAttributeNames = new Set();
+ var attributes = domElement.attributes;
+ for (var i = 0; i < attributes.length; i++) {
+ var name = attributes[i].name.toLowerCase();
+ switch (name) {
+ // Built-in SSR attribute is whitelisted
+ case 'data-reactroot':
+ break;
+ // Controlled attributes are not validated
+ // TODO: Only ignore them on controlled tags.
+ case 'value':
+ break;
+ case 'checked':
+ break;
+ case 'selected':
+ break;
+ default:
+ // Intentionally use the original name.
+ // See discussion in https://github.com/facebook/react/pull/10676.
+ extraAttributeNames.add(attributes[i].name);
+ }
+ }
+ }
-/**
- * `charCode` represents the actual "character code" and is safe to use with
- * `String.fromCharCode`. As such, only keys that correspond to printable
- * characters produce a valid `charCode`, the only exception to this is Enter.
- * The Tab-key is considered non-printable and does not have a `charCode`,
- * presumably because it does not produce a tab-character in browsers.
- *
- * @param {object} nativeEvent Native browser event.
- * @return {number} Normalized `charCode` property.
- */
+ var updatePayload = null;
+ for (var propKey in rawProps) {
+ if (!rawProps.hasOwnProperty(propKey)) {
+ continue;
+ }
+ var nextProp = rawProps[propKey];
+ if (propKey === CHILDREN) {
+ // For text content children we compare against textContent. This
+ // might match additional HTML that is hidden when we read it using
+ // textContent. E.g. "foo" will match "f<span>oo</span>" but that still
+ // satisfies our requirement. Our requirement is not to produce perfect
+ // HTML and attributes. Ideally we should preserve structure but it's
+ // ok not to if the visible content is still enough to indicate what
+ // even listeners these nodes might be wired up to.
+ // TODO: Warn if there is more than a single textNode as a child.
+ // TODO: Should we use domElement.firstChild.nodeValue to compare?
+ if (typeof nextProp === 'string') {
+ if (domElement.textContent !== nextProp) {
+ if (true && !suppressHydrationWarning) {
+ warnForTextDifference(domElement.textContent, nextProp);
+ }
+ updatePayload = [CHILDREN, nextProp];
+ }
+ } else if (typeof nextProp === 'number') {
+ if (domElement.textContent !== '' + nextProp) {
+ if (true && !suppressHydrationWarning) {
+ warnForTextDifference(domElement.textContent, nextProp);
+ }
+ updatePayload = [CHILDREN, '' + nextProp];
+ }
+ }
+ } else if (registrationNameModules.hasOwnProperty(propKey)) {
+ if (nextProp != null) {
+ if (true && typeof nextProp !== 'function') {
+ warnForInvalidEventListener(propKey, nextProp);
+ }
+ ensureListeningTo(rootContainerElement, propKey);
+ }
+ } else {
+ // Validate that the properties correspond to their expected values.
+ var serverValue;
+ var propertyInfo;
+ if (suppressHydrationWarning) {
+ // Don't bother comparing. We're ignoring all these warnings.
+ } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1 ||
+ // Controlled attributes are not validated
+ // TODO: Only ignore them on controlled tags.
+ propKey === 'value' || propKey === 'checked' || propKey === 'selected') {
+ // Noop
+ } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
+ var rawHtml = nextProp ? nextProp[HTML] || '' : '';
+ var serverHTML = domElement.innerHTML;
+ var expectedHTML = normalizeHTML(domElement, rawHtml);
+ if (expectedHTML !== serverHTML) {
+ warnForPropDifference(propKey, serverHTML, expectedHTML);
+ }
+ } else if (propKey === STYLE) {
+ // $FlowFixMe - Should be inferred as not undefined.
+ extraAttributeNames['delete'](propKey);
+ var expectedStyle = createDangerousStringForStyles(nextProp);
+ serverValue = domElement.getAttribute('style');
+ if (expectedStyle !== serverValue) {
+ warnForPropDifference(propKey, serverValue, expectedStyle);
+ }
+ } else if (isCustomComponentTag) {
+ // $FlowFixMe - Should be inferred as not undefined.
+ extraAttributeNames['delete'](propKey.toLowerCase());
+ serverValue = getValueForAttribute(domElement, propKey, nextProp);
-function getEventCharCode(nativeEvent) {
- var charCode;
- var keyCode = nativeEvent.keyCode;
+ if (nextProp !== serverValue) {
+ warnForPropDifference(propKey, serverValue, nextProp);
+ }
+ } else if (shouldSetAttribute(propKey, nextProp)) {
+ if (propertyInfo = getPropertyInfo(propKey)) {
+ // $FlowFixMe - Should be inferred as not undefined.
+ extraAttributeNames['delete'](propertyInfo.attributeName);
+ serverValue = getValueForProperty(domElement, propKey, nextProp);
+ } else {
+ var ownNamespace = parentNamespace;
+ if (ownNamespace === HTML_NAMESPACE) {
+ ownNamespace = getIntrinsicNamespace(tag);
+ }
+ if (ownNamespace === HTML_NAMESPACE) {
+ // $FlowFixMe - Should be inferred as not undefined.
+ extraAttributeNames['delete'](propKey.toLowerCase());
+ } else {
+ // $FlowFixMe - Should be inferred as not undefined.
+ extraAttributeNames['delete'](propKey);
+ }
+ serverValue = getValueForAttribute(domElement, propKey, nextProp);
+ }
- if ('charCode' in nativeEvent) {
- charCode = nativeEvent.charCode;
+ if (nextProp !== serverValue) {
+ warnForPropDifference(propKey, serverValue, nextProp);
+ }
+ }
+ }
+ }
- // FF does not set `charCode` for the Enter-key, check against `keyCode`.
- if (charCode === 0 && keyCode === 13) {
- charCode = 13;
+ {
+ // $FlowFixMe - Should be inferred as not undefined.
+ if (extraAttributeNames.size > 0 && !suppressHydrationWarning) {
+ // $FlowFixMe - Should be inferred as not undefined.
+ warnForExtraAttributes(extraAttributeNames);
}
- } else {
- // IE8 does not implement `charCode`, but `keyCode` has the correct value.
- charCode = keyCode;
}
- // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
- // Must not discard the (non-)printable Enter-key.
- if (charCode >= 32 || charCode === 13) {
- return charCode;
+ switch (tag) {
+ case 'input':
+ // TODO: Make sure we check if this is still unmounted or do any clean
+ // up necessary since we never stop tracking anymore.
+ track(domElement);
+ postMountWrapper(domElement, rawProps);
+ break;
+ case 'textarea':
+ // TODO: Make sure we check if this is still unmounted or do any clean
+ // up necessary since we never stop tracking anymore.
+ track(domElement);
+ postMountWrapper$3(domElement, rawProps);
+ break;
+ case 'select':
+ case 'option':
+ // For input and textarea we current always set the value property at
+ // post mount to force it to diverge from attributes. However, for
+ // option and select we don't quite do the same thing and select
+ // is not resilient to the DOM state changing so we don't do that here.
+ // TODO: Consider not doing this for input and textarea.
+ break;
+ default:
+ if (typeof rawProps.onClick === 'function') {
+ // TODO: This cast may not be sound for SVG, MathML or custom elements.
+ trapClickOnNonInteractiveElement(domElement);
+ }
+ break;
}
- return 0;
+ return updatePayload;
}
-var getEventCharCode_1 = getEventCharCode;
-
-/**
- * Normalization of deprecated HTML5 `key` values
- * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
- */
-var normalizeKey = {
- Esc: 'Escape',
- Spacebar: ' ',
- Left: 'ArrowLeft',
- Up: 'ArrowUp',
- Right: 'ArrowRight',
- Down: 'ArrowDown',
- Del: 'Delete',
- Win: 'OS',
- Menu: 'ContextMenu',
- Apps: 'ContextMenu',
- Scroll: 'ScrollLock',
- MozPrintableKey: 'Unidentified'
-};
-
-/**
- * Translation from legacy `keyCode` to HTML5 `key`
- * Only special keys supported, all others depend on keyboard layout or browser
- * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
- */
-var translateToKey = {
- 8: 'Backspace',
- 9: 'Tab',
- 12: 'Clear',
- 13: 'Enter',
- 16: 'Shift',
- 17: 'Control',
- 18: 'Alt',
- 19: 'Pause',
- 20: 'CapsLock',
- 27: 'Escape',
- 32: ' ',
- 33: 'PageUp',
- 34: 'PageDown',
- 35: 'End',
- 36: 'Home',
- 37: 'ArrowLeft',
- 38: 'ArrowUp',
- 39: 'ArrowRight',
- 40: 'ArrowDown',
- 45: 'Insert',
- 46: 'Delete',
- 112: 'F1',
- 113: 'F2',
- 114: 'F3',
- 115: 'F4',
- 116: 'F5',
- 117: 'F6',
- 118: 'F7',
- 119: 'F8',
- 120: 'F9',
- 121: 'F10',
- 122: 'F11',
- 123: 'F12',
- 144: 'NumLock',
- 145: 'ScrollLock',
- 224: 'Meta'
-};
+function diffHydratedText$1(textNode, text) {
+ var isDifferent = textNode.nodeValue !== text;
+ return isDifferent;
+}
-/**
- * @param {object} nativeEvent Native browser event.
- * @return {string} Normalized `key` property.
- */
-function getEventKey(nativeEvent) {
- if (nativeEvent.key) {
- // Normalize inconsistent values reported by browsers due to
- // implementations of a working draft specification.
+function warnForUnmatchedText$1(textNode, text) {
+ {
+ warnForTextDifference(textNode.nodeValue, text);
+ }
+}
- // FireFox implements `key` but returns `MozPrintableKey` for all
- // printable characters (normalized to `Unidentified`), ignore it.
- var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
- if (key !== 'Unidentified') {
- return key;
+function warnForDeletedHydratableElement$1(parentNode, child) {
+ {
+ if (didWarnInvalidHydration) {
+ return;
}
+ didWarnInvalidHydration = true;
+ warning_1(false, 'Did not expect server HTML to contain a <%s> in <%s>.', child.nodeName.toLowerCase(), parentNode.nodeName.toLowerCase());
}
+}
- // Browser does not implement `key`, polyfill as much of it as we can.
- if (nativeEvent.type === 'keypress') {
- var charCode = getEventCharCode_1(nativeEvent);
-
- // The enter-key is technically both printable and non-printable and can
- // thus be captured by `keypress`, no other non-printable key should.
- return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
- }
- if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
- // While user keyboard layout determines the actual meaning of each
- // `keyCode` value, almost all function keys have a universal value.
- return translateToKey[nativeEvent.keyCode] || 'Unidentified';
+function warnForDeletedHydratableText$1(parentNode, child) {
+ {
+ if (didWarnInvalidHydration) {
+ return;
+ }
+ didWarnInvalidHydration = true;
+ warning_1(false, 'Did not expect server HTML to contain the text node "%s" in <%s>.', child.nodeValue, parentNode.nodeName.toLowerCase());
}
- return '';
}
-var getEventKey_1 = getEventKey;
-
-/**
- * @interface KeyboardEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
-var KeyboardEventInterface = {
- key: getEventKey_1,
- location: null,
- ctrlKey: null,
- shiftKey: null,
- altKey: null,
- metaKey: null,
- repeat: null,
- locale: null,
- getModifierState: getEventModifierState_1,
- // Legacy Interface
- charCode: function (event) {
- // `charCode` is the result of a KeyPress event and represents the value of
- // the actual printable character.
-
- // KeyPress is deprecated, but its replacement is not yet final and not
- // implemented in any major browser. Only KeyPress has charCode.
- if (event.type === 'keypress') {
- return getEventCharCode_1(event);
+function warnForInsertedHydratedElement$1(parentNode, tag, props) {
+ {
+ if (didWarnInvalidHydration) {
+ return;
}
- return 0;
- },
- keyCode: function (event) {
- // `keyCode` is the result of a KeyDown/Up event and represents the value of
- // physical keyboard key.
+ didWarnInvalidHydration = true;
+ warning_1(false, 'Expected server HTML to contain a matching <%s> in <%s>.', tag, parentNode.nodeName.toLowerCase());
+ }
+}
- // The actual meaning of the value depends on the users' keyboard layout
- // which cannot be detected. Assuming that it is a US keyboard layout
- // provides a surprisingly accurate mapping for US and European users.
- // Due to this, it is left to the user to implement at this time.
- if (event.type === 'keydown' || event.type === 'keyup') {
- return event.keyCode;
- }
- return 0;
- },
- which: function (event) {
- // `which` is an alias for either `keyCode` or `charCode` depending on the
- // type of the event.
- if (event.type === 'keypress') {
- return getEventCharCode_1(event);
+function warnForInsertedHydratedText$1(parentNode, text) {
+ {
+ if (text === '') {
+ // We expect to insert empty text nodes since they're not represented in
+ // the HTML.
+ // TODO: Remove this special case if we can just avoid inserting empty
+ // text nodes.
+ return;
}
- if (event.type === 'keydown' || event.type === 'keyup') {
- return event.keyCode;
+ if (didWarnInvalidHydration) {
+ return;
}
- return 0;
+ didWarnInvalidHydration = true;
+ warning_1(false, 'Expected server HTML to contain a matching text node for "%s" in <%s>.', text, parentNode.nodeName.toLowerCase());
}
-};
-
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticUIEvent}
- */
-function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticUIEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
}
-SyntheticUIEvent_1.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);
-
-var SyntheticKeyboardEvent_1 = SyntheticKeyboardEvent;
-
-/**
- * @interface DragEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
-var DragEventInterface = {
- dataTransfer: null
-};
-
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticUIEvent}
- */
-function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticMouseEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
+function restoreControlledState(domElement, tag, props) {
+ switch (tag) {
+ case 'input':
+ restoreControlledState$1(domElement, props);
+ return;
+ case 'textarea':
+ restoreControlledState$3(domElement, props);
+ return;
+ case 'select':
+ restoreControlledState$2(domElement, props);
+ return;
+ }
}
-SyntheticMouseEvent_1.augmentClass(SyntheticDragEvent, DragEventInterface);
-
-var SyntheticDragEvent_1 = SyntheticDragEvent;
-
-/**
- * @interface TouchEvent
- * @see http://www.w3.org/TR/touch-events/
- */
-var TouchEventInterface = {
- touches: null,
- targetTouches: null,
- changedTouches: null,
- altKey: null,
- metaKey: null,
- ctrlKey: null,
- shiftKey: null,
- getModifierState: getEventModifierState_1
-};
+var ReactDOMFiberComponent = Object.freeze({
+ createElement: createElement$1,
+ createTextNode: createTextNode$1,
+ setInitialProperties: setInitialProperties$1,
+ diffProperties: diffProperties$1,
+ updateProperties: updateProperties$1,
+ diffHydratedProperties: diffHydratedProperties$1,
+ diffHydratedText: diffHydratedText$1,
+ warnForUnmatchedText: warnForUnmatchedText$1,
+ warnForDeletedHydratableElement: warnForDeletedHydratableElement$1,
+ warnForDeletedHydratableText: warnForDeletedHydratableText$1,
+ warnForInsertedHydratedElement: warnForInsertedHydratedElement$1,
+ warnForInsertedHydratedText: warnForInsertedHydratedText$1,
+ restoreControlledState: restoreControlledState
+});
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticUIEvent}
- */
-function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticUIEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
-}
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+var getCurrentFiberStackAddendum$6 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
-SyntheticUIEvent_1.augmentClass(SyntheticTouchEvent, TouchEventInterface);
+var validateDOMNesting = emptyFunction_1;
-var SyntheticTouchEvent_1 = SyntheticTouchEvent;
+{
+ // This validation code was written based on the HTML5 parsing spec:
+ // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
+ //
+ // Note: this does not catch all invalid nesting, nor does it try to (as it's
+ // not clear what practical benefit doing so provides); instead, we warn only
+ // for cases where the parser will give a parse tree differing from what React
+ // intended. For example, <b><div></div></b> is invalid but we don't warn
+ // because it still parses correctly; we do warn for other cases like nested
+ // <p> tags where the beginning of the second element implicitly closes the
+ // first, causing a confusing mess.
-/**
- * @interface Event
- * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
- * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
- */
-var TransitionEventInterface = {
- propertyName: null,
- elapsedTime: null,
- pseudoElement: null
-};
+ // https://html.spec.whatwg.org/multipage/syntax.html#special
+ var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticEvent}
- */
-function SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
-}
+ // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
+ var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
-SyntheticEvent_1.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);
+ // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
+ // TODO: Distinguish by namespace here -- for <title>, including it here
+ // errs on the side of fewer warnings
+ 'foreignObject', 'desc', 'title'];
-var SyntheticTransitionEvent_1 = SyntheticTransitionEvent;
+ // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
+ var buttonScopeTags = inScopeTags.concat(['button']);
-/**
- * @interface WheelEvent
- * @see http://www.w3.org/TR/DOM-Level-3-Events/
- */
-var WheelEventInterface = {
- deltaX: function (event) {
- return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
- 'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
- },
- deltaY: function (event) {
- return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
- 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
- 'wheelDelta' in event ? -event.wheelDelta : 0;
- },
- deltaZ: null,
+ // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
+ var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
- // Browsers without "deltaMode" is reporting in raw wheel delta where one
- // notch on the scroll is always +/- 120, roughly equivalent to pixels.
- // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
- // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
- deltaMode: null
-};
+ var emptyAncestorInfo = {
+ current: null,
-/**
- * @param {object} dispatchConfig Configuration used to dispatch this event.
- * @param {string} dispatchMarker Marker identifying the event target.
- * @param {object} nativeEvent Native browser event.
- * @extends {SyntheticMouseEvent}
- */
-function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
- return SyntheticMouseEvent_1.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
-}
+ formTag: null,
+ aTagInScope: null,
+ buttonTagInScope: null,
+ nobrTagInScope: null,
+ pTagInButtonScope: null,
-SyntheticMouseEvent_1.augmentClass(SyntheticWheelEvent, WheelEventInterface);
+ listItemTagAutoclosing: null,
+ dlItemTagAutoclosing: null
+ };
-var SyntheticWheelEvent_1 = SyntheticWheelEvent;
+ var updatedAncestorInfo$1 = function (oldInfo, tag, instance) {
+ var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);
+ var info = { tag: tag, instance: instance };
-/**
- * Turns
- * ['abort', ...]
- * into
- * eventTypes = {
- * 'abort': {
- * phasedRegistrationNames: {
- * bubbled: 'onAbort',
- * captured: 'onAbortCapture',
- * },
- * dependencies: ['topAbort'],
- * },
- * ...
- * };
- * topLevelEventsToDispatchConfig = {
- * 'topAbort': { sameConfig }
- * };
- */
-var eventTypes$4 = {};
-var topLevelEventsToDispatchConfig = {};
-['abort', 'animationEnd', 'animationIteration', 'animationStart', 'blur', 'cancel', 'canPlay', 'canPlayThrough', 'click', 'close', 'contextMenu', 'copy', 'cut', 'doubleClick', 'drag', 'dragEnd', 'dragEnter', 'dragExit', 'dragLeave', 'dragOver', 'dragStart', 'drop', 'durationChange', 'emptied', 'encrypted', 'ended', 'error', 'focus', 'input', 'invalid', 'keyDown', 'keyPress', 'keyUp', 'load', 'loadedData', 'loadedMetadata', 'loadStart', 'mouseDown', 'mouseMove', 'mouseOut', 'mouseOver', 'mouseUp', 'paste', 'pause', 'play', 'playing', 'progress', 'rateChange', 'reset', 'scroll', 'seeked', 'seeking', 'stalled', 'submit', 'suspend', 'timeUpdate', 'toggle', 'touchCancel', 'touchEnd', 'touchMove', 'touchStart', 'transitionEnd', 'volumeChange', 'waiting', 'wheel'].forEach(function (event) {
- var capitalizedEvent = event[0].toUpperCase() + event.slice(1);
- var onEvent = 'on' + capitalizedEvent;
- var topEvent = 'top' + capitalizedEvent;
+ if (inScopeTags.indexOf(tag) !== -1) {
+ ancestorInfo.aTagInScope = null;
+ ancestorInfo.buttonTagInScope = null;
+ ancestorInfo.nobrTagInScope = null;
+ }
+ if (buttonScopeTags.indexOf(tag) !== -1) {
+ ancestorInfo.pTagInButtonScope = null;
+ }
- var type = {
- phasedRegistrationNames: {
- bubbled: onEvent,
- captured: onEvent + 'Capture'
- },
- dependencies: [topEvent]
- };
- eventTypes$4[event] = type;
- topLevelEventsToDispatchConfig[topEvent] = type;
-});
+ // See rules for 'li', 'dd', 'dt' start tags in
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
+ if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
+ ancestorInfo.listItemTagAutoclosing = null;
+ ancestorInfo.dlItemTagAutoclosing = null;
+ }
-var SimpleEventPlugin = {
- eventTypes: eventTypes$4,
+ ancestorInfo.current = info;
- extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
- var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
- if (!dispatchConfig) {
- return null;
+ if (tag === 'form') {
+ ancestorInfo.formTag = info;
}
- var EventConstructor;
- switch (topLevelType) {
- case 'topAbort':
- case 'topCancel':
- case 'topCanPlay':
- case 'topCanPlayThrough':
- case 'topClose':
- case 'topDurationChange':
- case 'topEmptied':
- case 'topEncrypted':
- case 'topEnded':
- case 'topError':
- case 'topInput':
- case 'topInvalid':
- case 'topLoad':
- case 'topLoadedData':
- case 'topLoadedMetadata':
- case 'topLoadStart':
- case 'topPause':
- case 'topPlay':
- case 'topPlaying':
- case 'topProgress':
- case 'topRateChange':
- case 'topReset':
- case 'topSeeked':
- case 'topSeeking':
- case 'topStalled':
- case 'topSubmit':
- case 'topSuspend':
- case 'topTimeUpdate':
- case 'topToggle':
- case 'topVolumeChange':
- case 'topWaiting':
- // HTML Events
- // @see http://www.w3.org/TR/html5/index.html#events-0
- EventConstructor = SyntheticEvent_1;
- break;
- case 'topKeyPress':
- // Firefox creates a keypress event for function keys too. This removes
- // the unwanted keypress events. Enter is however both printable and
- // non-printable. One would expect Tab to be as well (but it isn't).
- if (getEventCharCode_1(nativeEvent) === 0) {
- return null;
- }
- /* falls through */
- case 'topKeyDown':
- case 'topKeyUp':
- EventConstructor = SyntheticKeyboardEvent_1;
- break;
- case 'topBlur':
- case 'topFocus':
- EventConstructor = SyntheticFocusEvent_1;
- break;
- case 'topClick':
- // Firefox creates a click event on right mouse clicks. This removes the
- // unwanted click events.
- if (nativeEvent.button === 2) {
- return null;
- }
- /* falls through */
- case 'topDoubleClick':
- case 'topMouseDown':
- case 'topMouseMove':
- case 'topMouseUp':
- // TODO: Disabled elements should not respond to mouse events
- /* falls through */
- case 'topMouseOut':
- case 'topMouseOver':
- case 'topContextMenu':
- EventConstructor = SyntheticMouseEvent_1;
- break;
- case 'topDrag':
- case 'topDragEnd':
- case 'topDragEnter':
- case 'topDragExit':
- case 'topDragLeave':
- case 'topDragOver':
- case 'topDragStart':
- case 'topDrop':
- EventConstructor = SyntheticDragEvent_1;
- break;
- case 'topTouchCancel':
- case 'topTouchEnd':
- case 'topTouchMove':
- case 'topTouchStart':
- EventConstructor = SyntheticTouchEvent_1;
- break;
- case 'topAnimationEnd':
- case 'topAnimationIteration':
- case 'topAnimationStart':
- EventConstructor = SyntheticAnimationEvent_1;
- break;
- case 'topTransitionEnd':
- EventConstructor = SyntheticTransitionEvent_1;
- break;
- case 'topScroll':
- EventConstructor = SyntheticUIEvent_1;
- break;
- case 'topWheel':
- EventConstructor = SyntheticWheelEvent_1;
- break;
- case 'topCopy':
- case 'topCut':
- case 'topPaste':
- EventConstructor = SyntheticClipboardEvent_1;
- break;
+ if (tag === 'a') {
+ ancestorInfo.aTagInScope = info;
+ }
+ if (tag === 'button') {
+ ancestorInfo.buttonTagInScope = info;
+ }
+ if (tag === 'nobr') {
+ ancestorInfo.nobrTagInScope = info;
+ }
+ if (tag === 'p') {
+ ancestorInfo.pTagInButtonScope = info;
+ }
+ if (tag === 'li') {
+ ancestorInfo.listItemTagAutoclosing = info;
+ }
+ if (tag === 'dd' || tag === 'dt') {
+ ancestorInfo.dlItemTagAutoclosing = info;
}
- !EventConstructor ? invariant_1(false, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType) : void 0;
- var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
- EventPropagators_1.accumulateTwoPhaseDispatches(event);
- return event;
- }
-};
-
-var SimpleEventPlugin_1 = SimpleEventPlugin;
-ReactDOMEventListener_1.setHandleTopLevel(ReactBrowserEventEmitter_1.handleTopLevel);
+ return ancestorInfo;
+ };
-/**
- * Inject modules for resolving DOM hierarchy and plugin ordering.
- */
-EventPluginHub_1.injection.injectEventPluginOrder(DOMEventPluginOrder_1);
-EventPluginUtils_1.injection.injectComponentTree(ReactDOMComponentTree_1);
+ /**
+ * Returns whether
+ */
+ var isTagValidWithParent = function (tag, parentTag) {
+ // First, let's check if we're in an unusual parsing mode...
+ switch (parentTag) {
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
+ case 'select':
+ return tag === 'option' || tag === 'optgroup' || tag === '#text';
+ case 'optgroup':
+ return tag === 'option' || tag === '#text';
+ // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
+ // but
+ case 'option':
+ return tag === '#text';
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
+ // No special behavior since these rules fall back to "in body" mode for
+ // all except special table nodes which cause bad parsing behavior anyway.
-/**
- * Some important event plugins included by default (without having to require
- * them).
- */
-EventPluginHub_1.injection.injectEventPluginsByName({
- SimpleEventPlugin: SimpleEventPlugin_1,
- EnterLeaveEventPlugin: EnterLeaveEventPlugin_1,
- ChangeEventPlugin: ChangeEventPlugin_1,
- SelectEventPlugin: SelectEventPlugin_1,
- BeforeInputEventPlugin: BeforeInputEventPlugin_1
-});
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
+ case 'tr':
+ return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
+ case 'tbody':
+ case 'thead':
+ case 'tfoot':
+ return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
+ case 'colgroup':
+ return tag === 'col' || tag === 'template';
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
+ case 'table':
+ return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
+ case 'head':
+ return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
+ // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
+ case 'html':
+ return tag === 'head' || tag === 'body';
+ case '#document':
+ return tag === 'html';
+ }
-var MUST_USE_PROPERTY = DOMProperty_1.injection.MUST_USE_PROPERTY;
-var HAS_BOOLEAN_VALUE = DOMProperty_1.injection.HAS_BOOLEAN_VALUE;
-var HAS_NUMERIC_VALUE = DOMProperty_1.injection.HAS_NUMERIC_VALUE;
-var HAS_POSITIVE_NUMERIC_VALUE = DOMProperty_1.injection.HAS_POSITIVE_NUMERIC_VALUE;
-var HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty_1.injection.HAS_OVERLOADED_BOOLEAN_VALUE;
-var HAS_STRING_BOOLEAN_VALUE = DOMProperty_1.injection.HAS_STRING_BOOLEAN_VALUE;
+ // Probably in the "in body" parsing mode, so we outlaw only tag combos
+ // where the parsing rules cause implicit opens or closes to be added.
+ // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
+ switch (tag) {
+ case 'h1':
+ case 'h2':
+ case 'h3':
+ case 'h4':
+ case 'h5':
+ case 'h6':
+ return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
-var HTMLDOMPropertyConfig = {
- // When adding attributes to this list, be sure to also add them to
- // the `possibleStandardNames` module to ensure casing and incorrect
- // name warnings.
- Properties: {
- allowFullScreen: HAS_BOOLEAN_VALUE,
- // IE only true/false iFrame attribute
- // https://msdn.microsoft.com/en-us/library/ms533072(v=vs.85).aspx
- allowTransparency: HAS_STRING_BOOLEAN_VALUE,
- // specifies target context for links with `preload` type
- async: HAS_BOOLEAN_VALUE,
- // autoFocus is polyfilled/normalized by AutoFocusUtils
- // autoFocus: HAS_BOOLEAN_VALUE,
- autoPlay: HAS_BOOLEAN_VALUE,
- capture: HAS_BOOLEAN_VALUE,
- checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- cols: HAS_POSITIVE_NUMERIC_VALUE,
- contentEditable: HAS_STRING_BOOLEAN_VALUE,
- controls: HAS_BOOLEAN_VALUE,
- 'default': HAS_BOOLEAN_VALUE,
- defer: HAS_BOOLEAN_VALUE,
- disabled: HAS_BOOLEAN_VALUE,
- download: HAS_OVERLOADED_BOOLEAN_VALUE,
- draggable: HAS_STRING_BOOLEAN_VALUE,
- formNoValidate: HAS_BOOLEAN_VALUE,
- hidden: HAS_BOOLEAN_VALUE,
- loop: HAS_BOOLEAN_VALUE,
- // Caution; `option.selected` is not updated if `select.multiple` is
- // disabled with `removeAttribute`.
- multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- noValidate: HAS_BOOLEAN_VALUE,
- open: HAS_BOOLEAN_VALUE,
- playsInline: HAS_BOOLEAN_VALUE,
- readOnly: HAS_BOOLEAN_VALUE,
- required: HAS_BOOLEAN_VALUE,
- reversed: HAS_BOOLEAN_VALUE,
- rows: HAS_POSITIVE_NUMERIC_VALUE,
- rowSpan: HAS_NUMERIC_VALUE,
- scoped: HAS_BOOLEAN_VALUE,
- seamless: HAS_BOOLEAN_VALUE,
- selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- size: HAS_POSITIVE_NUMERIC_VALUE,
- start: HAS_NUMERIC_VALUE,
- // support for projecting regular DOM Elements via V1 named slots ( shadow dom )
- span: HAS_POSITIVE_NUMERIC_VALUE,
- spellCheck: HAS_STRING_BOOLEAN_VALUE,
- // Style must be explicitly set in the attribute list. React components
- // expect a style object
- style: 0,
- // itemScope is for for Microdata support.
- // See http://schema.org/docs/gs.html
- itemScope: HAS_BOOLEAN_VALUE,
- // These attributes must stay in the white-list because they have
- // different attribute names (see DOMAttributeNames below)
- acceptCharset: 0,
- className: 0,
- htmlFor: 0,
- httpEquiv: 0,
- // Attributes with mutation methods must be specified in the whitelist
- // Set the string boolean flag to allow the behavior
- value: HAS_STRING_BOOLEAN_VALUE
- },
- DOMAttributeNames: {
- acceptCharset: 'accept-charset',
- className: 'class',
- htmlFor: 'for',
- httpEquiv: 'http-equiv'
- },
- DOMMutationMethods: {
- value: function (node, value) {
- if (value == null) {
- return node.removeAttribute('value');
- }
+ case 'rp':
+ case 'rt':
+ return impliedEndTags.indexOf(parentTag) === -1;
- // Number inputs get special treatment due to some edge cases in
- // Chrome. Let everything else assign the value attribute as normal.
- // https://github.com/facebook/react/issues/7253#issuecomment-236074326
- if (node.type !== 'number' || node.hasAttribute('value') === false) {
- node.setAttribute('value', '' + value);
- } else if (node.validity && !node.validity.badInput && node.ownerDocument.activeElement !== node) {
- // Don't assign an attribute if validation reports bad
- // input. Chrome will clear the value. Additionally, don't
- // operate on inputs that have focus, otherwise Chrome might
- // strip off trailing decimal places and cause the user's
- // cursor position to jump to the beginning of the input.
- //
- // In ReactDOMInput, we have an onBlur event that will trigger
- // this function again when focus is lost.
- node.setAttribute('value', '' + value);
- }
+ case 'body':
+ case 'caption':
+ case 'col':
+ case 'colgroup':
+ case 'frame':
+ case 'head':
+ case 'html':
+ case 'tbody':
+ case 'td':
+ case 'tfoot':
+ case 'th':
+ case 'thead':
+ case 'tr':
+ // These tags are only valid with a few parents that have special child
+ // parsing rules -- if we're down here, then none of those matched and
+ // so we allow it only if we don't know what the parent is, as all other
+ // cases are invalid.
+ return parentTag == null;
}
- }
-};
-var HTMLDOMPropertyConfig_1 = HTMLDOMPropertyConfig;
+ return true;
+ };
-var HAS_STRING_BOOLEAN_VALUE$1 = DOMProperty_1.injection.HAS_STRING_BOOLEAN_VALUE;
+ /**
+ * Returns whether
+ */
+ var findInvalidAncestorForTag = function (tag, ancestorInfo) {
+ switch (tag) {
+ case 'address':
+ case 'article':
+ case 'aside':
+ case 'blockquote':
+ case 'center':
+ case 'details':
+ case 'dialog':
+ case 'dir':
+ case 'div':
+ case 'dl':
+ case 'fieldset':
+ case 'figcaption':
+ case 'figure':
+ case 'footer':
+ case 'header':
+ case 'hgroup':
+ case 'main':
+ case 'menu':
+ case 'nav':
+ case 'ol':
+ case 'p':
+ case 'section':
+ case 'summary':
+ case 'ul':
+ case 'pre':
+ case 'listing':
+ case 'table':
+ case 'hr':
+ case 'xmp':
+ case 'h1':
+ case 'h2':
+ case 'h3':
+ case 'h4':
+ case 'h5':
+ case 'h6':
+ return ancestorInfo.pTagInButtonScope;
+ case 'form':
+ return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
-var NS = {
- xlink: 'http://www.w3.org/1999/xlink',
- xml: 'http://www.w3.org/XML/1998/namespace'
-};
+ case 'li':
+ return ancestorInfo.listItemTagAutoclosing;
-/**
- * This is a list of all SVG attributes that need special casing,
- * namespacing, or boolean value assignment.
- *
- * When adding attributes to this list, be sure to also add them to
- * the `possibleStandardNames` module to ensure casing and incorrect
- * name warnings.
- *
- * SVG Attributes List:
- * https://www.w3.org/TR/SVG/attindex.html
- * SMIL Spec:
- * https://www.w3.org/TR/smil
- */
-var ATTRS = ['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'x-height', 'xlink:actuate', 'xlink:arcrole', 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type', 'xml:base', 'xmlns:xlink', 'xml:lang', 'xml:space'];
+ case 'dd':
+ case 'dt':
+ return ancestorInfo.dlItemTagAutoclosing;
-var SVGDOMPropertyConfig = {
- Properties: {
- autoReverse: HAS_STRING_BOOLEAN_VALUE$1,
- externalResourcesRequired: HAS_STRING_BOOLEAN_VALUE$1,
- preserveAlpha: HAS_STRING_BOOLEAN_VALUE$1
- },
- DOMAttributeNames: {
- autoReverse: 'autoReverse',
- externalResourcesRequired: 'externalResourcesRequired',
- preserveAlpha: 'preserveAlpha'
- },
- DOMAttributeNamespaces: {
- xlinkActuate: NS.xlink,
- xlinkArcrole: NS.xlink,
- xlinkHref: NS.xlink,
- xlinkRole: NS.xlink,
- xlinkShow: NS.xlink,
- xlinkTitle: NS.xlink,
- xlinkType: NS.xlink,
- xmlBase: NS.xml,
- xmlLang: NS.xml,
- xmlSpace: NS.xml
- }
-};
+ case 'button':
+ return ancestorInfo.buttonTagInScope;
-var CAMELIZE = /[\-\:]([a-z])/g;
-var capitalize = function (token) {
- return token[1].toUpperCase();
-};
+ case 'a':
+ // Spec says something about storing a list of markers, but it sounds
+ // equivalent to this check.
+ return ancestorInfo.aTagInScope;
-ATTRS.forEach(function (original) {
- var reactName = original.replace(CAMELIZE, capitalize);
+ case 'nobr':
+ return ancestorInfo.nobrTagInScope;
+ }
- SVGDOMPropertyConfig.Properties[reactName] = 0;
- SVGDOMPropertyConfig.DOMAttributeNames[reactName] = original;
-});
+ return null;
+ };
-var SVGDOMPropertyConfig_1 = SVGDOMPropertyConfig;
+ var didWarn = {};
-DOMProperty_1.injection.injectDOMPropertyConfig(HTMLDOMPropertyConfig_1);
-DOMProperty_1.injection.injectDOMPropertyConfig(SVGDOMPropertyConfig_1);
+ validateDOMNesting = function (childTag, childText, ancestorInfo) {
+ ancestorInfo = ancestorInfo || emptyAncestorInfo;
+ var parentInfo = ancestorInfo.current;
+ var parentTag = parentInfo && parentInfo.tag;
-var injectInternals = ReactFiberDevToolsHook.injectInternals;
+ if (childText != null) {
+ warning_1(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null');
+ childTag = '#text';
+ }
-var ELEMENT_NODE = HTMLNodeType_1.ELEMENT_NODE;
-var TEXT_NODE = HTMLNodeType_1.TEXT_NODE;
-var COMMENT_NODE = HTMLNodeType_1.COMMENT_NODE;
-var DOCUMENT_NODE = HTMLNodeType_1.DOCUMENT_NODE;
-var DOCUMENT_FRAGMENT_NODE = HTMLNodeType_1.DOCUMENT_FRAGMENT_NODE;
+ var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
+ var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
+ var invalidParentOrAncestor = invalidParent || invalidAncestor;
+ if (!invalidParentOrAncestor) {
+ return;
+ }
-var ROOT_ATTRIBUTE_NAME = DOMProperty_1.ROOT_ATTRIBUTE_NAME;
+ var ancestorTag = invalidParentOrAncestor.tag;
+ var addendum = getCurrentFiberStackAddendum$6();
+
+ var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + addendum;
+ if (didWarn[warnKey]) {
+ return;
+ }
+ didWarn[warnKey] = true;
+ var tagDisplayName = childTag;
+ var whitespaceInfo = '';
+ if (childTag === '#text') {
+ if (/\S/.test(childText)) {
+ tagDisplayName = 'Text nodes';
+ } else {
+ tagDisplayName = 'Whitespace text nodes';
+ whitespaceInfo = " Make sure you don't have any extra whitespace between tags on " + 'each line of your source code.';
+ }
+ } else {
+ tagDisplayName = '<' + childTag + '>';
+ }
+ if (invalidParent) {
+ var info = '';
+ if (ancestorTag === 'table' && childTag === 'tr') {
+ info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
+ }
+ warning_1(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>.%s%s%s', tagDisplayName, ancestorTag, whitespaceInfo, info, addendum);
+ } else {
+ warning_1(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>.%s', tagDisplayName, ancestorTag, addendum);
+ }
+ };
+ // TODO: turn this into a named export
+ validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo$1;
-var getChildNamespace = DOMNamespaces.getChildNamespace;
-var createElement = ReactDOMFiberComponent_1.createElement;
-var createTextNode = ReactDOMFiberComponent_1.createTextNode;
-var setInitialProperties = ReactDOMFiberComponent_1.setInitialProperties;
-var diffProperties = ReactDOMFiberComponent_1.diffProperties;
-var updateProperties = ReactDOMFiberComponent_1.updateProperties;
-var diffHydratedProperties = ReactDOMFiberComponent_1.diffHydratedProperties;
-var diffHydratedText = ReactDOMFiberComponent_1.diffHydratedText;
-var warnForDeletedHydratableElement = ReactDOMFiberComponent_1.warnForDeletedHydratableElement;
-var warnForDeletedHydratableText = ReactDOMFiberComponent_1.warnForDeletedHydratableText;
-var warnForInsertedHydratedElement = ReactDOMFiberComponent_1.warnForInsertedHydratedElement;
-var warnForInsertedHydratedText = ReactDOMFiberComponent_1.warnForInsertedHydratedText;
-var precacheFiberNode = ReactDOMComponentTree_1.precacheFiberNode;
-var updateFiberProps = ReactDOMComponentTree_1.updateFiberProps;
+ // For testing
+ validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {
+ ancestorInfo = ancestorInfo || emptyAncestorInfo;
+ var parentInfo = ancestorInfo.current;
+ var parentTag = parentInfo && parentInfo.tag;
+ return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);
+ };
+}
+var validateDOMNesting$1 = validateDOMNesting;
-{
- var lowPriorityWarning = lowPriorityWarning_1;
- var warning = warning_1;
- var validateDOMNesting = validateDOMNesting_1;
- var updatedAncestorInfo = validateDOMNesting.updatedAncestorInfo;
+// TODO: direct imports like some-package/src/* are bad. Fix me.
+var createElement = createElement$1;
+var createTextNode = createTextNode$1;
+var setInitialProperties = setInitialProperties$1;
+var diffProperties = diffProperties$1;
+var updateProperties = updateProperties$1;
+var diffHydratedProperties = diffHydratedProperties$1;
+var diffHydratedText = diffHydratedText$1;
+var warnForUnmatchedText = warnForUnmatchedText$1;
+var warnForDeletedHydratableElement = warnForDeletedHydratableElement$1;
+var warnForDeletedHydratableText = warnForDeletedHydratableText$1;
+var warnForInsertedHydratedElement = warnForInsertedHydratedElement$1;
+var warnForInsertedHydratedText = warnForInsertedHydratedText$1;
+var updatedAncestorInfo = validateDOMNesting$1.updatedAncestorInfo;
+var precacheFiberNode = precacheFiberNode$1;
+var updateFiberProps = updateFiberProps$1;
+{
+ var SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
if (typeof Map !== 'function' || Map.prototype == null || typeof Map.prototype.forEach !== 'function' || typeof Set !== 'function' || Set.prototype == null || typeof Set.prototype.clear !== 'function' || typeof Set.prototype.forEach !== 'function') {
- warning(false, 'React depends on Map and Set built-in types. Make sure that you load a ' + 'polyfill in older browsers. http://fb.me/react-polyfills');
+ warning_1(false, 'React depends on Map and Set built-in types. Make sure that you load a ' + 'polyfill in older browsers. http://fb.me/react-polyfills');
}
}
-
-
-ReactControlledComponent_1.injection.injectFiberControlledHostComponent(ReactDOMFiberComponent_1);
-findDOMNode_1._injectFiber(function (fiber) {
- return DOMRenderer.findHostInstance(fiber);
-});
+injection$3.injectFiberControlledHostComponent(ReactDOMFiberComponent);
var eventsEnabled = null;
var selectionInformation = null;
@@ -18054,19 +15584,28 @@ function shouldAutoFocusHostComponent(type, props) {
return false;
}
-var DOMRenderer = ReactFiberReconciler({
+var DOMRenderer = reactReconciler({
getRootHostContext: function (rootContainerInstance) {
var type = void 0;
var namespace = void 0;
- if (rootContainerInstance.nodeType === DOCUMENT_NODE) {
- type = '#document';
- var root = rootContainerInstance.documentElement;
- namespace = root ? root.namespaceURI : getChildNamespace(null, '');
- } else {
- var container = rootContainerInstance.nodeType === COMMENT_NODE ? rootContainerInstance.parentNode : rootContainerInstance;
- var ownNamespace = container.namespaceURI || null;
- type = container.tagName;
- namespace = getChildNamespace(ownNamespace, type);
+ var nodeType = rootContainerInstance.nodeType;
+ switch (nodeType) {
+ case DOCUMENT_NODE:
+ case DOCUMENT_FRAGMENT_NODE:
+ {
+ type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment';
+ var root = rootContainerInstance.documentElement;
+ namespace = root ? root.namespaceURI : getChildNamespace(null, '');
+ break;
+ }
+ default:
+ {
+ var container = nodeType === COMMENT_NODE ? rootContainerInstance.parentNode : rootContainerInstance;
+ var ownNamespace = container.namespaceURI || null;
+ type = container.tagName;
+ namespace = getChildNamespace(ownNamespace, type);
+ break;
+ }
}
{
var validatedTag = type.toLowerCase();
@@ -18089,14 +15628,14 @@ var DOMRenderer = ReactFiberReconciler({
return instance;
},
prepareForCommit: function () {
- eventsEnabled = ReactBrowserEventEmitter_1.isEnabled();
- selectionInformation = ReactInputSelection_1.getSelectionInformation();
- ReactBrowserEventEmitter_1.setEnabled(false);
+ eventsEnabled = isEnabled();
+ selectionInformation = getSelectionInformation();
+ setEnabled(false);
},
resetAfterCommit: function () {
- ReactInputSelection_1.restoreSelection(selectionInformation);
+ restoreSelection(selectionInformation);
selectionInformation = null;
- ReactBrowserEventEmitter_1.setEnabled(eventsEnabled);
+ setEnabled(eventsEnabled);
eventsEnabled = null;
},
createInstance: function (type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
@@ -18104,11 +15643,11 @@ var DOMRenderer = ReactFiberReconciler({
{
// TODO: take namespace into account when validating.
var hostContextDev = hostContext;
- validateDOMNesting(type, null, null, hostContextDev.ancestorInfo);
+ validateDOMNesting$1(type, null, hostContextDev.ancestorInfo);
if (typeof props.children === 'string' || typeof props.children === 'number') {
var string = '' + props.children;
var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type, null);
- validateDOMNesting(null, string, null, ownAncestorInfo);
+ validateDOMNesting$1(null, string, ownAncestorInfo);
}
parentNamespace = hostContextDev.namespace;
}
@@ -18130,135 +15669,184 @@ var DOMRenderer = ReactFiberReconciler({
if (typeof newProps.children !== typeof oldProps.children && (typeof newProps.children === 'string' || typeof newProps.children === 'number')) {
var string = '' + newProps.children;
var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type, null);
- validateDOMNesting(null, string, null, ownAncestorInfo);
+ validateDOMNesting$1(null, string, ownAncestorInfo);
}
}
return diffProperties(domElement, type, oldProps, newProps, rootContainerInstance);
},
- commitMount: function (domElement, type, newProps, internalInstanceHandle) {
- domElement.focus();
- },
- commitUpdate: function (domElement, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
- // Update the props handle so that we know which props are the ones with
- // with current event handlers.
- updateFiberProps(domElement, newProps);
- // Apply the diff to the DOM node.
- updateProperties(domElement, updatePayload, type, oldProps, newProps);
- },
shouldSetTextContent: function (type, props) {
return type === 'textarea' || typeof props.children === 'string' || typeof props.children === 'number' || typeof props.dangerouslySetInnerHTML === 'object' && props.dangerouslySetInnerHTML !== null && typeof props.dangerouslySetInnerHTML.__html === 'string';
},
- resetTextContent: function (domElement) {
- domElement.textContent = '';
- },
shouldDeprioritizeSubtree: function (type, props) {
return !!props.hidden;
},
createTextInstance: function (text, rootContainerInstance, hostContext, internalInstanceHandle) {
{
var hostContextDev = hostContext;
- validateDOMNesting(null, text, null, hostContextDev.ancestorInfo);
+ validateDOMNesting$1(null, text, hostContextDev.ancestorInfo);
}
var textNode = createTextNode(text, rootContainerInstance);
precacheFiberNode(internalInstanceHandle, textNode);
return textNode;
},
- commitTextUpdate: function (textInstance, oldText, newText) {
- textInstance.nodeValue = newText;
- },
- appendChild: function (parentInstance, child) {
- parentInstance.appendChild(child);
- },
- appendChildToContainer: function (container, child) {
- if (container.nodeType === COMMENT_NODE) {
- container.parentNode.insertBefore(child, container);
- } else {
- container.appendChild(child);
- }
- },
- insertBefore: function (parentInstance, child, beforeChild) {
- parentInstance.insertBefore(child, beforeChild);
- },
- insertInContainerBefore: function (container, child, beforeChild) {
- if (container.nodeType === COMMENT_NODE) {
- container.parentNode.insertBefore(child, beforeChild);
- } else {
- container.insertBefore(child, beforeChild);
- }
- },
- removeChild: function (parentInstance, child) {
- parentInstance.removeChild(child);
- },
- removeChildFromContainer: function (container, child) {
- if (container.nodeType === COMMENT_NODE) {
- container.parentNode.removeChild(child);
- } else {
- container.removeChild(child);
- }
- },
- canHydrateInstance: function (instance, type, props) {
- return instance.nodeType === ELEMENT_NODE && type === instance.nodeName.toLowerCase();
- },
- canHydrateTextInstance: function (instance, text) {
- if (text === '') {
- // Empty strings are not parsed by HTML so there won't be a correct match here.
- return false;
- }
- return instance.nodeType === TEXT_NODE;
- },
- getNextHydratableSibling: function (instance) {
- var node = instance.nextSibling;
- // Skip non-hydratable nodes.
- while (node && node.nodeType !== ELEMENT_NODE && node.nodeType !== TEXT_NODE) {
- node = node.nextSibling;
- }
- return node;
- },
- getFirstHydratableChild: function (parentInstance) {
- var next = parentInstance.firstChild;
- // Skip non-hydratable nodes.
- while (next && next.nodeType !== ELEMENT_NODE && next.nodeType !== TEXT_NODE) {
- next = next.nextSibling;
- }
- return next;
- },
- hydrateInstance: function (instance, type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
- precacheFiberNode(internalInstanceHandle, instance);
- // TODO: Possibly defer this until the commit phase where all the events
- // get attached.
- updateFiberProps(instance, props);
- var parentNamespace = void 0;
- {
- var hostContextDev = hostContext;
- parentNamespace = hostContextDev.namespace;
+
+
+ now: now,
+
+ mutation: {
+ commitMount: function (domElement, type, newProps, internalInstanceHandle) {
+ domElement.focus();
+ },
+ commitUpdate: function (domElement, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
+ // Update the props handle so that we know which props are the ones with
+ // with current event handlers.
+ updateFiberProps(domElement, newProps);
+ // Apply the diff to the DOM node.
+ updateProperties(domElement, updatePayload, type, oldProps, newProps);
+ },
+ resetTextContent: function (domElement) {
+ domElement.textContent = '';
+ },
+ commitTextUpdate: function (textInstance, oldText, newText) {
+ textInstance.nodeValue = newText;
+ },
+ appendChild: function (parentInstance, child) {
+ parentInstance.appendChild(child);
+ },
+ appendChildToContainer: function (container, child) {
+ if (container.nodeType === COMMENT_NODE) {
+ container.parentNode.insertBefore(child, container);
+ } else {
+ container.appendChild(child);
+ }
+ },
+ insertBefore: function (parentInstance, child, beforeChild) {
+ parentInstance.insertBefore(child, beforeChild);
+ },
+ insertInContainerBefore: function (container, child, beforeChild) {
+ if (container.nodeType === COMMENT_NODE) {
+ container.parentNode.insertBefore(child, beforeChild);
+ } else {
+ container.insertBefore(child, beforeChild);
+ }
+ },
+ removeChild: function (parentInstance, child) {
+ parentInstance.removeChild(child);
+ },
+ removeChildFromContainer: function (container, child) {
+ if (container.nodeType === COMMENT_NODE) {
+ container.parentNode.removeChild(child);
+ } else {
+ container.removeChild(child);
+ }
}
- return diffHydratedProperties(instance, type, props, parentNamespace, rootContainerInstance);
- },
- hydrateTextInstance: function (textInstance, text, internalInstanceHandle) {
- precacheFiberNode(internalInstanceHandle, textInstance);
- return diffHydratedText(textInstance, text);
},
- didNotHydrateInstance: function (parentInstance, instance) {
- if (instance.nodeType === 1) {
- warnForDeletedHydratableElement(parentInstance, instance);
- } else {
- warnForDeletedHydratableText(parentInstance, instance);
+
+ hydration: {
+ canHydrateInstance: function (instance, type, props) {
+ if (instance.nodeType !== ELEMENT_NODE || type.toLowerCase() !== instance.nodeName.toLowerCase()) {
+ return null;
+ }
+ // This has now been refined to an element node.
+ return instance;
+ },
+ canHydrateTextInstance: function (instance, text) {
+ if (text === '' || instance.nodeType !== TEXT_NODE) {
+ // Empty strings are not parsed by HTML so there won't be a correct match here.
+ return null;
+ }
+ // This has now been refined to a text node.
+ return instance;
+ },
+ getNextHydratableSibling: function (instance) {
+ var node = instance.nextSibling;
+ // Skip non-hydratable nodes.
+ while (node && node.nodeType !== ELEMENT_NODE && node.nodeType !== TEXT_NODE) {
+ node = node.nextSibling;
+ }
+ return node;
+ },
+ getFirstHydratableChild: function (parentInstance) {
+ var next = parentInstance.firstChild;
+ // Skip non-hydratable nodes.
+ while (next && next.nodeType !== ELEMENT_NODE && next.nodeType !== TEXT_NODE) {
+ next = next.nextSibling;
+ }
+ return next;
+ },
+ hydrateInstance: function (instance, type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
+ precacheFiberNode(internalInstanceHandle, instance);
+ // TODO: Possibly defer this until the commit phase where all the events
+ // get attached.
+ updateFiberProps(instance, props);
+ var parentNamespace = void 0;
+ {
+ var hostContextDev = hostContext;
+ parentNamespace = hostContextDev.namespace;
+ }
+ return diffHydratedProperties(instance, type, props, parentNamespace, rootContainerInstance);
+ },
+ hydrateTextInstance: function (textInstance, text, internalInstanceHandle) {
+ precacheFiberNode(internalInstanceHandle, textInstance);
+ return diffHydratedText(textInstance, text);
+ },
+ didNotMatchHydratedContainerTextInstance: function (parentContainer, textInstance, text) {
+ {
+ warnForUnmatchedText(textInstance, text);
+ }
+ },
+ didNotMatchHydratedTextInstance: function (parentType, parentProps, parentInstance, textInstance, text) {
+ if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
+ warnForUnmatchedText(textInstance, text);
+ }
+ },
+ didNotHydrateContainerInstance: function (parentContainer, instance) {
+ {
+ if (instance.nodeType === 1) {
+ warnForDeletedHydratableElement(parentContainer, instance);
+ } else {
+ warnForDeletedHydratableText(parentContainer, instance);
+ }
+ }
+ },
+ didNotHydrateInstance: function (parentType, parentProps, parentInstance, instance) {
+ if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
+ if (instance.nodeType === 1) {
+ warnForDeletedHydratableElement(parentInstance, instance);
+ } else {
+ warnForDeletedHydratableText(parentInstance, instance);
+ }
+ }
+ },
+ didNotFindHydratableContainerInstance: function (parentContainer, type, props) {
+ {
+ warnForInsertedHydratedElement(parentContainer, type, props);
+ }
+ },
+ didNotFindHydratableContainerTextInstance: function (parentContainer, text) {
+ {
+ warnForInsertedHydratedText(parentContainer, text);
+ }
+ },
+ didNotFindHydratableInstance: function (parentType, parentProps, parentInstance, type, props) {
+ if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
+ warnForInsertedHydratedElement(parentInstance, type, props);
+ }
+ },
+ didNotFindHydratableTextInstance: function (parentType, parentProps, parentInstance, text) {
+ if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
+ warnForInsertedHydratedText(parentInstance, text);
+ }
}
},
- didNotFindHydratableInstance: function (parentInstance, type, props) {
- warnForInsertedHydratedElement(parentInstance, type, props);
- },
- didNotFindHydratableTextInstance: function (parentInstance, text) {
- warnForInsertedHydratedText(parentInstance, text);
- },
-
- scheduleDeferredCallback: ReactDOMFrameScheduling.rIC,
+ scheduleDeferredCallback: rIC,
+ cancelDeferredCallback: cIC,
- useSyncScheduling: !ReactDOMFeatureFlags_1.fiberAsyncScheduling
+ useSyncScheduling: !enableAsyncSchedulingByDefaultInReactDOM
});
-ReactGenericBatching_1.injection.injectFiberBatchedUpdates(DOMRenderer.batchedUpdates);
+injection$4.injectFiberBatchedUpdates(DOMRenderer.batchedUpdates);
var warnedAboutHydrateAPI = false;
@@ -18269,17 +15857,17 @@ function renderSubtreeIntoContainer(parentComponent, children, container, forceH
if (container._reactRootContainer && container.nodeType !== COMMENT_NODE) {
var hostInstance = DOMRenderer.findHostInstanceWithNoPortals(container._reactRootContainer.current);
if (hostInstance) {
- warning(hostInstance.parentNode === container, 'render(...): It looks like the React-rendered content of this ' + 'container was removed without using React. This is not ' + 'supported and will cause errors. Instead, call ' + 'ReactDOM.unmountComponentAtNode to empty a container.');
+ warning_1(hostInstance.parentNode === container, 'render(...): It looks like the React-rendered content of this ' + 'container was removed without using React. This is not ' + 'supported and will cause errors. Instead, call ' + 'ReactDOM.unmountComponentAtNode to empty a container.');
}
}
var isRootRenderedBySomeReact = !!container._reactRootContainer;
var rootEl = getReactRootElementInContainer(container);
- var hasNonRootReactChild = !!(rootEl && ReactDOMComponentTree_1.getInstanceFromNode(rootEl));
+ var hasNonRootReactChild = !!(rootEl && getInstanceFromNode$1(rootEl));
- warning(!hasNonRootReactChild || isRootRenderedBySomeReact, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.');
+ warning_1(!hasNonRootReactChild || isRootRenderedBySomeReact, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.');
- warning(container.nodeType !== ELEMENT_NODE || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.');
+ warning_1(container.nodeType !== ELEMENT_NODE || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.');
}
var root = container._reactRootContainer;
@@ -18293,7 +15881,7 @@ function renderSubtreeIntoContainer(parentComponent, children, container, forceH
{
if (!warned && rootSibling.nodeType === ELEMENT_NODE && rootSibling.hasAttribute(ROOT_ATTRIBUTE_NAME)) {
warned = true;
- warning(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.');
+ warning_1(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.');
}
}
container.removeChild(rootSibling);
@@ -18302,10 +15890,10 @@ function renderSubtreeIntoContainer(parentComponent, children, container, forceH
{
if (shouldHydrate && !forceHydrate && !warnedAboutHydrateAPI) {
warnedAboutHydrateAPI = true;
- lowPriorityWarning(false, 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' + 'will stop working in React v17. Replace the ReactDOM.render() call ' + 'with ReactDOM.hydrate() if you want React to attach to the server HTML.');
+ lowPriorityWarning$1(false, 'render(): Calling ReactDOM.render() to hydrate server-rendered markup ' + 'will stop working in React v17. Replace the ReactDOM.render() call ' + 'with ReactDOM.hydrate() if you want React to attach to the server HTML.');
}
}
- var newRoot = DOMRenderer.createContainer(container);
+ var newRoot = DOMRenderer.createContainer(container, shouldHydrate);
root = container._reactRootContainer = newRoot;
// Initial mount should not be batched.
DOMRenderer.unbatchedUpdates(function () {
@@ -18322,12 +15910,52 @@ function createPortal(children, container) {
!isValidContainer(container) ? invariant_1(false, 'Target container is not a DOM element.') : void 0;
// TODO: pass ReactDOM portal implementation as third argument
- return ReactPortal.createPortal(children, container, null, key);
+ return createPortal$1(children, container, null, key);
}
-var ReactDOMFiber = {
+function ReactRoot(container, hydrate) {
+ var root = DOMRenderer.createContainer(container, hydrate);
+ this._reactRootContainer = root;
+}
+ReactRoot.prototype.render = function (children, callback) {
+ var root = this._reactRootContainer;
+ DOMRenderer.updateContainer(children, root, null, callback);
+};
+ReactRoot.prototype.unmount = function (callback) {
+ var root = this._reactRootContainer;
+ DOMRenderer.updateContainer(null, root, null, callback);
+};
+
+var ReactDOM = {
createPortal: createPortal,
+ findDOMNode: function (componentOrElement) {
+ {
+ var owner = ReactCurrentOwner.current;
+ if (owner !== null) {
+ var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender;
+ warning_1(warnedAboutRefsInRender, '%s is accessing findDOMNode 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 (componentOrElement == null) {
+ return null;
+ }
+ if (componentOrElement.nodeType === ELEMENT_NODE) {
+ return componentOrElement;
+ }
+
+ var inst = get(componentOrElement);
+ if (inst) {
+ return DOMRenderer.findHostInstance(inst);
+ }
+
+ if (typeof componentOrElement.render === 'function') {
+ invariant_1(false, 'Unable to find node on an unmounted component.');
+ } else {
+ invariant_1(false, 'Element appears to be neither ReactComponent nor DOMNode. Keys: %s', Object.keys(componentOrElement));
+ }
+ },
hydrate: function (element, container, callback) {
// TODO: throw or warn if we couldn't hydrate?
return renderSubtreeIntoContainer(null, element, container, true, callback);
@@ -18336,7 +15964,7 @@ var ReactDOMFiber = {
return renderSubtreeIntoContainer(null, element, container, false, callback);
},
unstable_renderSubtreeIntoContainer: function (parentComponent, element, containerNode, callback) {
- !(parentComponent != null && ReactInstanceMap_1.has(parentComponent)) ? invariant_1(false, 'parentComponent must be a valid React Component') : void 0;
+ !(parentComponent != null && has(parentComponent)) ? invariant_1(false, 'parentComponent must be a valid React Component') : void 0;
return renderSubtreeIntoContainer(parentComponent, element, containerNode, false, callback);
},
unmountComponentAtNode: function (container) {
@@ -18345,8 +15973,8 @@ var ReactDOMFiber = {
if (container._reactRootContainer) {
{
var rootEl = getReactRootElementInContainer(container);
- var renderedByDifferentReact = rootEl && !ReactDOMComponentTree_1.getInstanceFromNode(rootEl);
- warning(!renderedByDifferentReact, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.');
+ var renderedByDifferentReact = rootEl && !getInstanceFromNode$1(rootEl);
+ warning_1(!renderedByDifferentReact, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.');
}
// Unmount should not be batched.
@@ -18361,12 +15989,12 @@ var ReactDOMFiber = {
} else {
{
var _rootEl = getReactRootElementInContainer(container);
- var hasNonRootReactChild = !!(_rootEl && ReactDOMComponentTree_1.getInstanceFromNode(_rootEl));
+ var hasNonRootReactChild = !!(_rootEl && getInstanceFromNode$1(_rootEl));
// Check if the container itself is a React root node.
var isContainerReactRoot = container.nodeType === 1 && isValidContainer(container.parentNode) && !!container.parentNode._reactRootContainer;
- warning(!hasNonRootReactChild, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.');
+ warning_1(!hasNonRootReactChild, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.');
}
return false;
@@ -18374,13 +16002,11 @@ var ReactDOMFiber = {
},
- findDOMNode: findDOMNode_1,
-
// Temporary alias since we already shipped React 16 RC with it.
// TODO: remove in React 17.
unstable_createPortal: createPortal,
- unstable_batchedUpdates: ReactGenericBatching_1.batchedUpdates,
+ unstable_batchedUpdates: batchedUpdates,
unstable_deferredUpdates: DOMRenderer.deferredUpdates,
@@ -18388,20 +16014,25 @@ var ReactDOMFiber = {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
// For TapEventPlugin which is popular in open source
- EventPluginHub: EventPluginHub_1,
+ EventPluginHub: EventPluginHub,
// Used by test-utils
- EventPluginRegistry: EventPluginRegistry_1,
- EventPropagators: EventPropagators_1,
- ReactControlledComponent: ReactControlledComponent_1,
- ReactDOMComponentTree: ReactDOMComponentTree_1,
- ReactDOMEventListener: ReactDOMEventListener_1
+ EventPluginRegistry: EventPluginRegistry,
+ EventPropagators: EventPropagators,
+ ReactControlledComponent: ReactControlledComponent,
+ ReactDOMComponentTree: ReactDOMComponentTree,
+ ReactDOMEventListener: ReactDOMEventListener
}
};
-var foundDevTools = injectInternals({
- findFiberByHostInstance: ReactDOMComponentTree_1.getClosestInstanceFromNode,
- findHostInstanceByFiber: DOMRenderer.findHostInstance,
- // This is an enum because we may add more (e.g. profiler build)
+if (enableCreateRoot) {
+ ReactDOM.createRoot = function createRoot(container, options) {
+ var hydrate = options != null && options.hydrate === true;
+ return new ReactRoot(container, hydrate);
+ };
+}
+
+var foundDevTools = DOMRenderer.injectIntoDevTools({
+ findFiberByHostInstance: getClosestInstanceFromNode,
bundleType: 1,
version: ReactVersion,
rendererPackageName: 'react-dom'
@@ -18420,8 +16051,18 @@ var foundDevTools = injectInternals({
}
}
-var ReactDOMFiberEntry = ReactDOMFiber;
-return ReactDOMFiberEntry;
+
+var ReactDOM$2 = Object.freeze({
+ default: ReactDOM
+});
+
+var ReactDOM$3 = ( ReactDOM$2 && ReactDOM ) || ReactDOM$2;
+
+// TODO: decide on the top-level export form.
+// This is hacky but makes it work with both Rollup and Jest.
+var reactDom = ReactDOM$3['default'] ? ReactDOM$3['default'] : ReactDOM$3;
+
+return reactDom;
})));