· 8 years ago · Jan 05, 2018, 10:26 AM
1/** @license React v16.2.0
2 * react-dom.development.js
3 *
4 * Copyright (c) 2013-present, Facebook, Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE file in the root directory of this source tree.
8 */
9
10'use strict';
11
12(function (global, factory) {
13 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
14 typeof define === 'function' && define.amd ? define(['react'], factory) :
15 (global.ReactDOM = factory(global.React));
16}(this, (function (React) { 'use strict';
17
18/**
19 * WARNING: DO NOT manually require this module.
20 * This is a replacement for `invariant(...)` used by the error code system
21 * and will _only_ be required by the corresponding babel pass.
22 * It always throws.
23 */
24
25/**
26 * Copyright (c) 2013-present, Facebook, Inc.
27 *
28 * This source code is licensed under the MIT license found in the
29 * LICENSE file in the root directory of this source tree.
30 *
31 */
32
33
34
35/**
36 * Use invariant() to assert state which your program assumes to be true.
37 *
38 * Provide sprintf-style format (only %s is supported) and arguments
39 * to provide information about what broke and what you were
40 * expecting.
41 *
42 * The invariant message will be stripped in production, but the invariant
43 * will remain to ensure logic does not differ in production.
44 */
45
46var validateFormat = function validateFormat(format) {};
47
48{
49 validateFormat = function validateFormat(format) {
50 if (format === undefined) {
51 throw new Error('invariant requires an error message argument');
52 }
53 };
54}
55
56function invariant(condition, format, a, b, c, d, e, f) {
57 validateFormat(format);
58
59 if (!condition) {
60 var error;
61 if (format === undefined) {
62 error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
63 } else {
64 var args = [a, b, c, d, e, f];
65 var argIndex = 0;
66 error = new Error(format.replace(/%s/g, function () {
67 return args[argIndex++];
68 }));
69 error.name = 'Invariant Violation';
70 }
71
72 error.framesToPop = 1; // we don't care about invariant's own frame
73 throw error;
74 }
75}
76
77var invariant_1 = invariant;
78
79!React ? invariant_1(false, 'ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.') : void 0;
80
81var invokeGuardedCallback = function (name, func, context, a, b, c, d, e, f) {
82 this._hasCaughtError = false;
83 this._caughtError = null;
84 var funcArgs = Array.prototype.slice.call(arguments, 3);
85 try {
86 func.apply(context, funcArgs);
87 } catch (error) {
88 this._caughtError = error;
89 this._hasCaughtError = true;
90 }
91};
92
93{
94 // In DEV mode, we swap out invokeGuardedCallback for a special version
95 // that plays more nicely with the browser's DevTools. The idea is to preserve
96 // "Pause on exceptions" behavior. Because React wraps all user-provided
97 // functions in invokeGuardedCallback, and the production version of
98 // invokeGuardedCallback uses a try-catch, all user exceptions are treated
99 // like caught exceptions, and the DevTools won't pause unless the developer
100 // takes the extra step of enabling pause on caught exceptions. This is
101 // untintuitive, though, because even though React has caught the error, from
102 // the developer's perspective, the error is uncaught.
103 //
104 // To preserve the expected "Pause on exceptions" behavior, we don't use a
105 // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake
106 // DOM node, and call the user-provided callback from inside an event handler
107 // for that fake event. If the callback throws, the error is "captured" using
108 // a global event handler. But because the error happens in a different
109 // event loop context, it does not interrupt the normal program flow.
110 // Effectively, this gives us try-catch behavior without actually using
111 // try-catch. Neat!
112
113 // Check that the browser supports the APIs we need to implement our special
114 // DEV version of invokeGuardedCallback
115 if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
116 var fakeNode = document.createElement('react');
117
118 var invokeGuardedCallbackDev = function (name, func, context, a, b, c, d, e, f) {
119 // If document doesn't exist we know for sure we will crash in this method
120 // when we call document.createEvent(). However this can cause confusing
121 // errors: https://github.com/facebookincubator/create-react-app/issues/3482
122 // So we preemptively throw with a better message instead.
123 !(typeof document !== 'undefined') ? invariant_1(false, 'The `document` global was defined when React was initialized, but is not defined anymore. This can happen in a test environment if a component schedules an update from an asynchronous callback, but the test has already finished running. To solve this, you can either unmount the component at the end of your test (and ensure that any asynchronous operations get canceled in `componentWillUnmount`), or you can change the test itself to be asynchronous.') : void 0;
124 var evt = document.createEvent('Event');
125
126 // Keeps track of whether the user-provided callback threw an error. We
127 // set this to true at the beginning, then set it to false right after
128 // calling the function. If the function errors, `didError` will never be
129 // set to false. This strategy works even if the browser is flaky and
130 // fails to call our global error handler, because it doesn't rely on
131 // the error event at all.
132 var didError = true;
133
134 // Create an event handler for our fake event. We will synchronously
135 // dispatch our fake event using `dispatchEvent`. Inside the handler, we
136 // call the user-provided callback.
137 var funcArgs = Array.prototype.slice.call(arguments, 3);
138 function callCallback() {
139 // We immediately remove the callback from event listeners so that
140 // nested `invokeGuardedCallback` calls do not clash. Otherwise, a
141 // nested call would trigger the fake event handlers of any call higher
142 // in the stack.
143 fakeNode.removeEventListener(evtType, callCallback, false);
144 func.apply(context, funcArgs);
145 didError = false;
146 }
147
148 // Create a global error event handler. We use this to capture the value
149 // that was thrown. It's possible that this error handler will fire more
150 // than once; for example, if non-React code also calls `dispatchEvent`
151 // and a handler for that event throws. We should be resilient to most of
152 // those cases. Even if our error event handler fires more than once, the
153 // last error event is always used. If the callback actually does error,
154 // we know that the last error event is the correct one, because it's not
155 // possible for anything else to have happened in between our callback
156 // erroring and the code that follows the `dispatchEvent` call below. If
157 // the callback doesn't error, but the error event was fired, we know to
158 // ignore it because `didError` will be false, as described above.
159 var error = void 0;
160 // Use this to track whether the error event is ever called.
161 var didSetError = false;
162 var isCrossOriginError = false;
163
164 function onError(event) {
165 error = event.error;
166 didSetError = true;
167 if (error === null && event.colno === 0 && event.lineno === 0) {
168 isCrossOriginError = true;
169 }
170 }
171
172 // Create a fake event type.
173 var evtType = 'react-' + (name ? name : 'invokeguardedcallback');
174
175 // Attach our event handlers
176 window.addEventListener('error', onError);
177 fakeNode.addEventListener(evtType, callCallback, false);
178
179 // Synchronously dispatch our fake event. If the user-provided function
180 // errors, it will trigger our global error handler.
181 evt.initEvent(evtType, false, false);
182 fakeNode.dispatchEvent(evt);
183
184 if (didError) {
185 if (!didSetError) {
186 // The callback errored, but the error event never fired.
187 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.');
188 } else if (isCrossOriginError) {
189 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.');
190 }
191 this._hasCaughtError = true;
192 this._caughtError = error;
193 } else {
194 this._hasCaughtError = false;
195 this._caughtError = null;
196 }
197
198 // Remove our event listeners
199 window.removeEventListener('error', onError);
200 };
201
202 invokeGuardedCallback = invokeGuardedCallbackDev;
203 }
204}
205
206var invokeGuardedCallback$1 = invokeGuardedCallback;
207
208var ReactErrorUtils = {
209 // Used by Fiber to simulate a try-catch.
210 _caughtError: null,
211 _hasCaughtError: false,
212
213 // Used by event system to capture/rethrow the first error.
214 _rethrowError: null,
215 _hasRethrowError: false,
216
217 /**
218 * Call a function while guarding against errors that happens within it.
219 * Returns an error if it throws, otherwise null.
220 *
221 * In production, this is implemented using a try-catch. The reason we don't
222 * use a try-catch directly is so that we can swap out a different
223 * implementation in DEV mode.
224 *
225 * @param {String} name of the guard to use for logging or debugging
226 * @param {Function} func The function to invoke
227 * @param {*} context The context to use when calling the function
228 * @param {...*} args Arguments for function
229 */
230 invokeGuardedCallback: function (name, func, context, a, b, c, d, e, f) {
231 invokeGuardedCallback$1.apply(ReactErrorUtils, arguments);
232 },
233
234 /**
235 * Same as invokeGuardedCallback, but instead of returning an error, it stores
236 * it in a global so it can be rethrown by `rethrowCaughtError` later.
237 * TODO: See if _caughtError and _rethrowError can be unified.
238 *
239 * @param {String} name of the guard to use for logging or debugging
240 * @param {Function} func The function to invoke
241 * @param {*} context The context to use when calling the function
242 * @param {...*} args Arguments for function
243 */
244 invokeGuardedCallbackAndCatchFirstError: function (name, func, context, a, b, c, d, e, f) {
245 ReactErrorUtils.invokeGuardedCallback.apply(this, arguments);
246 if (ReactErrorUtils.hasCaughtError()) {
247 var error = ReactErrorUtils.clearCaughtError();
248 if (!ReactErrorUtils._hasRethrowError) {
249 ReactErrorUtils._hasRethrowError = true;
250 ReactErrorUtils._rethrowError = error;
251 }
252 }
253 },
254
255 /**
256 * During execution of guarded functions we will capture the first error which
257 * we will rethrow to be handled by the top level error handler.
258 */
259 rethrowCaughtError: function () {
260 return rethrowCaughtError.apply(ReactErrorUtils, arguments);
261 },
262
263 hasCaughtError: function () {
264 return ReactErrorUtils._hasCaughtError;
265 },
266
267 clearCaughtError: function () {
268 if (ReactErrorUtils._hasCaughtError) {
269 var error = ReactErrorUtils._caughtError;
270 ReactErrorUtils._caughtError = null;
271 ReactErrorUtils._hasCaughtError = false;
272 return error;
273 } else {
274 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.');
275 }
276 }
277};
278
279var rethrowCaughtError = function () {
280 if (ReactErrorUtils._hasRethrowError) {
281 var error = ReactErrorUtils._rethrowError;
282 ReactErrorUtils._rethrowError = null;
283 ReactErrorUtils._hasRethrowError = false;
284 throw error;
285 }
286};
287
288/**
289 * Forked from fbjs/warning:
290 * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js
291 *
292 * Only change is we use console.warn instead of console.error,
293 * and do nothing when 'console' is not supported.
294 * This really simplifies the code.
295 * ---
296 * Similar to invariant but only logs a warning if the condition is not met.
297 * This can be used to log issues in development environments in critical
298 * paths. Removing the logging code for production environments will keep the
299 * same logic and follow the same code paths.
300 */
301
302var lowPriorityWarning = function () {};
303
304{
305 var printWarning = function (format) {
306 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
307 args[_key - 1] = arguments[_key];
308 }
309
310 var argIndex = 0;
311 var message = 'Warning: ' + format.replace(/%s/g, function () {
312 return args[argIndex++];
313 });
314 if (typeof console !== 'undefined') {
315 console.warn(message);
316 }
317 try {
318 // --- Welcome to debugging React ---
319 // This error was thrown as a convenience so that you can use this stack
320 // to find the callsite that caused this warning to fire.
321 throw new Error(message);
322 } catch (x) {}
323 };
324
325 lowPriorityWarning = function (condition, format) {
326 if (format === undefined) {
327 throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
328 }
329 if (!condition) {
330 for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
331 args[_key2 - 2] = arguments[_key2];
332 }
333
334 printWarning.apply(undefined, [format].concat(args));
335 }
336 };
337}
338
339var lowPriorityWarning$1 = lowPriorityWarning;
340
341var shouldWarnOnInjection = false;
342
343/**
344 * Injectable ordering of event plugins.
345 */
346var eventPluginOrder = null;
347
348/**
349 * Injectable mapping from names to event plugin modules.
350 */
351var namesToPlugins = {};
352
353function enableWarningOnInjection() {
354 shouldWarnOnInjection = true;
355}
356
357/**
358 * Recomputes the plugin list using the injected plugins and plugin ordering.
359 *
360 * @private
361 */
362function recomputePluginOrdering() {
363 if (!eventPluginOrder) {
364 // Wait until an `eventPluginOrder` is injected.
365 return;
366 }
367 for (var pluginName in namesToPlugins) {
368 var pluginModule = namesToPlugins[pluginName];
369 var pluginIndex = eventPluginOrder.indexOf(pluginName);
370 !(pluginIndex > -1) ? invariant_1(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : void 0;
371 if (plugins[pluginIndex]) {
372 continue;
373 }
374 !pluginModule.extractEvents ? invariant_1(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : void 0;
375 plugins[pluginIndex] = pluginModule;
376 var publishedEvents = pluginModule.eventTypes;
377 for (var eventName in publishedEvents) {
378 !publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) ? invariant_1(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : void 0;
379 }
380 }
381}
382
383/**
384 * Publishes an event so that it can be dispatched by the supplied plugin.
385 *
386 * @param {object} dispatchConfig Dispatch configuration for the event.
387 * @param {object} PluginModule Plugin publishing the event.
388 * @return {boolean} True if the event was successfully published.
389 * @private
390 */
391function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
392 !!eventNameDispatchConfigs.hasOwnProperty(eventName) ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : void 0;
393 eventNameDispatchConfigs[eventName] = dispatchConfig;
394
395 var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
396 if (phasedRegistrationNames) {
397 for (var phaseName in phasedRegistrationNames) {
398 if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
399 var phasedRegistrationName = phasedRegistrationNames[phaseName];
400 publishRegistrationName(phasedRegistrationName, pluginModule, eventName);
401 }
402 }
403 return true;
404 } else if (dispatchConfig.registrationName) {
405 publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName);
406 return true;
407 }
408 return false;
409}
410
411/**
412 * Publishes a registration name that is used to identify dispatched events.
413 *
414 * @param {string} registrationName Registration name to add.
415 * @param {object} PluginModule Plugin publishing the event.
416 * @private
417 */
418function publishRegistrationName(registrationName, pluginModule, eventName) {
419 !!registrationNameModules[registrationName] ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : void 0;
420 registrationNameModules[registrationName] = pluginModule;
421 registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies;
422
423 {
424 var lowerCasedName = registrationName.toLowerCase();
425 possibleRegistrationNames[lowerCasedName] = registrationName;
426
427 if (registrationName === 'onDoubleClick') {
428 possibleRegistrationNames.ondblclick = registrationName;
429 }
430 }
431}
432
433/**
434 * Registers plugins so that they can extract and dispatch events.
435 *
436 * @see {EventPluginHub}
437 */
438
439/**
440 * Ordered list of injected plugins.
441 */
442var plugins = [];
443
444/**
445 * Mapping from event name to dispatch config
446 */
447var eventNameDispatchConfigs = {};
448
449/**
450 * Mapping from registration name to plugin module
451 */
452var registrationNameModules = {};
453
454/**
455 * Mapping from registration name to event name
456 */
457var registrationNameDependencies = {};
458
459/**
460 * Mapping from lowercase registration names to the properly cased version,
461 * used to warn in the case of missing event handlers. Available
462 * only in true.
463 * @type {Object}
464 */
465var possibleRegistrationNames = {};
466// Trust the developer to only use possibleRegistrationNames in true
467
468/**
469 * Injects an ordering of plugins (by plugin name). This allows the ordering
470 * to be decoupled from injection of the actual plugins so that ordering is
471 * always deterministic regardless of packaging, on-the-fly injection, etc.
472 *
473 * @param {array} InjectedEventPluginOrder
474 * @internal
475 * @see {EventPluginHub.injection.injectEventPluginOrder}
476 */
477function injectEventPluginOrder(injectedEventPluginOrder) {
478 !!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;
479 // Clone the ordering so it cannot be dynamically mutated.
480 eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder);
481 recomputePluginOrdering();
482}
483
484/**
485 * Injects plugins to be used by `EventPluginHub`. The plugin names must be
486 * in the ordering injected by `injectEventPluginOrder`.
487 *
488 * Plugins can be injected as part of page initialization or on-the-fly.
489 *
490 * @param {object} injectedNamesToPlugins Map from names to plugin modules.
491 * @internal
492 * @see {EventPluginHub.injection.injectEventPluginsByName}
493 */
494function injectEventPluginsByName(injectedNamesToPlugins) {
495 {
496 if (shouldWarnOnInjection) {
497 var names = Object.keys(injectedNamesToPlugins).join(', ');
498 lowPriorityWarning$1(false, 'Injecting custom event plugins (%s) is deprecated ' + 'and will not work in React 17+. Please update your code ' + 'to not depend on React internals. The stack trace for this ' + 'warning should reveal the library that is using them. ' + 'See https://github.com/facebook/react/issues/11689 for a discussion.', names);
499 }
500 }
501
502 var isOrderingDirty = false;
503 for (var pluginName in injectedNamesToPlugins) {
504 if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
505 continue;
506 }
507 var pluginModule = injectedNamesToPlugins[pluginName];
508 if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) {
509 !!namesToPlugins[pluginName] ? invariant_1(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : void 0;
510 namesToPlugins[pluginName] = pluginModule;
511 isOrderingDirty = true;
512 }
513 }
514 if (isOrderingDirty) {
515 recomputePluginOrdering();
516 }
517}
518
519var EventPluginRegistry = Object.freeze({
520 enableWarningOnInjection: enableWarningOnInjection,
521 plugins: plugins,
522 eventNameDispatchConfigs: eventNameDispatchConfigs,
523 registrationNameModules: registrationNameModules,
524 registrationNameDependencies: registrationNameDependencies,
525 possibleRegistrationNames: possibleRegistrationNames,
526 injectEventPluginOrder: injectEventPluginOrder,
527 injectEventPluginsByName: injectEventPluginsByName
528});
529
530/**
531 * Copyright (c) 2013-present, Facebook, Inc.
532 *
533 * This source code is licensed under the MIT license found in the
534 * LICENSE file in the root directory of this source tree.
535 *
536 *
537 */
538
539function makeEmptyFunction(arg) {
540 return function () {
541 return arg;
542 };
543}
544
545/**
546 * This function accepts and discards inputs; it has no side effects. This is
547 * primarily useful idiomatically for overridable function endpoints which
548 * always need to be callable, since JS lacks a null-call idiom ala Cocoa.
549 */
550var emptyFunction = function emptyFunction() {};
551
552emptyFunction.thatReturns = makeEmptyFunction;
553emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
554emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
555emptyFunction.thatReturnsNull = makeEmptyFunction(null);
556emptyFunction.thatReturnsThis = function () {
557 return this;
558};
559emptyFunction.thatReturnsArgument = function (arg) {
560 return arg;
561};
562
563var emptyFunction_1 = emptyFunction;
564
565/**
566 * Copyright (c) 2014-present, Facebook, Inc.
567 *
568 * This source code is licensed under the MIT license found in the
569 * LICENSE file in the root directory of this source tree.
570 *
571 */
572
573
574
575
576
577/**
578 * Similar to invariant but only logs a warning if the condition is not met.
579 * This can be used to log issues in development environments in critical
580 * paths. Removing the logging code for production environments will keep the
581 * same logic and follow the same code paths.
582 */
583
584var warning = emptyFunction_1;
585
586{
587 var printWarning$1 = function printWarning(format) {
588 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
589 args[_key - 1] = arguments[_key];
590 }
591
592 var argIndex = 0;
593 var message = 'Warning: ' + format.replace(/%s/g, function () {
594 return args[argIndex++];
595 });
596 if (typeof console !== 'undefined') {
597 console.error(message);
598 }
599 try {
600 // --- Welcome to debugging React ---
601 // This error was thrown as a convenience so that you can use this stack
602 // to find the callsite that caused this warning to fire.
603 throw new Error(message);
604 } catch (x) {}
605 };
606
607 warning = function warning(condition, format) {
608 if (format === undefined) {
609 throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
610 }
611
612 if (format.indexOf('Failed Composite propType: ') === 0) {
613 return; // Ignore CompositeComponent proptype check.
614 }
615
616 if (!condition) {
617 for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
618 args[_key2 - 2] = arguments[_key2];
619 }
620
621 printWarning$1.apply(undefined, [format].concat(args));
622 }
623 };
624}
625
626var warning_1 = warning;
627
628var getFiberCurrentPropsFromNode = null;
629var getInstanceFromNode = null;
630var getNodeFromInstance = null;
631
632var injection$1 = {
633 injectComponentTree: function (Injected) {
634 getFiberCurrentPropsFromNode = Injected.getFiberCurrentPropsFromNode;
635 getInstanceFromNode = Injected.getInstanceFromNode;
636 getNodeFromInstance = Injected.getNodeFromInstance;
637
638 {
639 warning_1(getNodeFromInstance && getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.');
640 }
641 }
642};
643
644
645
646
647
648
649var validateEventDispatches = void 0;
650{
651 validateEventDispatches = function (event) {
652 var dispatchListeners = event._dispatchListeners;
653 var dispatchInstances = event._dispatchInstances;
654
655 var listenersIsArr = Array.isArray(dispatchListeners);
656 var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
657
658 var instancesIsArr = Array.isArray(dispatchInstances);
659 var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
660
661 warning_1(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.');
662 };
663}
664
665/**
666 * Dispatch the event to the listener.
667 * @param {SyntheticEvent} event SyntheticEvent to handle
668 * @param {boolean} simulated If the event is simulated (changes exn behavior)
669 * @param {function} listener Application-level callback
670 * @param {*} inst Internal component instance
671 */
672function executeDispatch(event, simulated, listener, inst) {
673 var type = event.type || 'unknown-event';
674 event.currentTarget = getNodeFromInstance(inst);
675 ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event);
676 event.currentTarget = null;
677}
678
679/**
680 * Standard/simple iteration through an event's collected dispatches.
681 */
682function executeDispatchesInOrder(event, simulated) {
683 var dispatchListeners = event._dispatchListeners;
684 var dispatchInstances = event._dispatchInstances;
685 {
686 validateEventDispatches(event);
687 }
688 if (Array.isArray(dispatchListeners)) {
689 for (var i = 0; i < dispatchListeners.length; i++) {
690 if (event.isPropagationStopped()) {
691 break;
692 }
693 // Listeners and Instances are two parallel arrays that are always in sync.
694 executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);
695 }
696 } else if (dispatchListeners) {
697 executeDispatch(event, simulated, dispatchListeners, dispatchInstances);
698 }
699 event._dispatchListeners = null;
700 event._dispatchInstances = null;
701}
702
703/**
704 * @see executeDispatchesInOrderStopAtTrueImpl
705 */
706
707
708/**
709 * Execution of a "direct" dispatch - there must be at most one dispatch
710 * accumulated on the event or it is considered an error. It doesn't really make
711 * sense for an event with multiple dispatches (bubbled) to keep track of the
712 * return values at each dispatch execution, but it does tend to make sense when
713 * dealing with "direct" dispatches.
714 *
715 * @return {*} The return value of executing the single dispatch.
716 */
717
718
719/**
720 * @param {SyntheticEvent} event
721 * @return {boolean} True iff number of dispatches accumulated is greater than 0.
722 */
723
724/**
725 * Accumulates items that must not be null or undefined into the first one. This
726 * is used to conserve memory by avoiding array allocations, and thus sacrifices
727 * API cleanness. Since `current` can be null before being passed in and not
728 * null after this function, make sure to assign it back to `current`:
729 *
730 * `a = accumulateInto(a, b);`
731 *
732 * This API should be sparingly used. Try `accumulate` for something cleaner.
733 *
734 * @return {*|array<*>} An accumulation of items.
735 */
736
737function accumulateInto(current, next) {
738 !(next != null) ? invariant_1(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : void 0;
739
740 if (current == null) {
741 return next;
742 }
743
744 // Both are not empty. Warning: Never call x.concat(y) when you are not
745 // certain that x is an Array (x could be a string with concat method).
746 if (Array.isArray(current)) {
747 if (Array.isArray(next)) {
748 current.push.apply(current, next);
749 return current;
750 }
751 current.push(next);
752 return current;
753 }
754
755 if (Array.isArray(next)) {
756 // A bit too dangerous to mutate `next`.
757 return [current].concat(next);
758 }
759
760 return [current, next];
761}
762
763/**
764 * @param {array} arr an "accumulation" of items which is either an Array or
765 * a single item. Useful when paired with the `accumulate` module. This is a
766 * simple utility that allows us to reason about a collection of items, but
767 * handling the case when there is exactly one item (and we do not need to
768 * allocate an array).
769 * @param {function} cb Callback invoked with each element or a collection.
770 * @param {?} [scope] Scope used as `this` in a callback.
771 */
772function forEachAccumulated(arr, cb, scope) {
773 if (Array.isArray(arr)) {
774 arr.forEach(cb, scope);
775 } else if (arr) {
776 cb.call(scope, arr);
777 }
778}
779
780/**
781 * Internal queue of events that have accumulated their dispatches and are
782 * waiting to have their dispatches executed.
783 */
784var eventQueue = null;
785
786/**
787 * Dispatches an event and releases it back into the pool, unless persistent.
788 *
789 * @param {?object} event Synthetic event to be dispatched.
790 * @param {boolean} simulated If the event is simulated (changes exn behavior)
791 * @private
792 */
793var executeDispatchesAndRelease = function (event, simulated) {
794 if (event) {
795 executeDispatchesInOrder(event, simulated);
796
797 if (!event.isPersistent()) {
798 event.constructor.release(event);
799 }
800 }
801};
802var executeDispatchesAndReleaseSimulated = function (e) {
803 return executeDispatchesAndRelease(e, true);
804};
805var executeDispatchesAndReleaseTopLevel = function (e) {
806 return executeDispatchesAndRelease(e, false);
807};
808
809function isInteractive(tag) {
810 return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
811}
812
813function shouldPreventMouseEvent(name, type, props) {
814 switch (name) {
815 case 'onClick':
816 case 'onClickCapture':
817 case 'onDoubleClick':
818 case 'onDoubleClickCapture':
819 case 'onMouseDown':
820 case 'onMouseDownCapture':
821 case 'onMouseMove':
822 case 'onMouseMoveCapture':
823 case 'onMouseUp':
824 case 'onMouseUpCapture':
825 return !!(props.disabled && isInteractive(type));
826 default:
827 return false;
828 }
829}
830
831/**
832 * This is a unified interface for event plugins to be installed and configured.
833 *
834 * Event plugins can implement the following properties:
835 *
836 * `extractEvents` {function(string, DOMEventTarget, string, object): *}
837 * Required. When a top-level event is fired, this method is expected to
838 * extract synthetic events that will in turn be queued and dispatched.
839 *
840 * `eventTypes` {object}
841 * Optional, plugins that fire events must publish a mapping of registration
842 * names that are used to register listeners. Values of this mapping must
843 * be objects that contain `registrationName` or `phasedRegistrationNames`.
844 *
845 * `executeDispatch` {function(object, function, string)}
846 * Optional, allows plugins to override how an event gets dispatched. By
847 * default, the listener is simply invoked.
848 *
849 * Each plugin that is injected into `EventsPluginHub` is immediately operable.
850 *
851 * @public
852 */
853
854/**
855 * Methods for injecting dependencies.
856 */
857var injection = {
858 /**
859 * @param {array} InjectedEventPluginOrder
860 * @public
861 */
862 injectEventPluginOrder: injectEventPluginOrder,
863
864 /**
865 * @param {object} injectedNamesToPlugins Map from names to plugin modules.
866 */
867 injectEventPluginsByName: injectEventPluginsByName
868};
869
870/**
871 * @param {object} inst The instance, which is the source of events.
872 * @param {string} registrationName Name of listener (e.g. `onClick`).
873 * @return {?function} The stored callback.
874 */
875function getListener(inst, registrationName) {
876 var listener = void 0;
877
878 // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
879 // live here; needs to be moved to a better place soon
880 var stateNode = inst.stateNode;
881 if (!stateNode) {
882 // Work in progress (ex: onload events in incremental mode).
883 return null;
884 }
885 var props = getFiberCurrentPropsFromNode(stateNode);
886 if (!props) {
887 // Work in progress.
888 return null;
889 }
890 listener = props[registrationName];
891 if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
892 return null;
893 }
894 !(!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;
895 return listener;
896}
897
898/**
899 * Allows registered plugins an opportunity to extract events from top-level
900 * native browser events.
901 *
902 * @return {*} An accumulation of synthetic events.
903 * @internal
904 */
905function extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
906 var events = void 0;
907 for (var i = 0; i < plugins.length; i++) {
908 // Not every plugin in the ordering may be loaded at runtime.
909 var possiblePlugin = plugins[i];
910 if (possiblePlugin) {
911 var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
912 if (extractedEvents) {
913 events = accumulateInto(events, extractedEvents);
914 }
915 }
916 }
917 return events;
918}
919
920/**
921 * Enqueues a synthetic event that should be dispatched when
922 * `processEventQueue` is invoked.
923 *
924 * @param {*} events An accumulation of synthetic events.
925 * @internal
926 */
927function enqueueEvents(events) {
928 if (events) {
929 eventQueue = accumulateInto(eventQueue, events);
930 }
931}
932
933/**
934 * Dispatches all synthetic events on the event queue.
935 *
936 * @internal
937 */
938function processEventQueue(simulated) {
939 // Set `eventQueue` to null before processing it so that we can tell if more
940 // events get enqueued while processing.
941 var processingEventQueue = eventQueue;
942 eventQueue = null;
943
944 if (!processingEventQueue) {
945 return;
946 }
947
948 if (simulated) {
949 forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);
950 } else {
951 forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);
952 }
953 !!eventQueue ? invariant_1(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : void 0;
954 // This would be a good time to rethrow if any of the event handlers threw.
955 ReactErrorUtils.rethrowCaughtError();
956}
957
958var EventPluginHub = Object.freeze({
959 injection: injection,
960 getListener: getListener,
961 extractEvents: extractEvents,
962 enqueueEvents: enqueueEvents,
963 processEventQueue: processEventQueue
964});
965
966var IndeterminateComponent = 0; // Before we know whether it is functional or class
967var FunctionalComponent = 1;
968var ClassComponent = 2;
969var HostRoot = 3; // Root of a host tree. Could be nested inside another node.
970var HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
971var HostComponent = 5;
972var HostText = 6;
973var CallComponent = 7;
974var CallHandlerPhase = 8;
975var ReturnComponent = 9;
976var Fragment = 10;
977
978var randomKey = Math.random().toString(36).slice(2);
979var internalInstanceKey = '__reactInternalInstance$' + randomKey;
980var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
981
982function precacheFiberNode$1(hostInst, node) {
983 node[internalInstanceKey] = hostInst;
984}
985
986/**
987 * Given a DOM node, return the closest ReactDOMComponent or
988 * ReactDOMTextComponent instance ancestor.
989 */
990function getClosestInstanceFromNode(node) {
991 if (node[internalInstanceKey]) {
992 return node[internalInstanceKey];
993 }
994
995 // Walk up the tree until we find an ancestor whose instance we have cached.
996 var parents = [];
997 while (!node[internalInstanceKey]) {
998 parents.push(node);
999 if (node.parentNode) {
1000 node = node.parentNode;
1001 } else {
1002 // Top of the tree. This node must not be part of a React tree (or is
1003 // unmounted, potentially).
1004 return null;
1005 }
1006 }
1007
1008 var closest = void 0;
1009 var inst = node[internalInstanceKey];
1010 if (inst.tag === HostComponent || inst.tag === HostText) {
1011 // In Fiber, this will always be the deepest root.
1012 return inst;
1013 }
1014 for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {
1015 closest = inst;
1016 }
1017
1018 return closest;
1019}
1020
1021/**
1022 * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
1023 * instance, or null if the node was not rendered by this React.
1024 */
1025function getInstanceFromNode$1(node) {
1026 var inst = node[internalInstanceKey];
1027 if (inst) {
1028 if (inst.tag === HostComponent || inst.tag === HostText) {
1029 return inst;
1030 } else {
1031 return null;
1032 }
1033 }
1034 return null;
1035}
1036
1037/**
1038 * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
1039 * DOM node.
1040 */
1041function getNodeFromInstance$1(inst) {
1042 if (inst.tag === HostComponent || inst.tag === HostText) {
1043 // In Fiber this, is just the state node right now. We assume it will be
1044 // a host component or host text.
1045 return inst.stateNode;
1046 }
1047
1048 // Without this first invariant, passing a non-DOM-component triggers the next
1049 // invariant for a missing parent, which is super confusing.
1050 invariant_1(false, 'getNodeFromInstance: Invalid argument.');
1051}
1052
1053function getFiberCurrentPropsFromNode$1(node) {
1054 return node[internalEventHandlersKey] || null;
1055}
1056
1057function updateFiberProps$1(node, props) {
1058 node[internalEventHandlersKey] = props;
1059}
1060
1061var ReactDOMComponentTree = Object.freeze({
1062 precacheFiberNode: precacheFiberNode$1,
1063 getClosestInstanceFromNode: getClosestInstanceFromNode,
1064 getInstanceFromNode: getInstanceFromNode$1,
1065 getNodeFromInstance: getNodeFromInstance$1,
1066 getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode$1,
1067 updateFiberProps: updateFiberProps$1
1068});
1069
1070function getParent(inst) {
1071 do {
1072 inst = inst['return'];
1073 // TODO: If this is a HostRoot we might want to bail out.
1074 // That is depending on if we want nested subtrees (layers) to bubble
1075 // events to their parent. We could also go through parentNode on the
1076 // host node but that wouldn't work for React Native and doesn't let us
1077 // do the portal feature.
1078 } while (inst && inst.tag !== HostComponent);
1079 if (inst) {
1080 return inst;
1081 }
1082 return null;
1083}
1084
1085/**
1086 * Return the lowest common ancestor of A and B, or null if they are in
1087 * different trees.
1088 */
1089function getLowestCommonAncestor(instA, instB) {
1090 var depthA = 0;
1091 for (var tempA = instA; tempA; tempA = getParent(tempA)) {
1092 depthA++;
1093 }
1094 var depthB = 0;
1095 for (var tempB = instB; tempB; tempB = getParent(tempB)) {
1096 depthB++;
1097 }
1098
1099 // If A is deeper, crawl up.
1100 while (depthA - depthB > 0) {
1101 instA = getParent(instA);
1102 depthA--;
1103 }
1104
1105 // If B is deeper, crawl up.
1106 while (depthB - depthA > 0) {
1107 instB = getParent(instB);
1108 depthB--;
1109 }
1110
1111 // Walk in lockstep until we find a match.
1112 var depth = depthA;
1113 while (depth--) {
1114 if (instA === instB || instA === instB.alternate) {
1115 return instA;
1116 }
1117 instA = getParent(instA);
1118 instB = getParent(instB);
1119 }
1120 return null;
1121}
1122
1123/**
1124 * Return if A is an ancestor of B.
1125 */
1126
1127
1128/**
1129 * Return the parent instance of the passed-in instance.
1130 */
1131function getParentInstance(inst) {
1132 return getParent(inst);
1133}
1134
1135/**
1136 * Simulates the traversal of a two-phase, capture/bubble event dispatch.
1137 */
1138function traverseTwoPhase(inst, fn, arg) {
1139 var path = [];
1140 while (inst) {
1141 path.push(inst);
1142 inst = getParent(inst);
1143 }
1144 var i = void 0;
1145 for (i = path.length; i-- > 0;) {
1146 fn(path[i], 'captured', arg);
1147 }
1148 for (i = 0; i < path.length; i++) {
1149 fn(path[i], 'bubbled', arg);
1150 }
1151}
1152
1153/**
1154 * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
1155 * should would receive a `mouseEnter` or `mouseLeave` event.
1156 *
1157 * Does not invoke the callback on the nearest common ancestor because nothing
1158 * "entered" or "left" that element.
1159 */
1160function traverseEnterLeave(from, to, fn, argFrom, argTo) {
1161 var common = from && to ? getLowestCommonAncestor(from, to) : null;
1162 var pathFrom = [];
1163 while (true) {
1164 if (!from) {
1165 break;
1166 }
1167 if (from === common) {
1168 break;
1169 }
1170 var alternate = from.alternate;
1171 if (alternate !== null && alternate === common) {
1172 break;
1173 }
1174 pathFrom.push(from);
1175 from = getParent(from);
1176 }
1177 var pathTo = [];
1178 while (true) {
1179 if (!to) {
1180 break;
1181 }
1182 if (to === common) {
1183 break;
1184 }
1185 var _alternate = to.alternate;
1186 if (_alternate !== null && _alternate === common) {
1187 break;
1188 }
1189 pathTo.push(to);
1190 to = getParent(to);
1191 }
1192 for (var i = 0; i < pathFrom.length; i++) {
1193 fn(pathFrom[i], 'bubbled', argFrom);
1194 }
1195 for (var _i = pathTo.length; _i-- > 0;) {
1196 fn(pathTo[_i], 'captured', argTo);
1197 }
1198}
1199
1200/**
1201 * Some event types have a notion of different registration names for different
1202 * "phases" of propagation. This finds listeners by a given phase.
1203 */
1204function listenerAtPhase(inst, event, propagationPhase) {
1205 var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
1206 return getListener(inst, registrationName);
1207}
1208
1209/**
1210 * A small set of propagation patterns, each of which will accept a small amount
1211 * of information, and generate a set of "dispatch ready event objects" - which
1212 * are sets of events that have already been annotated with a set of dispatched
1213 * listener functions/ids. The API is designed this way to discourage these
1214 * propagation strategies from actually executing the dispatches, since we
1215 * always want to collect the entire set of dispatches before executing even a
1216 * single one.
1217 */
1218
1219/**
1220 * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
1221 * here, allows us to not have to bind or create functions for each event.
1222 * Mutating the event's members allows us to not have to create a wrapping
1223 * "dispatch" object that pairs the event with the listener.
1224 */
1225function accumulateDirectionalDispatches(inst, phase, event) {
1226 {
1227 warning_1(inst, 'Dispatching inst must not be null');
1228 }
1229 var listener = listenerAtPhase(inst, event, phase);
1230 if (listener) {
1231 event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
1232 event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
1233 }
1234}
1235
1236/**
1237 * Collect dispatches (must be entirely collected before dispatching - see unit
1238 * tests). Lazily allocate the array to conserve memory. We must loop through
1239 * each event and perform the traversal for each one. We cannot perform a
1240 * single traversal for the entire collection of events because each event may
1241 * have a different target.
1242 */
1243function accumulateTwoPhaseDispatchesSingle(event) {
1244 if (event && event.dispatchConfig.phasedRegistrationNames) {
1245 traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
1246 }
1247}
1248
1249/**
1250 * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
1251 */
1252function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
1253 if (event && event.dispatchConfig.phasedRegistrationNames) {
1254 var targetInst = event._targetInst;
1255 var parentInst = targetInst ? getParentInstance(targetInst) : null;
1256 traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
1257 }
1258}
1259
1260/**
1261 * Accumulates without regard to direction, does not look for phased
1262 * registration names. Same as `accumulateDirectDispatchesSingle` but without
1263 * requiring that the `dispatchMarker` be the same as the dispatched ID.
1264 */
1265function accumulateDispatches(inst, ignoredDirection, event) {
1266 if (inst && event && event.dispatchConfig.registrationName) {
1267 var registrationName = event.dispatchConfig.registrationName;
1268 var listener = getListener(inst, registrationName);
1269 if (listener) {
1270 event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
1271 event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
1272 }
1273 }
1274}
1275
1276/**
1277 * Accumulates dispatches on an `SyntheticEvent`, but only for the
1278 * `dispatchMarker`.
1279 * @param {SyntheticEvent} event
1280 */
1281function accumulateDirectDispatchesSingle(event) {
1282 if (event && event.dispatchConfig.registrationName) {
1283 accumulateDispatches(event._targetInst, null, event);
1284 }
1285}
1286
1287function accumulateTwoPhaseDispatches(events) {
1288 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
1289}
1290
1291function accumulateTwoPhaseDispatchesSkipTarget(events) {
1292 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
1293}
1294
1295function accumulateEnterLeaveDispatches(leave, enter, from, to) {
1296 traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
1297}
1298
1299function accumulateDirectDispatches(events) {
1300 forEachAccumulated(events, accumulateDirectDispatchesSingle);
1301}
1302
1303var EventPropagators = Object.freeze({
1304 accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
1305 accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
1306 accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches,
1307 accumulateDirectDispatches: accumulateDirectDispatches
1308});
1309
1310/**
1311 * Copyright (c) 2013-present, Facebook, Inc.
1312 *
1313 * This source code is licensed under the MIT license found in the
1314 * LICENSE file in the root directory of this source tree.
1315 *
1316 */
1317
1318
1319
1320var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
1321
1322/**
1323 * Simple, lightweight module assisting with the detection and context of
1324 * Worker. Helps avoid circular dependencies and allows code to reason about
1325 * whether or not they are in a Worker, even if they never include the main
1326 * `ReactWorker` dependency.
1327 */
1328var ExecutionEnvironment = {
1329
1330 canUseDOM: canUseDOM,
1331
1332 canUseWorkers: typeof Worker !== 'undefined',
1333
1334 canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),
1335
1336 canUseViewport: canUseDOM && !!window.screen,
1337
1338 isInWorker: !canUseDOM // For now, this is true - might change in the future.
1339
1340};
1341
1342var ExecutionEnvironment_1 = ExecutionEnvironment;
1343
1344var contentKey = null;
1345
1346/**
1347 * Gets the key used to access text content on a DOM node.
1348 *
1349 * @return {?string} Key used to access text content.
1350 * @internal
1351 */
1352function getTextContentAccessor() {
1353 if (!contentKey && ExecutionEnvironment_1.canUseDOM) {
1354 // Prefer textContent to innerText because many browsers support both but
1355 // SVG <text> elements don't support innerText even when <div> does.
1356 contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';
1357 }
1358 return contentKey;
1359}
1360
1361/**
1362 * This helper object stores information about text content of a target node,
1363 * allowing comparison of content before and after a given event.
1364 *
1365 * Identify the node where selection currently begins, then observe
1366 * both its text content and its current position in the DOM. Since the
1367 * browser may natively replace the target node during composition, we can
1368 * use its position to find its replacement.
1369 *
1370 *
1371 */
1372var compositionState = {
1373 _root: null,
1374 _startText: null,
1375 _fallbackText: null
1376};
1377
1378function initialize(nativeEventTarget) {
1379 compositionState._root = nativeEventTarget;
1380 compositionState._startText = getText();
1381 return true;
1382}
1383
1384function reset() {
1385 compositionState._root = null;
1386 compositionState._startText = null;
1387 compositionState._fallbackText = null;
1388}
1389
1390function getData() {
1391 if (compositionState._fallbackText) {
1392 return compositionState._fallbackText;
1393 }
1394
1395 var start = void 0;
1396 var startValue = compositionState._startText;
1397 var startLength = startValue.length;
1398 var end = void 0;
1399 var endValue = getText();
1400 var endLength = endValue.length;
1401
1402 for (start = 0; start < startLength; start++) {
1403 if (startValue[start] !== endValue[start]) {
1404 break;
1405 }
1406 }
1407
1408 var minEnd = startLength - start;
1409 for (end = 1; end <= minEnd; end++) {
1410 if (startValue[startLength - end] !== endValue[endLength - end]) {
1411 break;
1412 }
1413 }
1414
1415 var sliceTail = end > 1 ? 1 - end : undefined;
1416 compositionState._fallbackText = endValue.slice(start, sliceTail);
1417 return compositionState._fallbackText;
1418}
1419
1420function getText() {
1421 if ('value' in compositionState._root) {
1422 return compositionState._root.value;
1423 }
1424 return compositionState._root[getTextContentAccessor()];
1425}
1426
1427var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
1428
1429var _assign = ReactInternals.assign;
1430
1431/* eslint valid-typeof: 0 */
1432
1433var didWarnForAddedNewProperty = false;
1434var isProxySupported = typeof Proxy === 'function';
1435var EVENT_POOL_SIZE = 10;
1436
1437var shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];
1438
1439/**
1440 * @interface Event
1441 * @see http://www.w3.org/TR/DOM-Level-3-Events/
1442 */
1443var EventInterface = {
1444 type: null,
1445 target: null,
1446 // currentTarget is set when dispatching; no use in copying it here
1447 currentTarget: emptyFunction_1.thatReturnsNull,
1448 eventPhase: null,
1449 bubbles: null,
1450 cancelable: null,
1451 timeStamp: function (event) {
1452 return event.timeStamp || Date.now();
1453 },
1454 defaultPrevented: null,
1455 isTrusted: null
1456};
1457
1458/**
1459 * Synthetic events are dispatched by event plugins, typically in response to a
1460 * top-level event delegation handler.
1461 *
1462 * These systems should generally use pooling to reduce the frequency of garbage
1463 * collection. The system should check `isPersistent` to determine whether the
1464 * event should be released into the pool after being dispatched. Users that
1465 * need a persisted event should invoke `persist`.
1466 *
1467 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
1468 * normalizing browser quirks. Subclasses do not necessarily have to implement a
1469 * DOM interface; custom application-specific events can also subclass this.
1470 *
1471 * @param {object} dispatchConfig Configuration used to dispatch this event.
1472 * @param {*} targetInst Marker identifying the event target.
1473 * @param {object} nativeEvent Native browser event.
1474 * @param {DOMEventTarget} nativeEventTarget Target node.
1475 */
1476function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
1477 {
1478 // these have a getter/setter for warnings
1479 delete this.nativeEvent;
1480 delete this.preventDefault;
1481 delete this.stopPropagation;
1482 }
1483
1484 this.dispatchConfig = dispatchConfig;
1485 this._targetInst = targetInst;
1486 this.nativeEvent = nativeEvent;
1487
1488 var Interface = this.constructor.Interface;
1489 for (var propName in Interface) {
1490 if (!Interface.hasOwnProperty(propName)) {
1491 continue;
1492 }
1493 {
1494 delete this[propName]; // this has a getter/setter for warnings
1495 }
1496 var normalize = Interface[propName];
1497 if (normalize) {
1498 this[propName] = normalize(nativeEvent);
1499 } else {
1500 if (propName === 'target') {
1501 this.target = nativeEventTarget;
1502 } else {
1503 this[propName] = nativeEvent[propName];
1504 }
1505 }
1506 }
1507
1508 var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
1509 if (defaultPrevented) {
1510 this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue;
1511 } else {
1512 this.isDefaultPrevented = emptyFunction_1.thatReturnsFalse;
1513 }
1514 this.isPropagationStopped = emptyFunction_1.thatReturnsFalse;
1515 return this;
1516}
1517
1518_assign(SyntheticEvent.prototype, {
1519 preventDefault: function () {
1520 this.defaultPrevented = true;
1521 var event = this.nativeEvent;
1522 if (!event) {
1523 return;
1524 }
1525
1526 if (event.preventDefault) {
1527 event.preventDefault();
1528 } else if (typeof event.returnValue !== 'unknown') {
1529 event.returnValue = false;
1530 }
1531 this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue;
1532 },
1533
1534 stopPropagation: function () {
1535 var event = this.nativeEvent;
1536 if (!event) {
1537 return;
1538 }
1539
1540 if (event.stopPropagation) {
1541 event.stopPropagation();
1542 } else if (typeof event.cancelBubble !== 'unknown') {
1543 // The ChangeEventPlugin registers a "propertychange" event for
1544 // IE. This event does not support bubbling or cancelling, and
1545 // any references to cancelBubble throw "Member not found". A
1546 // typeof check of "unknown" circumvents this issue (and is also
1547 // IE specific).
1548 event.cancelBubble = true;
1549 }
1550
1551 this.isPropagationStopped = emptyFunction_1.thatReturnsTrue;
1552 },
1553
1554 /**
1555 * We release all dispatched `SyntheticEvent`s after each event loop, adding
1556 * them back into the pool. This allows a way to hold onto a reference that
1557 * won't be added back into the pool.
1558 */
1559 persist: function () {
1560 this.isPersistent = emptyFunction_1.thatReturnsTrue;
1561 },
1562
1563 /**
1564 * Checks if this event should be released back into the pool.
1565 *
1566 * @return {boolean} True if this should not be released, false otherwise.
1567 */
1568 isPersistent: emptyFunction_1.thatReturnsFalse,
1569
1570 /**
1571 * `PooledClass` looks for `destructor` on each instance it releases.
1572 */
1573 destructor: function () {
1574 var Interface = this.constructor.Interface;
1575 for (var propName in Interface) {
1576 {
1577 Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));
1578 }
1579 }
1580 for (var i = 0; i < shouldBeReleasedProperties.length; i++) {
1581 this[shouldBeReleasedProperties[i]] = null;
1582 }
1583 {
1584 Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));
1585 Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', emptyFunction_1));
1586 Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction_1));
1587 }
1588 }
1589});
1590
1591SyntheticEvent.Interface = EventInterface;
1592
1593/**
1594 * Helper to reduce boilerplate when creating subclasses.
1595 */
1596SyntheticEvent.extend = function (Interface) {
1597 var Super = this;
1598
1599 var E = function () {};
1600 E.prototype = Super.prototype;
1601 var prototype = new E();
1602
1603 function Class() {
1604 return Super.apply(this, arguments);
1605 }
1606 _assign(prototype, Class.prototype);
1607 Class.prototype = prototype;
1608 Class.prototype.constructor = Class;
1609
1610 Class.Interface = _assign({}, Super.Interface, Interface);
1611 Class.extend = Super.extend;
1612 addEventPoolingTo(Class);
1613
1614 return Class;
1615};
1616
1617/** Proxying after everything set on SyntheticEvent
1618 * to resolve Proxy issue on some WebKit browsers
1619 * in which some Event properties are set to undefined (GH#10010)
1620 */
1621{
1622 if (isProxySupported) {
1623 /*eslint-disable no-func-assign */
1624 SyntheticEvent = new Proxy(SyntheticEvent, {
1625 construct: function (target, args) {
1626 return this.apply(target, Object.create(target.prototype), args);
1627 },
1628 apply: function (constructor, that, args) {
1629 return new Proxy(constructor.apply(that, args), {
1630 set: function (target, prop, value) {
1631 if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {
1632 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.');
1633 didWarnForAddedNewProperty = true;
1634 }
1635 target[prop] = value;
1636 return true;
1637 }
1638 });
1639 }
1640 });
1641 /*eslint-enable no-func-assign */
1642 }
1643}
1644
1645addEventPoolingTo(SyntheticEvent);
1646
1647/**
1648 * Helper to nullify syntheticEvent instance properties when destructing
1649 *
1650 * @param {String} propName
1651 * @param {?object} getVal
1652 * @return {object} defineProperty object
1653 */
1654function getPooledWarningPropertyDefinition(propName, getVal) {
1655 var isFunction = typeof getVal === 'function';
1656 return {
1657 configurable: true,
1658 set: set,
1659 get: get
1660 };
1661
1662 function set(val) {
1663 var action = isFunction ? 'setting the method' : 'setting the property';
1664 warn(action, 'This is effectively a no-op');
1665 return val;
1666 }
1667
1668 function get() {
1669 var action = isFunction ? 'accessing the method' : 'accessing the property';
1670 var result = isFunction ? 'This is a no-op function' : 'This is set to null';
1671 warn(action, result);
1672 return getVal;
1673 }
1674
1675 function warn(action, result) {
1676 var warningCondition = false;
1677 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);
1678 }
1679}
1680
1681function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {
1682 var EventConstructor = this;
1683 if (EventConstructor.eventPool.length) {
1684 var instance = EventConstructor.eventPool.pop();
1685 EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst);
1686 return instance;
1687 }
1688 return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst);
1689}
1690
1691function releasePooledEvent(event) {
1692 var EventConstructor = this;
1693 !(event instanceof EventConstructor) ? invariant_1(false, 'Trying to release an event instance into a pool of a different type.') : void 0;
1694 event.destructor();
1695 if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
1696 EventConstructor.eventPool.push(event);
1697 }
1698}
1699
1700function addEventPoolingTo(EventConstructor) {
1701 EventConstructor.eventPool = [];
1702 EventConstructor.getPooled = getPooledEvent;
1703 EventConstructor.release = releasePooledEvent;
1704}
1705
1706var SyntheticEvent$1 = SyntheticEvent;
1707
1708/**
1709 * @interface Event
1710 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents
1711 */
1712var SyntheticCompositionEvent = SyntheticEvent$1.extend({
1713 data: null
1714});
1715
1716/**
1717 * @interface Event
1718 * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
1719 * /#events-inputevents
1720 */
1721var SyntheticInputEvent = SyntheticEvent$1.extend({
1722 data: null
1723});
1724
1725var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
1726var START_KEYCODE = 229;
1727
1728var canUseCompositionEvent = ExecutionEnvironment_1.canUseDOM && 'CompositionEvent' in window;
1729
1730var documentMode = null;
1731if (ExecutionEnvironment_1.canUseDOM && 'documentMode' in document) {
1732 documentMode = document.documentMode;
1733}
1734
1735// Webkit offers a very useful `textInput` event that can be used to
1736// directly represent `beforeInput`. The IE `textinput` event is not as
1737// useful, so we don't use it.
1738var canUseTextInputEvent = ExecutionEnvironment_1.canUseDOM && 'TextEvent' in window && !documentMode;
1739
1740// In IE9+, we have access to composition events, but the data supplied
1741// by the native compositionend event may be incorrect. Japanese ideographic
1742// spaces, for instance (\u3000) are not recorded correctly.
1743var useFallbackCompositionData = ExecutionEnvironment_1.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);
1744
1745var SPACEBAR_CODE = 32;
1746var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
1747
1748// Events and their corresponding property names.
1749var eventTypes = {
1750 beforeInput: {
1751 phasedRegistrationNames: {
1752 bubbled: 'onBeforeInput',
1753 captured: 'onBeforeInputCapture'
1754 },
1755 dependencies: ['topCompositionEnd', 'topKeyPress', 'topTextInput', 'topPaste']
1756 },
1757 compositionEnd: {
1758 phasedRegistrationNames: {
1759 bubbled: 'onCompositionEnd',
1760 captured: 'onCompositionEndCapture'
1761 },
1762 dependencies: ['topBlur', 'topCompositionEnd', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
1763 },
1764 compositionStart: {
1765 phasedRegistrationNames: {
1766 bubbled: 'onCompositionStart',
1767 captured: 'onCompositionStartCapture'
1768 },
1769 dependencies: ['topBlur', 'topCompositionStart', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
1770 },
1771 compositionUpdate: {
1772 phasedRegistrationNames: {
1773 bubbled: 'onCompositionUpdate',
1774 captured: 'onCompositionUpdateCapture'
1775 },
1776 dependencies: ['topBlur', 'topCompositionUpdate', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
1777 }
1778};
1779
1780// Track whether we've ever handled a keypress on the space key.
1781var hasSpaceKeypress = false;
1782
1783/**
1784 * Return whether a native keypress event is assumed to be a command.
1785 * This is required because Firefox fires `keypress` events for key commands
1786 * (cut, copy, select-all, etc.) even though no character is inserted.
1787 */
1788function isKeypressCommand(nativeEvent) {
1789 return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
1790 // ctrlKey && altKey is equivalent to AltGr, and is not a command.
1791 !(nativeEvent.ctrlKey && nativeEvent.altKey);
1792}
1793
1794/**
1795 * Translate native top level events into event types.
1796 *
1797 * @param {string} topLevelType
1798 * @return {object}
1799 */
1800function getCompositionEventType(topLevelType) {
1801 switch (topLevelType) {
1802 case 'topCompositionStart':
1803 return eventTypes.compositionStart;
1804 case 'topCompositionEnd':
1805 return eventTypes.compositionEnd;
1806 case 'topCompositionUpdate':
1807 return eventTypes.compositionUpdate;
1808 }
1809}
1810
1811/**
1812 * Does our fallback best-guess model think this event signifies that
1813 * composition has begun?
1814 *
1815 * @param {string} topLevelType
1816 * @param {object} nativeEvent
1817 * @return {boolean}
1818 */
1819function isFallbackCompositionStart(topLevelType, nativeEvent) {
1820 return topLevelType === 'topKeyDown' && nativeEvent.keyCode === START_KEYCODE;
1821}
1822
1823/**
1824 * Does our fallback mode think that this event is the end of composition?
1825 *
1826 * @param {string} topLevelType
1827 * @param {object} nativeEvent
1828 * @return {boolean}
1829 */
1830function isFallbackCompositionEnd(topLevelType, nativeEvent) {
1831 switch (topLevelType) {
1832 case 'topKeyUp':
1833 // Command keys insert or clear IME input.
1834 return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
1835 case 'topKeyDown':
1836 // Expect IME keyCode on each keydown. If we get any other
1837 // code we must have exited earlier.
1838 return nativeEvent.keyCode !== START_KEYCODE;
1839 case 'topKeyPress':
1840 case 'topMouseDown':
1841 case 'topBlur':
1842 // Events are not possible without cancelling IME.
1843 return true;
1844 default:
1845 return false;
1846 }
1847}
1848
1849/**
1850 * Google Input Tools provides composition data via a CustomEvent,
1851 * with the `data` property populated in the `detail` object. If this
1852 * is available on the event object, use it. If not, this is a plain
1853 * composition event and we have nothing special to extract.
1854 *
1855 * @param {object} nativeEvent
1856 * @return {?string}
1857 */
1858function getDataFromCustomEvent(nativeEvent) {
1859 var detail = nativeEvent.detail;
1860 if (typeof detail === 'object' && 'data' in detail) {
1861 return detail.data;
1862 }
1863 return null;
1864}
1865
1866// Track the current IME composition status, if any.
1867var isComposing = false;
1868
1869/**
1870 * @return {?object} A SyntheticCompositionEvent.
1871 */
1872function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
1873 var eventType = void 0;
1874 var fallbackData = void 0;
1875
1876 if (canUseCompositionEvent) {
1877 eventType = getCompositionEventType(topLevelType);
1878 } else if (!isComposing) {
1879 if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
1880 eventType = eventTypes.compositionStart;
1881 }
1882 } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
1883 eventType = eventTypes.compositionEnd;
1884 }
1885
1886 if (!eventType) {
1887 return null;
1888 }
1889
1890 if (useFallbackCompositionData) {
1891 // The current composition is stored statically and must not be
1892 // overwritten while composition continues.
1893 if (!isComposing && eventType === eventTypes.compositionStart) {
1894 isComposing = initialize(nativeEventTarget);
1895 } else if (eventType === eventTypes.compositionEnd) {
1896 if (isComposing) {
1897 fallbackData = getData();
1898 }
1899 }
1900 }
1901
1902 var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);
1903
1904 if (fallbackData) {
1905 // Inject data generated from fallback path into the synthetic event.
1906 // This matches the property of native CompositionEventInterface.
1907 event.data = fallbackData;
1908 } else {
1909 var customData = getDataFromCustomEvent(nativeEvent);
1910 if (customData !== null) {
1911 event.data = customData;
1912 }
1913 }
1914
1915 accumulateTwoPhaseDispatches(event);
1916 return event;
1917}
1918
1919/**
1920 * @param {TopLevelTypes} topLevelType Record from `BrowserEventConstants`.
1921 * @param {object} nativeEvent Native browser event.
1922 * @return {?string} The string corresponding to this `beforeInput` event.
1923 */
1924function getNativeBeforeInputChars(topLevelType, nativeEvent) {
1925 switch (topLevelType) {
1926 case 'topCompositionEnd':
1927 return getDataFromCustomEvent(nativeEvent);
1928 case 'topKeyPress':
1929 /**
1930 * If native `textInput` events are available, our goal is to make
1931 * use of them. However, there is a special case: the spacebar key.
1932 * In Webkit, preventing default on a spacebar `textInput` event
1933 * cancels character insertion, but it *also* causes the browser
1934 * to fall back to its default spacebar behavior of scrolling the
1935 * page.
1936 *
1937 * Tracking at:
1938 * https://code.google.com/p/chromium/issues/detail?id=355103
1939 *
1940 * To avoid this issue, use the keypress event as if no `textInput`
1941 * event is available.
1942 */
1943 var which = nativeEvent.which;
1944 if (which !== SPACEBAR_CODE) {
1945 return null;
1946 }
1947
1948 hasSpaceKeypress = true;
1949 return SPACEBAR_CHAR;
1950
1951 case 'topTextInput':
1952 // Record the characters to be added to the DOM.
1953 var chars = nativeEvent.data;
1954
1955 // If it's a spacebar character, assume that we have already handled
1956 // it at the keypress level and bail immediately. Android Chrome
1957 // doesn't give us keycodes, so we need to blacklist it.
1958 if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
1959 return null;
1960 }
1961
1962 return chars;
1963
1964 default:
1965 // For other native event types, do nothing.
1966 return null;
1967 }
1968}
1969
1970/**
1971 * For browsers that do not provide the `textInput` event, extract the
1972 * appropriate string to use for SyntheticInputEvent.
1973 *
1974 * @param {string} topLevelType Record from `BrowserEventConstants`.
1975 * @param {object} nativeEvent Native browser event.
1976 * @return {?string} The fallback string for this `beforeInput` event.
1977 */
1978function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
1979 // If we are currently composing (IME) and using a fallback to do so,
1980 // try to extract the composed characters from the fallback object.
1981 // If composition event is available, we extract a string only at
1982 // compositionevent, otherwise extract it at fallback events.
1983 if (isComposing) {
1984 if (topLevelType === 'topCompositionEnd' || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) {
1985 var chars = getData();
1986 reset();
1987 isComposing = false;
1988 return chars;
1989 }
1990 return null;
1991 }
1992
1993 switch (topLevelType) {
1994 case 'topPaste':
1995 // If a paste event occurs after a keypress, throw out the input
1996 // chars. Paste events should not lead to BeforeInput events.
1997 return null;
1998 case 'topKeyPress':
1999 /**
2000 * As of v27, Firefox may fire keypress events even when no character
2001 * will be inserted. A few possibilities:
2002 *
2003 * - `which` is `0`. Arrow keys, Esc key, etc.
2004 *
2005 * - `which` is the pressed key code, but no char is available.
2006 * Ex: 'AltGr + d` in Polish. There is no modified character for
2007 * this key combination and no character is inserted into the
2008 * document, but FF fires the keypress for char code `100` anyway.
2009 * No `input` event will occur.
2010 *
2011 * - `which` is the pressed key code, but a command combination is
2012 * being used. Ex: `Cmd+C`. No character is inserted, and no
2013 * `input` event will occur.
2014 */
2015 if (!isKeypressCommand(nativeEvent)) {
2016 // IE fires the `keypress` event when a user types an emoji via
2017 // Touch keyboard of Windows. In such a case, the `char` property
2018 // holds an emoji character like `\uD83D\uDE0A`. Because its length
2019 // is 2, the property `which` does not represent an emoji correctly.
2020 // In such a case, we directly return the `char` property instead of
2021 // using `which`.
2022 if (nativeEvent.char && nativeEvent.char.length > 1) {
2023 return nativeEvent.char;
2024 } else if (nativeEvent.which) {
2025 return String.fromCharCode(nativeEvent.which);
2026 }
2027 }
2028 return null;
2029 case 'topCompositionEnd':
2030 return useFallbackCompositionData ? null : nativeEvent.data;
2031 default:
2032 return null;
2033 }
2034}
2035
2036/**
2037 * Extract a SyntheticInputEvent for `beforeInput`, based on either native
2038 * `textInput` or fallback behavior.
2039 *
2040 * @return {?object} A SyntheticInputEvent.
2041 */
2042function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
2043 var chars = void 0;
2044
2045 if (canUseTextInputEvent) {
2046 chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
2047 } else {
2048 chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
2049 }
2050
2051 // If no characters are being inserted, no BeforeInput event should
2052 // be fired.
2053 if (!chars) {
2054 return null;
2055 }
2056
2057 var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);
2058
2059 event.data = chars;
2060 accumulateTwoPhaseDispatches(event);
2061 return event;
2062}
2063
2064/**
2065 * Create an `onBeforeInput` event to match
2066 * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
2067 *
2068 * This event plugin is based on the native `textInput` event
2069 * available in Chrome, Safari, Opera, and IE. This event fires after
2070 * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
2071 *
2072 * `beforeInput` is spec'd but not implemented in any browsers, and
2073 * the `input` event does not provide any useful information about what has
2074 * actually been added, contrary to the spec. Thus, `textInput` is the best
2075 * available event to identify the characters that have actually been inserted
2076 * into the target node.
2077 *
2078 * This plugin is also responsible for emitting `composition` events, thus
2079 * allowing us to share composition fallback code for both `beforeInput` and
2080 * `composition` event types.
2081 */
2082var BeforeInputEventPlugin = {
2083 eventTypes: eventTypes,
2084
2085 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
2086 var composition = extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget);
2087
2088 var beforeInput = extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget);
2089
2090 if (composition === null) {
2091 return beforeInput;
2092 }
2093
2094 if (beforeInput === null) {
2095 return composition;
2096 }
2097
2098 return [composition, beforeInput];
2099 }
2100};
2101
2102// Use to restore controlled state after a change event has fired.
2103
2104var fiberHostComponent = null;
2105
2106var ReactControlledComponentInjection = {
2107 injectFiberControlledHostComponent: function (hostComponentImpl) {
2108 // The fiber implementation doesn't use dynamic dispatch so we need to
2109 // inject the implementation.
2110 fiberHostComponent = hostComponentImpl;
2111 }
2112};
2113
2114var restoreTarget = null;
2115var restoreQueue = null;
2116
2117function restoreStateOfTarget(target) {
2118 // We perform this translation at the end of the event loop so that we
2119 // always receive the correct fiber here
2120 var internalInstance = getInstanceFromNode(target);
2121 if (!internalInstance) {
2122 // Unmounted
2123 return;
2124 }
2125 !(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;
2126 var props = getFiberCurrentPropsFromNode(internalInstance.stateNode);
2127 fiberHostComponent.restoreControlledState(internalInstance.stateNode, internalInstance.type, props);
2128}
2129
2130var injection$2 = ReactControlledComponentInjection;
2131
2132function enqueueStateRestore(target) {
2133 if (restoreTarget) {
2134 if (restoreQueue) {
2135 restoreQueue.push(target);
2136 } else {
2137 restoreQueue = [target];
2138 }
2139 } else {
2140 restoreTarget = target;
2141 }
2142}
2143
2144function restoreStateIfNeeded() {
2145 if (!restoreTarget) {
2146 return;
2147 }
2148 var target = restoreTarget;
2149 var queuedTargets = restoreQueue;
2150 restoreTarget = null;
2151 restoreQueue = null;
2152
2153 restoreStateOfTarget(target);
2154 if (queuedTargets) {
2155 for (var i = 0; i < queuedTargets.length; i++) {
2156 restoreStateOfTarget(queuedTargets[i]);
2157 }
2158 }
2159}
2160
2161var ReactControlledComponent = Object.freeze({
2162 injection: injection$2,
2163 enqueueStateRestore: enqueueStateRestore,
2164 restoreStateIfNeeded: restoreStateIfNeeded
2165});
2166
2167// Used as a way to call batchedUpdates when we don't have a reference to
2168// the renderer. Such as when we're dispatching events or if third party
2169// libraries need to call batchedUpdates. Eventually, this API will go away when
2170// everything is batched by default. We'll then have a similar API to opt-out of
2171// scheduled work and instead do synchronous work.
2172
2173// Defaults
2174var fiberBatchedUpdates = function (fn, bookkeeping) {
2175 return fn(bookkeeping);
2176};
2177
2178var isNestingBatched = false;
2179function batchedUpdates(fn, bookkeeping) {
2180 if (isNestingBatched) {
2181 // If we are currently inside another batch, we need to wait until it
2182 // fully completes before restoring state. Therefore, we add the target to
2183 // a queue of work.
2184 return fiberBatchedUpdates(fn, bookkeeping);
2185 }
2186 isNestingBatched = true;
2187 try {
2188 return fiberBatchedUpdates(fn, bookkeeping);
2189 } finally {
2190 // Here we wait until all updates have propagated, which is important
2191 // when using controlled components within layers:
2192 // https://github.com/facebook/react/issues/1698
2193 // Then we restore state of any controlled component.
2194 isNestingBatched = false;
2195 restoreStateIfNeeded();
2196 }
2197}
2198
2199var ReactGenericBatchingInjection = {
2200 injectFiberBatchedUpdates: function (_batchedUpdates) {
2201 fiberBatchedUpdates = _batchedUpdates;
2202 }
2203};
2204
2205var injection$3 = ReactGenericBatchingInjection;
2206
2207/**
2208 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
2209 */
2210var supportedInputTypes = {
2211 color: true,
2212 date: true,
2213 datetime: true,
2214 'datetime-local': true,
2215 email: true,
2216 month: true,
2217 number: true,
2218 password: true,
2219 range: true,
2220 search: true,
2221 tel: true,
2222 text: true,
2223 time: true,
2224 url: true,
2225 week: true
2226};
2227
2228function isTextInputElement(elem) {
2229 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
2230
2231 if (nodeName === 'input') {
2232 return !!supportedInputTypes[elem.type];
2233 }
2234
2235 if (nodeName === 'textarea') {
2236 return true;
2237 }
2238
2239 return false;
2240}
2241
2242/**
2243 * HTML nodeType values that represent the type of the node
2244 */
2245
2246var ELEMENT_NODE = 1;
2247var TEXT_NODE = 3;
2248var COMMENT_NODE = 8;
2249var DOCUMENT_NODE = 9;
2250var DOCUMENT_FRAGMENT_NODE = 11;
2251
2252/**
2253 * Gets the target node from a native browser event by accounting for
2254 * inconsistencies in browser DOM APIs.
2255 *
2256 * @param {object} nativeEvent Native browser event.
2257 * @return {DOMEventTarget} Target node.
2258 */
2259function getEventTarget(nativeEvent) {
2260 var target = nativeEvent.target || nativeEvent.srcElement || window;
2261
2262 // Normalize SVG <use> element events #4963
2263 if (target.correspondingUseElement) {
2264 target = target.correspondingUseElement;
2265 }
2266
2267 // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
2268 // @see http://www.quirksmode.org/js/events_properties.html
2269 return target.nodeType === TEXT_NODE ? target.parentNode : target;
2270}
2271
2272/**
2273 * Checks if an event is supported in the current execution environment.
2274 *
2275 * NOTE: This will not work correctly for non-generic events such as `change`,
2276 * `reset`, `load`, `error`, and `select`.
2277 *
2278 * Borrows from Modernizr.
2279 *
2280 * @param {string} eventNameSuffix Event name, e.g. "click".
2281 * @param {?boolean} capture Check if the capture phase is supported.
2282 * @return {boolean} True if the event is supported.
2283 * @internal
2284 * @license Modernizr 3.0.0pre (Custom Build) | MIT
2285 */
2286function isEventSupported(eventNameSuffix, capture) {
2287 if (!ExecutionEnvironment_1.canUseDOM || capture && !('addEventListener' in document)) {
2288 return false;
2289 }
2290
2291 var eventName = 'on' + eventNameSuffix;
2292 var isSupported = eventName in document;
2293
2294 if (!isSupported) {
2295 var element = document.createElement('div');
2296 element.setAttribute(eventName, 'return;');
2297 isSupported = typeof element[eventName] === 'function';
2298 }
2299
2300 return isSupported;
2301}
2302
2303function isCheckable(elem) {
2304 var type = elem.type;
2305 var nodeName = elem.nodeName;
2306 return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
2307}
2308
2309function getTracker(node) {
2310 return node._valueTracker;
2311}
2312
2313function detachTracker(node) {
2314 node._valueTracker = null;
2315}
2316
2317function getValueFromNode(node) {
2318 var value = '';
2319 if (!node) {
2320 return value;
2321 }
2322
2323 if (isCheckable(node)) {
2324 value = node.checked ? 'true' : 'false';
2325 } else {
2326 value = node.value;
2327 }
2328
2329 return value;
2330}
2331
2332function trackValueOnNode(node) {
2333 var valueField = isCheckable(node) ? 'checked' : 'value';
2334 var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);
2335
2336 var currentValue = '' + node[valueField];
2337
2338 // if someone has already defined a value or Safari, then bail
2339 // and don't track value will cause over reporting of changes,
2340 // but it's better then a hard failure
2341 // (needed for certain tests that spyOn input values and Safari)
2342 if (node.hasOwnProperty(valueField) || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
2343 return;
2344 }
2345
2346 Object.defineProperty(node, valueField, {
2347 enumerable: descriptor.enumerable,
2348 configurable: true,
2349 get: function () {
2350 return descriptor.get.call(this);
2351 },
2352 set: function (value) {
2353 currentValue = '' + value;
2354 descriptor.set.call(this, value);
2355 }
2356 });
2357
2358 var tracker = {
2359 getValue: function () {
2360 return currentValue;
2361 },
2362 setValue: function (value) {
2363 currentValue = '' + value;
2364 },
2365 stopTracking: function () {
2366 detachTracker(node);
2367 delete node[valueField];
2368 }
2369 };
2370 return tracker;
2371}
2372
2373function track(node) {
2374 if (getTracker(node)) {
2375 return;
2376 }
2377
2378 // TODO: Once it's just Fiber we can move this to node._wrapperState
2379 node._valueTracker = trackValueOnNode(node);
2380}
2381
2382function updateValueIfChanged(node) {
2383 if (!node) {
2384 return false;
2385 }
2386
2387 var tracker = getTracker(node);
2388 // if there is no tracker at this point it's unlikely
2389 // that trying again will succeed
2390 if (!tracker) {
2391 return true;
2392 }
2393
2394 var lastValue = tracker.getValue();
2395 var nextValue = getValueFromNode(node);
2396 if (nextValue !== lastValue) {
2397 tracker.setValue(nextValue);
2398 return true;
2399 }
2400 return false;
2401}
2402
2403var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
2404
2405var ReactCurrentOwner = ReactInternals$1.ReactCurrentOwner;
2406var ReactDebugCurrentFrame = ReactInternals$1.ReactDebugCurrentFrame;
2407
2408var describeComponentFrame = function (name, source, ownerName) {
2409 return '\n in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
2410};
2411
2412// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
2413// nor polyfill, then a plain number is used for performance.
2414var hasSymbol = typeof Symbol === 'function' && Symbol['for'];
2415
2416var REACT_ELEMENT_TYPE = hasSymbol ? Symbol['for']('react.element') : 0xeac7;
2417var REACT_CALL_TYPE = hasSymbol ? Symbol['for']('react.call') : 0xeac8;
2418var REACT_RETURN_TYPE = hasSymbol ? Symbol['for']('react.return') : 0xeac9;
2419var REACT_PORTAL_TYPE = hasSymbol ? Symbol['for']('react.portal') : 0xeaca;
2420var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol['for']('react.fragment') : 0xeacb;
2421
2422var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
2423var FAUX_ITERATOR_SYMBOL = '@@iterator';
2424
2425function getIteratorFn(maybeIterable) {
2426 if (maybeIterable === null || typeof maybeIterable === 'undefined') {
2427 return null;
2428 }
2429 var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
2430 if (typeof maybeIterator === 'function') {
2431 return maybeIterator;
2432 }
2433 return null;
2434}
2435
2436function getComponentName(fiber) {
2437 var type = fiber.type;
2438
2439 if (typeof type === 'function') {
2440 return type.displayName || type.name;
2441 }
2442 if (typeof type === 'string') {
2443 return type;
2444 }
2445 switch (type) {
2446 case REACT_FRAGMENT_TYPE:
2447 return 'ReactFragment';
2448 case REACT_PORTAL_TYPE:
2449 return 'ReactPortal';
2450 case REACT_CALL_TYPE:
2451 return 'ReactCall';
2452 case REACT_RETURN_TYPE:
2453 return 'ReactReturn';
2454 }
2455 return null;
2456}
2457
2458function describeFiber(fiber) {
2459 switch (fiber.tag) {
2460 case IndeterminateComponent:
2461 case FunctionalComponent:
2462 case ClassComponent:
2463 case HostComponent:
2464 var owner = fiber._debugOwner;
2465 var source = fiber._debugSource;
2466 var name = getComponentName(fiber);
2467 var ownerName = null;
2468 if (owner) {
2469 ownerName = getComponentName(owner);
2470 }
2471 return describeComponentFrame(name, source, ownerName);
2472 default:
2473 return '';
2474 }
2475}
2476
2477// This function can only be called with a work-in-progress fiber and
2478// only during begin or complete phase. Do not call it under any other
2479// circumstances.
2480function getStackAddendumByWorkInProgressFiber(workInProgress) {
2481 var info = '';
2482 var node = workInProgress;
2483 do {
2484 info += describeFiber(node);
2485 // Otherwise this return pointer might point to the wrong tree:
2486 node = node['return'];
2487 } while (node);
2488 return info;
2489}
2490
2491function getCurrentFiberOwnerName$1() {
2492 {
2493 var fiber = ReactDebugCurrentFiber.current;
2494 if (fiber === null) {
2495 return null;
2496 }
2497 var owner = fiber._debugOwner;
2498 if (owner !== null && typeof owner !== 'undefined') {
2499 return getComponentName(owner);
2500 }
2501 }
2502 return null;
2503}
2504
2505function getCurrentFiberStackAddendum$1() {
2506 {
2507 var fiber = ReactDebugCurrentFiber.current;
2508 if (fiber === null) {
2509 return null;
2510 }
2511 // Safe because if current fiber exists, we are reconciling,
2512 // and it is guaranteed to be the work-in-progress version.
2513 return getStackAddendumByWorkInProgressFiber(fiber);
2514 }
2515 return null;
2516}
2517
2518function resetCurrentFiber() {
2519 ReactDebugCurrentFrame.getCurrentStack = null;
2520 ReactDebugCurrentFiber.current = null;
2521 ReactDebugCurrentFiber.phase = null;
2522}
2523
2524function setCurrentFiber(fiber) {
2525 ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum$1;
2526 ReactDebugCurrentFiber.current = fiber;
2527 ReactDebugCurrentFiber.phase = null;
2528}
2529
2530function setCurrentPhase(phase) {
2531 ReactDebugCurrentFiber.phase = phase;
2532}
2533
2534var ReactDebugCurrentFiber = {
2535 current: null,
2536 phase: null,
2537 resetCurrentFiber: resetCurrentFiber,
2538 setCurrentFiber: setCurrentFiber,
2539 setCurrentPhase: setCurrentPhase,
2540 getCurrentFiberOwnerName: getCurrentFiberOwnerName$1,
2541 getCurrentFiberStackAddendum: getCurrentFiberStackAddendum$1
2542};
2543
2544// A reserved attribute.
2545// It is handled by React separately and shouldn't be written to the DOM.
2546var RESERVED = 0;
2547
2548// A simple string attribute.
2549// Attributes that aren't in the whitelist are presumed to have this type.
2550var STRING = 1;
2551
2552// A string attribute that accepts booleans in React. In HTML, these are called
2553// "enumerated" attributes with "true" and "false" as possible values.
2554// When true, it should be set to a "true" string.
2555// When false, it should be set to a "false" string.
2556var BOOLEANISH_STRING = 2;
2557
2558// A real boolean attribute.
2559// When true, it should be present (set either to an empty string or its name).
2560// When false, it should be omitted.
2561var BOOLEAN = 3;
2562
2563// An attribute that can be used as a flag as well as with a value.
2564// When true, it should be present (set either to an empty string or its name).
2565// When false, it should be omitted.
2566// For any other value, should be present with that value.
2567var OVERLOADED_BOOLEAN = 4;
2568
2569// An attribute that must be numeric or parse as a numeric.
2570// When falsy, it should be removed.
2571var NUMERIC = 5;
2572
2573// An attribute that must be positive numeric or parse as a positive numeric.
2574// When falsy, it should be removed.
2575var POSITIVE_NUMERIC = 6;
2576
2577/* eslint-disable max-len */
2578var 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';
2579/* eslint-enable max-len */
2580var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
2581
2582
2583var ROOT_ATTRIBUTE_NAME = 'data-reactroot';
2584var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$');
2585
2586var illegalAttributeNameCache = {};
2587var validatedAttributeNameCache = {};
2588
2589function isAttributeNameSafe(attributeName) {
2590 if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
2591 return true;
2592 }
2593 if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
2594 return false;
2595 }
2596 if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
2597 validatedAttributeNameCache[attributeName] = true;
2598 return true;
2599 }
2600 illegalAttributeNameCache[attributeName] = true;
2601 {
2602 warning_1(false, 'Invalid attribute name: `%s`', attributeName);
2603 }
2604 return false;
2605}
2606
2607function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) {
2608 if (propertyInfo !== null) {
2609 return propertyInfo.type === RESERVED;
2610 }
2611 if (isCustomComponentTag) {
2612 return false;
2613 }
2614 if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) {
2615 return true;
2616 }
2617 return false;
2618}
2619
2620function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) {
2621 if (propertyInfo !== null && propertyInfo.type === RESERVED) {
2622 return false;
2623 }
2624 switch (typeof value) {
2625 case 'function':
2626 // $FlowIssue symbol is perfectly valid here
2627 case 'symbol':
2628 // eslint-disable-line
2629 return true;
2630 case 'boolean':
2631 {
2632 if (isCustomComponentTag) {
2633 return false;
2634 }
2635 if (propertyInfo !== null) {
2636 return !propertyInfo.acceptsBooleans;
2637 } else {
2638 var prefix = name.toLowerCase().slice(0, 5);
2639 return prefix !== 'data-' && prefix !== 'aria-';
2640 }
2641 }
2642 default:
2643 return false;
2644 }
2645}
2646
2647function shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag) {
2648 if (value === null || typeof value === 'undefined') {
2649 return true;
2650 }
2651 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag)) {
2652 return true;
2653 }
2654 if (propertyInfo !== null) {
2655 switch (propertyInfo.type) {
2656 case BOOLEAN:
2657 return !value;
2658 case OVERLOADED_BOOLEAN:
2659 return value === false;
2660 case NUMERIC:
2661 return isNaN(value);
2662 case POSITIVE_NUMERIC:
2663 return isNaN(value) || value < 1;
2664 }
2665 }
2666 return false;
2667}
2668
2669function getPropertyInfo(name) {
2670 return properties.hasOwnProperty(name) ? properties[name] : null;
2671}
2672
2673function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace) {
2674 this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN;
2675 this.attributeName = attributeName;
2676 this.attributeNamespace = attributeNamespace;
2677 this.mustUseProperty = mustUseProperty;
2678 this.propertyName = name;
2679 this.type = type;
2680}
2681
2682// When adding attributes to this list, be sure to also add them to
2683// the `possibleStandardNames` module to ensure casing and incorrect
2684// name warnings.
2685var properties = {};
2686
2687// These props are reserved by React. They shouldn't be written to the DOM.
2688['children', 'dangerouslySetInnerHTML',
2689// TODO: This prevents the assignment of defaultValue to regular
2690// elements (not just inputs). Now that ReactDOMInput assigns to the
2691// defaultValue property -- do we need this?
2692'defaultValue', 'defaultChecked', 'innerHTML', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'style'].forEach(function (name) {
2693 properties[name] = new PropertyInfoRecord(name, RESERVED, false, // mustUseProperty
2694 name, // attributeName
2695 null);
2696});
2697
2698// A few React string attributes have a different name.
2699// This is a mapping from React prop names to the attribute names.
2700new Map([['acceptCharset', 'accept-charset'], ['className', 'class'], ['htmlFor', 'for'], ['httpEquiv', 'http-equiv']]).forEach(function (attributeName, name) {
2701 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
2702 attributeName, // attributeName
2703 null);
2704});
2705
2706// These are "enumerated" HTML attributes that accept "true" and "false".
2707// In React, we let users pass `true` and `false` even though technically
2708// these aren't boolean attributes (they are coerced to strings).
2709['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (name) {
2710 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty
2711 name.toLowerCase(), // attributeName
2712 null);
2713});
2714
2715// These are "enumerated" SVG attributes that accept "true" and "false".
2716// In React, we let users pass `true` and `false` even though technically
2717// these aren't boolean attributes (they are coerced to strings).
2718// Since these are SVG attributes, their attribute names are case-sensitive.
2719['autoReverse', 'externalResourcesRequired', 'preserveAlpha'].forEach(function (name) {
2720 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty
2721 name, // attributeName
2722 null);
2723});
2724
2725// These are HTML boolean attributes.
2726['allowFullScreen', 'async',
2727// Note: there is a special case that prevents it from being written to the DOM
2728// on the client side because the browsers are inconsistent. Instead we call focus().
2729'autoFocus', 'autoPlay', 'controls', 'default', 'defer', 'disabled', 'formNoValidate', 'hidden', 'loop', 'noModule', 'noValidate', 'open', 'playsInline', 'readOnly', 'required', 'reversed', 'scoped', 'seamless',
2730// Microdata
2731'itemScope'].forEach(function (name) {
2732 properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, // mustUseProperty
2733 name.toLowerCase(), // attributeName
2734 null);
2735});
2736
2737// These are the few React props that we set as DOM properties
2738// rather than attributes. These are all booleans.
2739['checked',
2740// Note: `option.selected` is not updated if `select.multiple` is
2741// disabled with `removeAttribute`. We have special logic for handling this.
2742'multiple', 'muted', 'selected'].forEach(function (name) {
2743 properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, // mustUseProperty
2744 name.toLowerCase(), // attributeName
2745 null);
2746});
2747
2748// These are HTML attributes that are "overloaded booleans": they behave like
2749// booleans, but can also accept a string value.
2750['capture', 'download'].forEach(function (name) {
2751 properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, // mustUseProperty
2752 name.toLowerCase(), // attributeName
2753 null);
2754});
2755
2756// These are HTML attributes that must be positive numbers.
2757['cols', 'rows', 'size', 'span'].forEach(function (name) {
2758 properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, // mustUseProperty
2759 name.toLowerCase(), // attributeName
2760 null);
2761});
2762
2763// These are HTML attributes that must be numbers.
2764['rowSpan', 'start'].forEach(function (name) {
2765 properties[name] = new PropertyInfoRecord(name, NUMERIC, false, // mustUseProperty
2766 name.toLowerCase(), // attributeName
2767 null);
2768});
2769
2770var CAMELIZE = /[\-\:]([a-z])/g;
2771var capitalize = function (token) {
2772 return token[1].toUpperCase();
2773};
2774
2775// This is a list of all SVG attributes that need special casing, namespacing,
2776// or boolean value assignment. Regular attributes that just accept strings
2777// and have the same names are omitted, just like in the HTML whitelist.
2778// Some of these attributes can be hard to find. This list was created by
2779// scrapping the MDN documentation.
2780['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'xmlns:xlink', 'x-height'].forEach(function (attributeName) {
2781 var name = attributeName.replace(CAMELIZE, capitalize);
2782 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
2783 attributeName, null);
2784});
2785
2786// String SVG attributes with the xlink namespace.
2787['xlink:actuate', 'xlink:arcrole', 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type'].forEach(function (attributeName) {
2788 var name = attributeName.replace(CAMELIZE, capitalize);
2789 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
2790 attributeName, 'http://www.w3.org/1999/xlink');
2791});
2792
2793// String SVG attributes with the xml namespace.
2794['xml:base', 'xml:lang', 'xml:space'].forEach(function (attributeName) {
2795 var name = attributeName.replace(CAMELIZE, capitalize);
2796 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
2797 attributeName, 'http://www.w3.org/XML/1998/namespace');
2798});
2799
2800// Special case: this attribute exists both in HTML and SVG.
2801// Its "tabindex" attribute name is case-sensitive in SVG so we can't just use
2802// its React `tabIndex` name, like we do for attributes that exist only in HTML.
2803properties.tabIndex = new PropertyInfoRecord('tabIndex', STRING, false, // mustUseProperty
2804'tabindex', // attributeName
2805null);
2806
2807/**
2808 * Get the value for a property on a node. Only used in DEV for SSR validation.
2809 * The "expected" argument is used as a hint of what the expected value is.
2810 * Some properties have multiple equivalent values.
2811 */
2812function getValueForProperty(node, name, expected, propertyInfo) {
2813 {
2814 if (propertyInfo.mustUseProperty) {
2815 var propertyName = propertyInfo.propertyName;
2816
2817 return node[propertyName];
2818 } else {
2819 var attributeName = propertyInfo.attributeName;
2820
2821 var stringValue = null;
2822
2823 if (propertyInfo.type === OVERLOADED_BOOLEAN) {
2824 if (node.hasAttribute(attributeName)) {
2825 var value = node.getAttribute(attributeName);
2826 if (value === '') {
2827 return true;
2828 }
2829 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
2830 return value;
2831 }
2832 if (value === '' + expected) {
2833 return expected;
2834 }
2835 return value;
2836 }
2837 } else if (node.hasAttribute(attributeName)) {
2838 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
2839 // We had an attribute but shouldn't have had one, so read it
2840 // for the error message.
2841 return node.getAttribute(attributeName);
2842 }
2843 if (propertyInfo.type === BOOLEAN) {
2844 // If this was a boolean, it doesn't matter what the value is
2845 // the fact that we have it is the same as the expected.
2846 return expected;
2847 }
2848 // Even if this property uses a namespace we use getAttribute
2849 // because we assume its namespaced name is the same as our config.
2850 // To use getAttributeNS we need the local name which we don't have
2851 // in our config atm.
2852 stringValue = node.getAttribute(attributeName);
2853 }
2854
2855 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
2856 return stringValue === null ? expected : stringValue;
2857 } else if (stringValue === '' + expected) {
2858 return expected;
2859 } else {
2860 return stringValue;
2861 }
2862 }
2863 }
2864}
2865
2866/**
2867 * Get the value for a attribute on a node. Only used in DEV for SSR validation.
2868 * The third argument is used as a hint of what the expected value is. Some
2869 * attributes have multiple equivalent values.
2870 */
2871function getValueForAttribute(node, name, expected) {
2872 {
2873 if (!isAttributeNameSafe(name)) {
2874 return;
2875 }
2876 if (!node.hasAttribute(name)) {
2877 return expected === undefined ? undefined : null;
2878 }
2879 var value = node.getAttribute(name);
2880 if (value === '' + expected) {
2881 return expected;
2882 }
2883 return value;
2884 }
2885}
2886
2887/**
2888 * Sets the value for a property on a node.
2889 *
2890 * @param {DOMElement} node
2891 * @param {string} name
2892 * @param {*} value
2893 */
2894function setValueForProperty(node, name, value, isCustomComponentTag) {
2895 var propertyInfo = getPropertyInfo(name);
2896 if (shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag)) {
2897 return;
2898 }
2899 if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
2900 value = null;
2901 }
2902 // If the prop isn't in the special list, treat it as a simple attribute.
2903 if (isCustomComponentTag || propertyInfo === null) {
2904 if (isAttributeNameSafe(name)) {
2905 var _attributeName = name;
2906 if (value === null) {
2907 node.removeAttribute(_attributeName);
2908 } else {
2909 node.setAttribute(_attributeName, '' + value);
2910 }
2911 }
2912 return;
2913 }
2914 var mustUseProperty = propertyInfo.mustUseProperty;
2915
2916 if (mustUseProperty) {
2917 var propertyName = propertyInfo.propertyName;
2918
2919 if (value === null) {
2920 var type = propertyInfo.type;
2921
2922 node[propertyName] = type === BOOLEAN ? false : '';
2923 } else {
2924 // Contrary to `setAttribute`, object properties are properly
2925 // `toString`ed by IE8/9.
2926 node[propertyName] = value;
2927 }
2928 return;
2929 }
2930 // The rest are treated as attributes with special cases.
2931 var attributeName = propertyInfo.attributeName,
2932 attributeNamespace = propertyInfo.attributeNamespace;
2933
2934 if (value === null) {
2935 node.removeAttribute(attributeName);
2936 } else {
2937 var _type = propertyInfo.type;
2938
2939 var attributeValue = void 0;
2940 if (_type === BOOLEAN || _type === OVERLOADED_BOOLEAN && value === true) {
2941 attributeValue = '';
2942 } else {
2943 // `setAttribute` with objects becomes only `[object]` in IE8/9,
2944 // ('' + value) makes it output the correct toString()-value.
2945 attributeValue = '' + value;
2946 }
2947 if (attributeNamespace) {
2948 node.setAttributeNS(attributeNamespace, attributeName, attributeValue);
2949 } else {
2950 node.setAttribute(attributeName, attributeValue);
2951 }
2952 }
2953}
2954
2955/**
2956 * Copyright (c) 2013-present, Facebook, Inc.
2957 *
2958 * This source code is licensed under the MIT license found in the
2959 * LICENSE file in the root directory of this source tree.
2960 */
2961
2962
2963
2964var ReactPropTypesSecret$1 = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
2965
2966var ReactPropTypesSecret_1 = ReactPropTypesSecret$1;
2967
2968/**
2969 * Copyright (c) 2013-present, Facebook, Inc.
2970 *
2971 * This source code is licensed under the MIT license found in the
2972 * LICENSE file in the root directory of this source tree.
2973 */
2974
2975
2976
2977{
2978 var invariant$2 = invariant_1;
2979 var warning$2 = warning_1;
2980 var ReactPropTypesSecret = ReactPropTypesSecret_1;
2981 var loggedTypeFailures = {};
2982}
2983
2984/**
2985 * Assert that the values match with the type specs.
2986 * Error messages are memorized and will only be shown once.
2987 *
2988 * @param {object} typeSpecs Map of name to a ReactPropType
2989 * @param {object} values Runtime values that need to be type-checked
2990 * @param {string} location e.g. "prop", "context", "child context"
2991 * @param {string} componentName Name of the component for error messages.
2992 * @param {?Function} getStack Returns the component stack.
2993 * @private
2994 */
2995function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
2996 {
2997 for (var typeSpecName in typeSpecs) {
2998 if (typeSpecs.hasOwnProperty(typeSpecName)) {
2999 var error;
3000 // Prop type validation may throw. In case they do, we don't want to
3001 // fail the render phase where it didn't fail before. So we log it.
3002 // After these have been cleaned up, we'll let them throw.
3003 try {
3004 // This is intentionally an invariant that gets caught. It's the same
3005 // behavior as without this statement except with a better message.
3006 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]);
3007 error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
3008 } catch (ex) {
3009 error = ex;
3010 }
3011 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);
3012 if (error instanceof Error && !(error.message in loggedTypeFailures)) {
3013 // Only monitor this failure once because there tends to be a lot of the
3014 // same error.
3015 loggedTypeFailures[error.message] = true;
3016
3017 var stack = getStack ? getStack() : '';
3018
3019 warning$2(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : '');
3020 }
3021 }
3022 }
3023 }
3024}
3025
3026var checkPropTypes_1 = checkPropTypes;
3027
3028var ReactControlledValuePropTypes = {
3029 checkPropTypes: null
3030};
3031
3032{
3033 var hasReadOnlyValue = {
3034 button: true,
3035 checkbox: true,
3036 image: true,
3037 hidden: true,
3038 radio: true,
3039 reset: true,
3040 submit: true
3041 };
3042
3043 var propTypes = {
3044 value: function (props, propName, componentName) {
3045 if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {
3046 return null;
3047 }
3048 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`.');
3049 },
3050 checked: function (props, propName, componentName) {
3051 if (!props[propName] || props.onChange || props.readOnly || props.disabled) {
3052 return null;
3053 }
3054 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`.');
3055 }
3056 };
3057
3058 /**
3059 * Provide a linked `value` attribute for controlled forms. You should not use
3060 * this outside of the ReactDOM controlled form components.
3061 */
3062 ReactControlledValuePropTypes.checkPropTypes = function (tagName, props, getStack) {
3063 checkPropTypes_1(propTypes, props, 'prop', tagName, getStack);
3064 };
3065}
3066
3067// TODO: direct imports like some-package/src/* are bad. Fix me.
3068var getCurrentFiberOwnerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
3069var getCurrentFiberStackAddendum = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
3070
3071var didWarnValueDefaultValue = false;
3072var didWarnCheckedDefaultChecked = false;
3073var didWarnControlledToUncontrolled = false;
3074var didWarnUncontrolledToControlled = false;
3075
3076function isControlled(props) {
3077 var usesChecked = props.type === 'checkbox' || props.type === 'radio';
3078 return usesChecked ? props.checked != null : props.value != null;
3079}
3080
3081/**
3082 * Implements an <input> host component that allows setting these optional
3083 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
3084 *
3085 * If `checked` or `value` are not supplied (or null/undefined), user actions
3086 * that affect the checked state or value will trigger updates to the element.
3087 *
3088 * If they are supplied (and not null/undefined), the rendered element will not
3089 * trigger updates to the element. Instead, the props must change in order for
3090 * the rendered element to be updated.
3091 *
3092 * The rendered element will be initialized as unchecked (or `defaultChecked`)
3093 * with an empty value (or `defaultValue`).
3094 *
3095 * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
3096 */
3097
3098function getHostProps(element, props) {
3099 var node = element;
3100 var checked = props.checked;
3101
3102 var hostProps = _assign({}, props, {
3103 defaultChecked: undefined,
3104 defaultValue: undefined,
3105 value: undefined,
3106 checked: checked != null ? checked : node._wrapperState.initialChecked
3107 });
3108
3109 return hostProps;
3110}
3111
3112function initWrapperState(element, props) {
3113 {
3114 ReactControlledValuePropTypes.checkPropTypes('input', props, getCurrentFiberStackAddendum);
3115
3116 if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
3117 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() || 'A component', props.type);
3118 didWarnCheckedDefaultChecked = true;
3119 }
3120 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
3121 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() || 'A component', props.type);
3122 didWarnValueDefaultValue = true;
3123 }
3124 }
3125
3126 var node = element;
3127 var defaultValue = props.defaultValue == null ? '' : props.defaultValue;
3128
3129 node._wrapperState = {
3130 initialChecked: props.checked != null ? props.checked : props.defaultChecked,
3131 initialValue: getSafeValue(props.value != null ? props.value : defaultValue),
3132 controlled: isControlled(props)
3133 };
3134}
3135
3136function updateChecked(element, props) {
3137 var node = element;
3138 var checked = props.checked;
3139 if (checked != null) {
3140 setValueForProperty(node, 'checked', checked, false);
3141 }
3142}
3143
3144function updateWrapper(element, props) {
3145 var node = element;
3146 {
3147 var _controlled = isControlled(props);
3148
3149 if (!node._wrapperState.controlled && _controlled && !didWarnUncontrolledToControlled) {
3150 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());
3151 didWarnUncontrolledToControlled = true;
3152 }
3153 if (node._wrapperState.controlled && !_controlled && !didWarnControlledToUncontrolled) {
3154 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());
3155 didWarnControlledToUncontrolled = true;
3156 }
3157 }
3158
3159 updateChecked(element, props);
3160
3161 var value = getSafeValue(props.value);
3162
3163 if (value != null) {
3164 if (props.type === 'number') {
3165 if (value === 0 && node.value === '' ||
3166 // eslint-disable-next-line
3167 node.value != value) {
3168 node.value = '' + value;
3169 }
3170 } else if (node.value !== '' + value) {
3171 node.value = '' + value;
3172 }
3173 }
3174
3175 if (props.hasOwnProperty('value')) {
3176 setDefaultValue(node, props.type, value);
3177 } else if (props.hasOwnProperty('defaultValue')) {
3178 setDefaultValue(node, props.type, getSafeValue(props.defaultValue));
3179 }
3180
3181 if (props.checked == null && props.defaultChecked != null) {
3182 node.defaultChecked = !!props.defaultChecked;
3183 }
3184}
3185
3186function postMountWrapper(element, props) {
3187 var node = element;
3188
3189 if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) {
3190 // Do not assign value if it is already set. This prevents user text input
3191 // from being lost during SSR hydration.
3192 if (node.value === '') {
3193 node.value = '' + node._wrapperState.initialValue;
3194 }
3195
3196 // value must be assigned before defaultValue. This fixes an issue where the
3197 // visually displayed value of date inputs disappears on mobile Safari and Chrome:
3198 // https://github.com/facebook/react/issues/7233
3199 node.defaultValue = '' + node._wrapperState.initialValue;
3200 }
3201
3202 // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
3203 // this is needed to work around a chrome bug where setting defaultChecked
3204 // will sometimes influence the value of checked (even after detachment).
3205 // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
3206 // We need to temporarily unset name to avoid disrupting radio button groups.
3207 var name = node.name;
3208 if (name !== '') {
3209 node.name = '';
3210 }
3211 node.defaultChecked = !node.defaultChecked;
3212 node.defaultChecked = !node.defaultChecked;
3213 if (name !== '') {
3214 node.name = name;
3215 }
3216}
3217
3218function restoreControlledState(element, props) {
3219 var node = element;
3220 updateWrapper(node, props);
3221 updateNamedCousins(node, props);
3222}
3223
3224function updateNamedCousins(rootNode, props) {
3225 var name = props.name;
3226 if (props.type === 'radio' && name != null) {
3227 var queryRoot = rootNode;
3228
3229 while (queryRoot.parentNode) {
3230 queryRoot = queryRoot.parentNode;
3231 }
3232
3233 // If `rootNode.form` was non-null, then we could try `form.elements`,
3234 // but that sometimes behaves strangely in IE8. We could also try using
3235 // `form.getElementsByName`, but that will only return direct children
3236 // and won't include inputs that use the HTML5 `form=` attribute. Since
3237 // the input might not even be in a form. It might not even be in the
3238 // document. Let's just use the local `querySelectorAll` to ensure we don't
3239 // miss anything.
3240 var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
3241
3242 for (var i = 0; i < group.length; i++) {
3243 var otherNode = group[i];
3244 if (otherNode === rootNode || otherNode.form !== rootNode.form) {
3245 continue;
3246 }
3247 // This will throw if radio buttons rendered by different copies of React
3248 // and the same name are rendered into the same form (same as #1939).
3249 // That's probably okay; we don't support it just as we don't support
3250 // mixing React radio buttons with non-React ones.
3251 var otherProps = getFiberCurrentPropsFromNode$1(otherNode);
3252 !otherProps ? invariant_1(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : void 0;
3253
3254 // We need update the tracked value on the named cousin since the value
3255 // was changed but the input saw no event or value set
3256 updateValueIfChanged(otherNode);
3257
3258 // If this is a controlled radio button group, forcing the input that
3259 // was previously checked to update will cause it to be come re-checked
3260 // as appropriate.
3261 updateWrapper(otherNode, otherProps);
3262 }
3263 }
3264}
3265
3266// In Chrome, assigning defaultValue to certain input types triggers input validation.
3267// For number inputs, the display value loses trailing decimal points. For email inputs,
3268// Chrome raises "The specified value <x> is not a valid email address".
3269//
3270// Here we check to see if the defaultValue has actually changed, avoiding these problems
3271// when the user is inputting text
3272//
3273// https://github.com/facebook/react/issues/7253
3274function setDefaultValue(node, type, value) {
3275 if (
3276 // Focused number inputs synchronize on blur. See ChangeEventPlugin.js
3277 type !== 'number' || node.ownerDocument.activeElement !== node) {
3278 if (value == null) {
3279 node.defaultValue = '' + node._wrapperState.initialValue;
3280 } else if (node.defaultValue !== '' + value) {
3281 node.defaultValue = '' + value;
3282 }
3283 }
3284}
3285
3286function getSafeValue(value) {
3287 switch (typeof value) {
3288 case 'boolean':
3289 case 'number':
3290 case 'object':
3291 case 'string':
3292 case 'undefined':
3293 return value;
3294 default:
3295 // function, symbol are assigned as empty strings
3296 return '';
3297 }
3298}
3299
3300var eventTypes$1 = {
3301 change: {
3302 phasedRegistrationNames: {
3303 bubbled: 'onChange',
3304 captured: 'onChangeCapture'
3305 },
3306 dependencies: ['topBlur', 'topChange', 'topClick', 'topFocus', 'topInput', 'topKeyDown', 'topKeyUp', 'topSelectionChange']
3307 }
3308};
3309
3310function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
3311 var event = SyntheticEvent$1.getPooled(eventTypes$1.change, inst, nativeEvent, target);
3312 event.type = 'change';
3313 // Flag this event loop as needing state restore.
3314 enqueueStateRestore(target);
3315 accumulateTwoPhaseDispatches(event);
3316 return event;
3317}
3318/**
3319 * For IE shims
3320 */
3321var activeElement = null;
3322var activeElementInst = null;
3323
3324/**
3325 * SECTION: handle `change` event
3326 */
3327function shouldUseChangeEvent(elem) {
3328 var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
3329 return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
3330}
3331
3332function manualDispatchChangeEvent(nativeEvent) {
3333 var event = createAndAccumulateChangeEvent(activeElementInst, nativeEvent, getEventTarget(nativeEvent));
3334
3335 // If change and propertychange bubbled, we'd just bind to it like all the
3336 // other events and have it go through ReactBrowserEventEmitter. Since it
3337 // doesn't, we manually listen for the events and so we have to enqueue and
3338 // process the abstract event manually.
3339 //
3340 // Batching is necessary here in order to ensure that all event handlers run
3341 // before the next rerender (including event handlers attached to ancestor
3342 // elements instead of directly on the input). Without this, controlled
3343 // components don't work properly in conjunction with event bubbling because
3344 // the component is rerendered and the value reverted before all the event
3345 // handlers can run. See https://github.com/facebook/react/issues/708.
3346 batchedUpdates(runEventInBatch, event);
3347}
3348
3349function runEventInBatch(event) {
3350 enqueueEvents(event);
3351 processEventQueue(false);
3352}
3353
3354function getInstIfValueChanged(targetInst) {
3355 var targetNode = getNodeFromInstance$1(targetInst);
3356 if (updateValueIfChanged(targetNode)) {
3357 return targetInst;
3358 }
3359}
3360
3361function getTargetInstForChangeEvent(topLevelType, targetInst) {
3362 if (topLevelType === 'topChange') {
3363 return targetInst;
3364 }
3365}
3366
3367/**
3368 * SECTION: handle `input` event
3369 */
3370var isInputEventSupported = false;
3371if (ExecutionEnvironment_1.canUseDOM) {
3372 // IE9 claims to support the input event but fails to trigger it when
3373 // deleting text, so we ignore its input events.
3374 isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9);
3375}
3376
3377/**
3378 * (For IE <=9) Starts tracking propertychange events on the passed-in element
3379 * and override the value property so that we can distinguish user events from
3380 * value changes in JS.
3381 */
3382function startWatchingForValueChange(target, targetInst) {
3383 activeElement = target;
3384 activeElementInst = targetInst;
3385 activeElement.attachEvent('onpropertychange', handlePropertyChange);
3386}
3387
3388/**
3389 * (For IE <=9) Removes the event listeners from the currently-tracked element,
3390 * if any exists.
3391 */
3392function stopWatchingForValueChange() {
3393 if (!activeElement) {
3394 return;
3395 }
3396 activeElement.detachEvent('onpropertychange', handlePropertyChange);
3397 activeElement = null;
3398 activeElementInst = null;
3399}
3400
3401/**
3402 * (For IE <=9) Handles a propertychange event, sending a `change` event if
3403 * the value of the active element has changed.
3404 */
3405function handlePropertyChange(nativeEvent) {
3406 if (nativeEvent.propertyName !== 'value') {
3407 return;
3408 }
3409 if (getInstIfValueChanged(activeElementInst)) {
3410 manualDispatchChangeEvent(nativeEvent);
3411 }
3412}
3413
3414function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) {
3415 if (topLevelType === 'topFocus') {
3416 // In IE9, propertychange fires for most input events but is buggy and
3417 // doesn't fire when text is deleted, but conveniently, selectionchange
3418 // appears to fire in all of the remaining cases so we catch those and
3419 // forward the event if the value has changed
3420 // In either case, we don't want to call the event handler if the value
3421 // is changed from JS so we redefine a setter for `.value` that updates
3422 // our activeElementValue variable, allowing us to ignore those changes
3423 //
3424 // stopWatching() should be a noop here but we call it just in case we
3425 // missed a blur event somehow.
3426 stopWatchingForValueChange();
3427 startWatchingForValueChange(target, targetInst);
3428 } else if (topLevelType === 'topBlur') {
3429 stopWatchingForValueChange();
3430 }
3431}
3432
3433// For IE8 and IE9.
3434function getTargetInstForInputEventPolyfill(topLevelType, targetInst) {
3435 if (topLevelType === 'topSelectionChange' || topLevelType === 'topKeyUp' || topLevelType === 'topKeyDown') {
3436 // On the selectionchange event, the target is just document which isn't
3437 // helpful for us so just check activeElement instead.
3438 //
3439 // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
3440 // propertychange on the first input event after setting `value` from a
3441 // script and fires only keydown, keypress, keyup. Catching keyup usually
3442 // gets it and catching keydown lets us fire an event for the first
3443 // keystroke if user does a key repeat (it'll be a little delayed: right
3444 // before the second keystroke). Other input methods (e.g., paste) seem to
3445 // fire selectionchange normally.
3446 return getInstIfValueChanged(activeElementInst);
3447 }
3448}
3449
3450/**
3451 * SECTION: handle `click` event
3452 */
3453function shouldUseClickEvent(elem) {
3454 // Use the `click` event to detect changes to checkbox and radio inputs.
3455 // This approach works across all browsers, whereas `change` does not fire
3456 // until `blur` in IE8.
3457 var nodeName = elem.nodeName;
3458 return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
3459}
3460
3461function getTargetInstForClickEvent(topLevelType, targetInst) {
3462 if (topLevelType === 'topClick') {
3463 return getInstIfValueChanged(targetInst);
3464 }
3465}
3466
3467function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) {
3468 if (topLevelType === 'topInput' || topLevelType === 'topChange') {
3469 return getInstIfValueChanged(targetInst);
3470 }
3471}
3472
3473function handleControlledInputBlur(inst, node) {
3474 // TODO: In IE, inst is occasionally null. Why?
3475 if (inst == null) {
3476 return;
3477 }
3478
3479 // Fiber and ReactDOM keep wrapper state in separate places
3480 var state = inst._wrapperState || node._wrapperState;
3481
3482 if (!state || !state.controlled || node.type !== 'number') {
3483 return;
3484 }
3485
3486 // If controlled, assign the value attribute to the current value on blur
3487 setDefaultValue(node, 'number', node.value);
3488}
3489
3490/**
3491 * This plugin creates an `onChange` event that normalizes change events
3492 * across form elements. This event fires at a time when it's possible to
3493 * change the element's value without seeing a flicker.
3494 *
3495 * Supported elements are:
3496 * - input (see `isTextInputElement`)
3497 * - textarea
3498 * - select
3499 */
3500var ChangeEventPlugin = {
3501 eventTypes: eventTypes$1,
3502
3503 _isInputEventSupported: isInputEventSupported,
3504
3505 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
3506 var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
3507
3508 var getTargetInstFunc = void 0,
3509 handleEventFunc = void 0;
3510 if (shouldUseChangeEvent(targetNode)) {
3511 getTargetInstFunc = getTargetInstForChangeEvent;
3512 } else if (isTextInputElement(targetNode)) {
3513 if (isInputEventSupported) {
3514 getTargetInstFunc = getTargetInstForInputOrChangeEvent;
3515 } else {
3516 getTargetInstFunc = getTargetInstForInputEventPolyfill;
3517 handleEventFunc = handleEventsForInputEventPolyfill;
3518 }
3519 } else if (shouldUseClickEvent(targetNode)) {
3520 getTargetInstFunc = getTargetInstForClickEvent;
3521 }
3522
3523 if (getTargetInstFunc) {
3524 var inst = getTargetInstFunc(topLevelType, targetInst);
3525 if (inst) {
3526 var event = createAndAccumulateChangeEvent(inst, nativeEvent, nativeEventTarget);
3527 return event;
3528 }
3529 }
3530
3531 if (handleEventFunc) {
3532 handleEventFunc(topLevelType, targetNode, targetInst);
3533 }
3534
3535 // When blurring, set the value attribute for number inputs
3536 if (topLevelType === 'topBlur') {
3537 handleControlledInputBlur(targetInst, targetNode);
3538 }
3539 }
3540};
3541
3542/**
3543 * Module that is injectable into `EventPluginHub`, that specifies a
3544 * deterministic ordering of `EventPlugin`s. A convenient way to reason about
3545 * plugins, without having to package every one of them. This is better than
3546 * having plugins be ordered in the same order that they are injected because
3547 * that ordering would be influenced by the packaging order.
3548 * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
3549 * preventing default on events is convenient in `SimpleEventPlugin` handlers.
3550 */
3551var DOMEventPluginOrder = ['ResponderEventPlugin', 'SimpleEventPlugin', 'TapEventPlugin', 'EnterLeaveEventPlugin', 'ChangeEventPlugin', 'SelectEventPlugin', 'BeforeInputEventPlugin'];
3552
3553var SyntheticUIEvent = SyntheticEvent$1.extend({
3554 view: null,
3555 detail: null
3556});
3557
3558/**
3559 * Translation from modifier key to the associated property in the event.
3560 * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
3561 */
3562
3563var modifierKeyToProp = {
3564 Alt: 'altKey',
3565 Control: 'ctrlKey',
3566 Meta: 'metaKey',
3567 Shift: 'shiftKey'
3568};
3569
3570// IE8 does not implement getModifierState so we simply map it to the only
3571// modifier keys exposed by the event itself, does not support Lock-keys.
3572// Currently, all major browsers except Chrome seems to support Lock-keys.
3573function modifierStateGetter(keyArg) {
3574 var syntheticEvent = this;
3575 var nativeEvent = syntheticEvent.nativeEvent;
3576 if (nativeEvent.getModifierState) {
3577 return nativeEvent.getModifierState(keyArg);
3578 }
3579 var keyProp = modifierKeyToProp[keyArg];
3580 return keyProp ? !!nativeEvent[keyProp] : false;
3581}
3582
3583function getEventModifierState(nativeEvent) {
3584 return modifierStateGetter;
3585}
3586
3587/**
3588 * @interface MouseEvent
3589 * @see http://www.w3.org/TR/DOM-Level-3-Events/
3590 */
3591var SyntheticMouseEvent = SyntheticUIEvent.extend({
3592 screenX: null,
3593 screenY: null,
3594 clientX: null,
3595 clientY: null,
3596 pageX: null,
3597 pageY: null,
3598 ctrlKey: null,
3599 shiftKey: null,
3600 altKey: null,
3601 metaKey: null,
3602 getModifierState: getEventModifierState,
3603 button: null,
3604 buttons: null,
3605 relatedTarget: function (event) {
3606 return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);
3607 }
3608});
3609
3610var eventTypes$2 = {
3611 mouseEnter: {
3612 registrationName: 'onMouseEnter',
3613 dependencies: ['topMouseOut', 'topMouseOver']
3614 },
3615 mouseLeave: {
3616 registrationName: 'onMouseLeave',
3617 dependencies: ['topMouseOut', 'topMouseOver']
3618 }
3619};
3620
3621var EnterLeaveEventPlugin = {
3622 eventTypes: eventTypes$2,
3623
3624 /**
3625 * For almost every interaction we care about, there will be both a top-level
3626 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
3627 * we do not extract duplicate events. However, moving the mouse into the
3628 * browser from outside will not fire a `mouseout` event. In this case, we use
3629 * the `mouseover` top-level event.
3630 */
3631 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
3632 if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
3633 return null;
3634 }
3635 if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') {
3636 // Must not be a mouse in or mouse out - ignoring.
3637 return null;
3638 }
3639
3640 var win = void 0;
3641 if (nativeEventTarget.window === nativeEventTarget) {
3642 // `nativeEventTarget` is probably a window object.
3643 win = nativeEventTarget;
3644 } else {
3645 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
3646 var doc = nativeEventTarget.ownerDocument;
3647 if (doc) {
3648 win = doc.defaultView || doc.parentWindow;
3649 } else {
3650 win = window;
3651 }
3652 }
3653
3654 var from = void 0;
3655 var to = void 0;
3656 if (topLevelType === 'topMouseOut') {
3657 from = targetInst;
3658 var related = nativeEvent.relatedTarget || nativeEvent.toElement;
3659 to = related ? getClosestInstanceFromNode(related) : null;
3660 } else {
3661 // Moving to a node from outside the window.
3662 from = null;
3663 to = targetInst;
3664 }
3665
3666 if (from === to) {
3667 // Nothing pertains to our managed components.
3668 return null;
3669 }
3670
3671 var fromNode = from == null ? win : getNodeFromInstance$1(from);
3672 var toNode = to == null ? win : getNodeFromInstance$1(to);
3673
3674 var leave = SyntheticMouseEvent.getPooled(eventTypes$2.mouseLeave, from, nativeEvent, nativeEventTarget);
3675 leave.type = 'mouseleave';
3676 leave.target = fromNode;
3677 leave.relatedTarget = toNode;
3678
3679 var enter = SyntheticMouseEvent.getPooled(eventTypes$2.mouseEnter, to, nativeEvent, nativeEventTarget);
3680 enter.type = 'mouseenter';
3681 enter.target = toNode;
3682 enter.relatedTarget = fromNode;
3683
3684 accumulateEnterLeaveDispatches(leave, enter, from, to);
3685
3686 return [leave, enter];
3687 }
3688};
3689
3690/**
3691 * `ReactInstanceMap` maintains a mapping from a public facing stateful
3692 * instance (key) and the internal representation (value). This allows public
3693 * methods to accept the user facing instance as an argument and map them back
3694 * to internal methods.
3695 *
3696 * Note that this module is currently shared and assumed to be stateless.
3697 * If this becomes an actual Map, that will break.
3698 */
3699
3700/**
3701 * This API should be called `delete` but we'd have to make sure to always
3702 * transform these to strings for IE support. When this transform is fully
3703 * supported we can rename it.
3704 */
3705
3706
3707function get(key) {
3708 return key._reactInternalFiber;
3709}
3710
3711function has(key) {
3712 return key._reactInternalFiber !== undefined;
3713}
3714
3715function set(key, value) {
3716 key._reactInternalFiber = value;
3717}
3718
3719// Don't change these two values:
3720var NoEffect = 0;
3721var PerformedWork = 1;
3722
3723// You can change the rest (and add more).
3724var Placement = 2;
3725var Update = 4;
3726var PlacementAndUpdate = 6;
3727var Deletion = 8;
3728var ContentReset = 16;
3729var Callback = 32;
3730var Err = 64;
3731var Ref = 128;
3732
3733var MOUNTING = 1;
3734var MOUNTED = 2;
3735var UNMOUNTED = 3;
3736
3737function isFiberMountedImpl(fiber) {
3738 var node = fiber;
3739 if (!fiber.alternate) {
3740 // If there is no alternate, this might be a new tree that isn't inserted
3741 // yet. If it is, then it will have a pending insertion effect on it.
3742 if ((node.effectTag & Placement) !== NoEffect) {
3743 return MOUNTING;
3744 }
3745 while (node['return']) {
3746 node = node['return'];
3747 if ((node.effectTag & Placement) !== NoEffect) {
3748 return MOUNTING;
3749 }
3750 }
3751 } else {
3752 while (node['return']) {
3753 node = node['return'];
3754 }
3755 }
3756 if (node.tag === HostRoot) {
3757 // TODO: Check if this was a nested HostRoot when used with
3758 // renderContainerIntoSubtree.
3759 return MOUNTED;
3760 }
3761 // If we didn't hit the root, that means that we're in an disconnected tree
3762 // that has been unmounted.
3763 return UNMOUNTED;
3764}
3765
3766function isFiberMounted(fiber) {
3767 return isFiberMountedImpl(fiber) === MOUNTED;
3768}
3769
3770function isMounted(component) {
3771 {
3772 var owner = ReactCurrentOwner.current;
3773 if (owner !== null && owner.tag === ClassComponent) {
3774 var ownerFiber = owner;
3775 var instance = ownerFiber.stateNode;
3776 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');
3777 instance._warnedAboutRefsInRender = true;
3778 }
3779 }
3780
3781 var fiber = get(component);
3782 if (!fiber) {
3783 return false;
3784 }
3785 return isFiberMountedImpl(fiber) === MOUNTED;
3786}
3787
3788function assertIsMounted(fiber) {
3789 !(isFiberMountedImpl(fiber) === MOUNTED) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
3790}
3791
3792function findCurrentFiberUsingSlowPath(fiber) {
3793 var alternate = fiber.alternate;
3794 if (!alternate) {
3795 // If there is no alternate, then we only need to check if it is mounted.
3796 var state = isFiberMountedImpl(fiber);
3797 !(state !== UNMOUNTED) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
3798 if (state === MOUNTING) {
3799 return null;
3800 }
3801 return fiber;
3802 }
3803 // If we have two possible branches, we'll walk backwards up to the root
3804 // to see what path the root points to. On the way we may hit one of the
3805 // special cases and we'll deal with them.
3806 var a = fiber;
3807 var b = alternate;
3808 while (true) {
3809 var parentA = a['return'];
3810 var parentB = parentA ? parentA.alternate : null;
3811 if (!parentA || !parentB) {
3812 // We're at the root.
3813 break;
3814 }
3815
3816 // If both copies of the parent fiber point to the same child, we can
3817 // assume that the child is current. This happens when we bailout on low
3818 // priority: the bailed out fiber's child reuses the current child.
3819 if (parentA.child === parentB.child) {
3820 var child = parentA.child;
3821 while (child) {
3822 if (child === a) {
3823 // We've determined that A is the current branch.
3824 assertIsMounted(parentA);
3825 return fiber;
3826 }
3827 if (child === b) {
3828 // We've determined that B is the current branch.
3829 assertIsMounted(parentA);
3830 return alternate;
3831 }
3832 child = child.sibling;
3833 }
3834 // We should never have an alternate for any mounting node. So the only
3835 // way this could possibly happen is if this was unmounted, if at all.
3836 invariant_1(false, 'Unable to find node on an unmounted component.');
3837 }
3838
3839 if (a['return'] !== b['return']) {
3840 // The return pointer of A and the return pointer of B point to different
3841 // fibers. We assume that return pointers never criss-cross, so A must
3842 // belong to the child set of A.return, and B must belong to the child
3843 // set of B.return.
3844 a = parentA;
3845 b = parentB;
3846 } else {
3847 // The return pointers point to the same fiber. We'll have to use the
3848 // default, slow path: scan the child sets of each parent alternate to see
3849 // which child belongs to which set.
3850 //
3851 // Search parent A's child set
3852 var didFindChild = false;
3853 var _child = parentA.child;
3854 while (_child) {
3855 if (_child === a) {
3856 didFindChild = true;
3857 a = parentA;
3858 b = parentB;
3859 break;
3860 }
3861 if (_child === b) {
3862 didFindChild = true;
3863 b = parentA;
3864 a = parentB;
3865 break;
3866 }
3867 _child = _child.sibling;
3868 }
3869 if (!didFindChild) {
3870 // Search parent B's child set
3871 _child = parentB.child;
3872 while (_child) {
3873 if (_child === a) {
3874 didFindChild = true;
3875 a = parentB;
3876 b = parentA;
3877 break;
3878 }
3879 if (_child === b) {
3880 didFindChild = true;
3881 b = parentB;
3882 a = parentA;
3883 break;
3884 }
3885 _child = _child.sibling;
3886 }
3887 !didFindChild ? invariant_1(false, 'Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue.') : void 0;
3888 }
3889 }
3890
3891 !(a.alternate === b) ? invariant_1(false, 'Return fibers should always be each others\' alternates. This error is likely caused by a bug in React. Please file an issue.') : void 0;
3892 }
3893 // If the root is not a host container, we're in a disconnected tree. I.e.
3894 // unmounted.
3895 !(a.tag === HostRoot) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
3896 if (a.stateNode.current === a) {
3897 // We've determined that A is the current branch.
3898 return fiber;
3899 }
3900 // Otherwise B has to be current branch.
3901 return alternate;
3902}
3903
3904function findCurrentHostFiber(parent) {
3905 var currentParent = findCurrentFiberUsingSlowPath(parent);
3906 if (!currentParent) {
3907 return null;
3908 }
3909
3910 // Next we'll drill down this component to find the first HostComponent/Text.
3911 var node = currentParent;
3912 while (true) {
3913 if (node.tag === HostComponent || node.tag === HostText) {
3914 return node;
3915 } else if (node.child) {
3916 node.child['return'] = node;
3917 node = node.child;
3918 continue;
3919 }
3920 if (node === currentParent) {
3921 return null;
3922 }
3923 while (!node.sibling) {
3924 if (!node['return'] || node['return'] === currentParent) {
3925 return null;
3926 }
3927 node = node['return'];
3928 }
3929 node.sibling['return'] = node['return'];
3930 node = node.sibling;
3931 }
3932 // Flow needs the return null here, but ESLint complains about it.
3933 // eslint-disable-next-line no-unreachable
3934 return null;
3935}
3936
3937function findCurrentHostFiberWithNoPortals(parent) {
3938 var currentParent = findCurrentFiberUsingSlowPath(parent);
3939 if (!currentParent) {
3940 return null;
3941 }
3942
3943 // Next we'll drill down this component to find the first HostComponent/Text.
3944 var node = currentParent;
3945 while (true) {
3946 if (node.tag === HostComponent || node.tag === HostText) {
3947 return node;
3948 } else if (node.child && node.tag !== HostPortal) {
3949 node.child['return'] = node;
3950 node = node.child;
3951 continue;
3952 }
3953 if (node === currentParent) {
3954 return null;
3955 }
3956 while (!node.sibling) {
3957 if (!node['return'] || node['return'] === currentParent) {
3958 return null;
3959 }
3960 node = node['return'];
3961 }
3962 node.sibling['return'] = node['return'];
3963 node = node.sibling;
3964 }
3965 // Flow needs the return null here, but ESLint complains about it.
3966 // eslint-disable-next-line no-unreachable
3967 return null;
3968}
3969
3970function addEventBubbleListener(element, eventType, listener) {
3971 element.addEventListener(eventType, listener, false);
3972}
3973
3974function addEventCaptureListener(element, eventType, listener) {
3975 element.addEventListener(eventType, listener, true);
3976}
3977
3978var CALLBACK_BOOKKEEPING_POOL_SIZE = 10;
3979var callbackBookkeepingPool = [];
3980
3981/**
3982 * Find the deepest React component completely containing the root of the
3983 * passed-in instance (for use when entire React trees are nested within each
3984 * other). If React trees are not nested, returns null.
3985 */
3986function findRootContainerNode(inst) {
3987 // TODO: It may be a good idea to cache this to prevent unnecessary DOM
3988 // traversal, but caching is difficult to do correctly without using a
3989 // mutation observer to listen for all DOM changes.
3990 while (inst['return']) {
3991 inst = inst['return'];
3992 }
3993 if (inst.tag !== HostRoot) {
3994 // This can happen if we're in a detached tree.
3995 return null;
3996 }
3997 return inst.stateNode.containerInfo;
3998}
3999
4000// Used to store ancestor hierarchy in top level callback
4001function getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst) {
4002 if (callbackBookkeepingPool.length) {
4003 var instance = callbackBookkeepingPool.pop();
4004 instance.topLevelType = topLevelType;
4005 instance.nativeEvent = nativeEvent;
4006 instance.targetInst = targetInst;
4007 return instance;
4008 }
4009 return {
4010 topLevelType: topLevelType,
4011 nativeEvent: nativeEvent,
4012 targetInst: targetInst,
4013 ancestors: []
4014 };
4015}
4016
4017function releaseTopLevelCallbackBookKeeping(instance) {
4018 instance.topLevelType = null;
4019 instance.nativeEvent = null;
4020 instance.targetInst = null;
4021 instance.ancestors.length = 0;
4022 if (callbackBookkeepingPool.length < CALLBACK_BOOKKEEPING_POOL_SIZE) {
4023 callbackBookkeepingPool.push(instance);
4024 }
4025}
4026
4027function handleTopLevelImpl(bookKeeping) {
4028 var targetInst = bookKeeping.targetInst;
4029
4030 // Loop through the hierarchy, in case there's any nested components.
4031 // It's important that we build the array of ancestors before calling any
4032 // event handlers, because event handlers can modify the DOM, leading to
4033 // inconsistencies with ReactMount's node cache. See #1105.
4034 var ancestor = targetInst;
4035 do {
4036 if (!ancestor) {
4037 bookKeeping.ancestors.push(ancestor);
4038 break;
4039 }
4040 var root = findRootContainerNode(ancestor);
4041 if (!root) {
4042 break;
4043 }
4044 bookKeeping.ancestors.push(ancestor);
4045 ancestor = getClosestInstanceFromNode(root);
4046 } while (ancestor);
4047
4048 for (var i = 0; i < bookKeeping.ancestors.length; i++) {
4049 targetInst = bookKeeping.ancestors[i];
4050 _handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
4051 }
4052}
4053
4054// TODO: can we stop exporting these?
4055var _enabled = true;
4056var _handleTopLevel = void 0;
4057
4058function setHandleTopLevel(handleTopLevel) {
4059 _handleTopLevel = handleTopLevel;
4060}
4061
4062function setEnabled(enabled) {
4063 _enabled = !!enabled;
4064}
4065
4066function isEnabled() {
4067 return _enabled;
4068}
4069
4070/**
4071 * Traps top-level events by using event bubbling.
4072 *
4073 * @param {string} topLevelType Record from `BrowserEventConstants`.
4074 * @param {string} handlerBaseName Event name (e.g. "click").
4075 * @param {object} element Element on which to attach listener.
4076 * @return {?object} An object with a remove function which will forcefully
4077 * remove the listener.
4078 * @internal
4079 */
4080function trapBubbledEvent(topLevelType, handlerBaseName, element) {
4081 if (!element) {
4082 return null;
4083 }
4084 addEventBubbleListener(element, handlerBaseName, dispatchEvent.bind(null, topLevelType));
4085}
4086
4087/**
4088 * Traps a top-level event by using event capturing.
4089 *
4090 * @param {string} topLevelType Record from `BrowserEventConstants`.
4091 * @param {string} handlerBaseName Event name (e.g. "click").
4092 * @param {object} element Element on which to attach listener.
4093 * @return {?object} An object with a remove function which will forcefully
4094 * remove the listener.
4095 * @internal
4096 */
4097function trapCapturedEvent(topLevelType, handlerBaseName, element) {
4098 if (!element) {
4099 return null;
4100 }
4101 addEventCaptureListener(element, handlerBaseName, dispatchEvent.bind(null, topLevelType));
4102}
4103
4104function dispatchEvent(topLevelType, nativeEvent) {
4105 if (!_enabled) {
4106 return;
4107 }
4108
4109 var nativeEventTarget = getEventTarget(nativeEvent);
4110 var targetInst = getClosestInstanceFromNode(nativeEventTarget);
4111 if (targetInst !== null && typeof targetInst.tag === 'number' && !isFiberMounted(targetInst)) {
4112 // If we get an event (ex: img onload) before committing that
4113 // component's mount, ignore it for now (that is, treat it as if it was an
4114 // event on a non-React tree). We might also consider queueing events and
4115 // dispatching them after the mount.
4116 targetInst = null;
4117 }
4118
4119 var bookKeeping = getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst);
4120
4121 try {
4122 // Event queue being processed in the same cycle allows
4123 // `preventDefault`.
4124 batchedUpdates(handleTopLevelImpl, bookKeeping);
4125 } finally {
4126 releaseTopLevelCallbackBookKeeping(bookKeeping);
4127 }
4128}
4129
4130var ReactDOMEventListener = Object.freeze({
4131 get _enabled () { return _enabled; },
4132 get _handleTopLevel () { return _handleTopLevel; },
4133 setHandleTopLevel: setHandleTopLevel,
4134 setEnabled: setEnabled,
4135 isEnabled: isEnabled,
4136 trapBubbledEvent: trapBubbledEvent,
4137 trapCapturedEvent: trapCapturedEvent,
4138 dispatchEvent: dispatchEvent
4139});
4140
4141/**
4142 * Generate a mapping of standard vendor prefixes using the defined style property and event name.
4143 *
4144 * @param {string} styleProp
4145 * @param {string} eventName
4146 * @returns {object}
4147 */
4148function makePrefixMap(styleProp, eventName) {
4149 var prefixes = {};
4150
4151 prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
4152 prefixes['Webkit' + styleProp] = 'webkit' + eventName;
4153 prefixes['Moz' + styleProp] = 'moz' + eventName;
4154 prefixes['ms' + styleProp] = 'MS' + eventName;
4155 prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();
4156
4157 return prefixes;
4158}
4159
4160/**
4161 * A list of event names to a configurable list of vendor prefixes.
4162 */
4163var vendorPrefixes = {
4164 animationend: makePrefixMap('Animation', 'AnimationEnd'),
4165 animationiteration: makePrefixMap('Animation', 'AnimationIteration'),
4166 animationstart: makePrefixMap('Animation', 'AnimationStart'),
4167 transitionend: makePrefixMap('Transition', 'TransitionEnd')
4168};
4169
4170/**
4171 * Event names that have already been detected and prefixed (if applicable).
4172 */
4173var prefixedEventNames = {};
4174
4175/**
4176 * Element to check for prefixes on.
4177 */
4178var style = {};
4179
4180/**
4181 * Bootstrap if a DOM exists.
4182 */
4183if (ExecutionEnvironment_1.canUseDOM) {
4184 style = document.createElement('div').style;
4185
4186 // On some platforms, in particular some releases of Android 4.x,
4187 // the un-prefixed "animation" and "transition" properties are defined on the
4188 // style object but the events that fire will still be prefixed, so we need
4189 // to check if the un-prefixed events are usable, and if not remove them from the map.
4190 if (!('AnimationEvent' in window)) {
4191 delete vendorPrefixes.animationend.animation;
4192 delete vendorPrefixes.animationiteration.animation;
4193 delete vendorPrefixes.animationstart.animation;
4194 }
4195
4196 // Same as above
4197 if (!('TransitionEvent' in window)) {
4198 delete vendorPrefixes.transitionend.transition;
4199 }
4200}
4201
4202/**
4203 * Attempts to determine the correct vendor prefixed event name.
4204 *
4205 * @param {string} eventName
4206 * @returns {string}
4207 */
4208function getVendorPrefixedEventName(eventName) {
4209 if (prefixedEventNames[eventName]) {
4210 return prefixedEventNames[eventName];
4211 } else if (!vendorPrefixes[eventName]) {
4212 return eventName;
4213 }
4214
4215 var prefixMap = vendorPrefixes[eventName];
4216
4217 for (var styleProp in prefixMap) {
4218 if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {
4219 return prefixedEventNames[eventName] = prefixMap[styleProp];
4220 }
4221 }
4222
4223 return eventName;
4224}
4225
4226/**
4227 * Types of raw signals from the browser caught at the top level.
4228 *
4229 * For events like 'submit' which don't consistently bubble (which we
4230 * trap at a lower node than `document`), binding at `document` would
4231 * cause duplicate events so we don't include them here.
4232 */
4233var topLevelTypes$1 = {
4234 topAbort: 'abort',
4235 topAnimationEnd: getVendorPrefixedEventName('animationend'),
4236 topAnimationIteration: getVendorPrefixedEventName('animationiteration'),
4237 topAnimationStart: getVendorPrefixedEventName('animationstart'),
4238 topBlur: 'blur',
4239 topCancel: 'cancel',
4240 topCanPlay: 'canplay',
4241 topCanPlayThrough: 'canplaythrough',
4242 topChange: 'change',
4243 topClick: 'click',
4244 topClose: 'close',
4245 topCompositionEnd: 'compositionend',
4246 topCompositionStart: 'compositionstart',
4247 topCompositionUpdate: 'compositionupdate',
4248 topContextMenu: 'contextmenu',
4249 topCopy: 'copy',
4250 topCut: 'cut',
4251 topDoubleClick: 'dblclick',
4252 topDrag: 'drag',
4253 topDragEnd: 'dragend',
4254 topDragEnter: 'dragenter',
4255 topDragExit: 'dragexit',
4256 topDragLeave: 'dragleave',
4257 topDragOver: 'dragover',
4258 topDragStart: 'dragstart',
4259 topDrop: 'drop',
4260 topDurationChange: 'durationchange',
4261 topEmptied: 'emptied',
4262 topEncrypted: 'encrypted',
4263 topEnded: 'ended',
4264 topError: 'error',
4265 topFocus: 'focus',
4266 topInput: 'input',
4267 topKeyDown: 'keydown',
4268 topKeyPress: 'keypress',
4269 topKeyUp: 'keyup',
4270 topLoadedData: 'loadeddata',
4271 topLoad: 'load',
4272 topLoadedMetadata: 'loadedmetadata',
4273 topLoadStart: 'loadstart',
4274 topMouseDown: 'mousedown',
4275 topMouseMove: 'mousemove',
4276 topMouseOut: 'mouseout',
4277 topMouseOver: 'mouseover',
4278 topMouseUp: 'mouseup',
4279 topPaste: 'paste',
4280 topPause: 'pause',
4281 topPlay: 'play',
4282 topPlaying: 'playing',
4283 topProgress: 'progress',
4284 topRateChange: 'ratechange',
4285 topScroll: 'scroll',
4286 topSeeked: 'seeked',
4287 topSeeking: 'seeking',
4288 topSelectionChange: 'selectionchange',
4289 topStalled: 'stalled',
4290 topSuspend: 'suspend',
4291 topTextInput: 'textInput',
4292 topTimeUpdate: 'timeupdate',
4293 topToggle: 'toggle',
4294 topTouchCancel: 'touchcancel',
4295 topTouchEnd: 'touchend',
4296 topTouchMove: 'touchmove',
4297 topTouchStart: 'touchstart',
4298 topTransitionEnd: getVendorPrefixedEventName('transitionend'),
4299 topVolumeChange: 'volumechange',
4300 topWaiting: 'waiting',
4301 topWheel: 'wheel'
4302};
4303
4304var BrowserEventConstants = {
4305 topLevelTypes: topLevelTypes$1
4306};
4307
4308function runEventQueueInBatch(events) {
4309 enqueueEvents(events);
4310 processEventQueue(false);
4311}
4312
4313/**
4314 * Streams a fired top-level event to `EventPluginHub` where plugins have the
4315 * opportunity to create `ReactEvent`s to be dispatched.
4316 */
4317function handleTopLevel(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
4318 var events = extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
4319 runEventQueueInBatch(events);
4320}
4321
4322var topLevelTypes = BrowserEventConstants.topLevelTypes;
4323
4324/**
4325 * Summary of `ReactBrowserEventEmitter` event handling:
4326 *
4327 * - Top-level delegation is used to trap most native browser events. This
4328 * may only occur in the main thread and is the responsibility of
4329 * ReactDOMEventListener, which is injected and can therefore support
4330 * pluggable event sources. This is the only work that occurs in the main
4331 * thread.
4332 *
4333 * - We normalize and de-duplicate events to account for browser quirks. This
4334 * may be done in the worker thread.
4335 *
4336 * - Forward these native events (with the associated top-level type used to
4337 * trap it) to `EventPluginHub`, which in turn will ask plugins if they want
4338 * to extract any synthetic events.
4339 *
4340 * - The `EventPluginHub` will then process each event by annotating them with
4341 * "dispatches", a sequence of listeners and IDs that care about that event.
4342 *
4343 * - The `EventPluginHub` then dispatches the events.
4344 *
4345 * Overview of React and the event system:
4346 *
4347 * +------------+ .
4348 * | DOM | .
4349 * +------------+ .
4350 * | .
4351 * v .
4352 * +------------+ .
4353 * | ReactEvent | .
4354 * | Listener | .
4355 * +------------+ . +-----------+
4356 * | . +--------+|SimpleEvent|
4357 * | . | |Plugin |
4358 * +-----|------+ . v +-----------+
4359 * | | | . +--------------+ +------------+
4360 * | +-----------.--->|EventPluginHub| | Event |
4361 * | | . | | +-----------+ | Propagators|
4362 * | ReactEvent | . | | |TapEvent | |------------|
4363 * | Emitter | . | |<---+|Plugin | |other plugin|
4364 * | | . | | +-----------+ | utilities |
4365 * | +-----------.--->| | +------------+
4366 * | | | . +--------------+
4367 * +-----|------+ . ^ +-----------+
4368 * | . | |Enter/Leave|
4369 * + . +-------+|Plugin |
4370 * +-------------+ . +-----------+
4371 * | application | .
4372 * |-------------| .
4373 * | | .
4374 * | | .
4375 * +-------------+ .
4376 * .
4377 * React Core . General Purpose Event Plugin System
4378 */
4379
4380var alreadyListeningTo = {};
4381var reactTopListenersCounter = 0;
4382
4383/**
4384 * To ensure no conflicts with other potential React instances on the page
4385 */
4386var topListenersIDKey = '_reactListenersID' + ('' + Math.random()).slice(2);
4387
4388function getListeningForDocument(mountAt) {
4389 // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
4390 // directly.
4391 if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
4392 mountAt[topListenersIDKey] = reactTopListenersCounter++;
4393 alreadyListeningTo[mountAt[topListenersIDKey]] = {};
4394 }
4395 return alreadyListeningTo[mountAt[topListenersIDKey]];
4396}
4397
4398/**
4399 * We listen for bubbled touch events on the document object.
4400 *
4401 * Firefox v8.01 (and possibly others) exhibited strange behavior when
4402 * mounting `onmousemove` events at some node that was not the document
4403 * element. The symptoms were that if your mouse is not moving over something
4404 * contained within that mount point (for example on the background) the
4405 * top-level listeners for `onmousemove` won't be called. However, if you
4406 * register the `mousemove` on the document object, then it will of course
4407 * catch all `mousemove`s. This along with iOS quirks, justifies restricting
4408 * top-level listeners to the document object only, at least for these
4409 * movement types of events and possibly all events.
4410 *
4411 * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
4412 *
4413 * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
4414 * they bubble to document.
4415 *
4416 * @param {string} registrationName Name of listener (e.g. `onClick`).
4417 * @param {object} contentDocumentHandle Document which owns the container
4418 */
4419function listenTo(registrationName, contentDocumentHandle) {
4420 var mountAt = contentDocumentHandle;
4421 var isListening = getListeningForDocument(mountAt);
4422 var dependencies = registrationNameDependencies[registrationName];
4423
4424 for (var i = 0; i < dependencies.length; i++) {
4425 var dependency = dependencies[i];
4426 if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
4427 if (dependency === 'topScroll') {
4428 trapCapturedEvent('topScroll', 'scroll', mountAt);
4429 } else if (dependency === 'topFocus' || dependency === 'topBlur') {
4430 trapCapturedEvent('topFocus', 'focus', mountAt);
4431 trapCapturedEvent('topBlur', 'blur', mountAt);
4432
4433 // to make sure blur and focus event listeners are only attached once
4434 isListening.topBlur = true;
4435 isListening.topFocus = true;
4436 } else if (dependency === 'topCancel') {
4437 if (isEventSupported('cancel', true)) {
4438 trapCapturedEvent('topCancel', 'cancel', mountAt);
4439 }
4440 isListening.topCancel = true;
4441 } else if (dependency === 'topClose') {
4442 if (isEventSupported('close', true)) {
4443 trapCapturedEvent('topClose', 'close', mountAt);
4444 }
4445 isListening.topClose = true;
4446 } else if (topLevelTypes.hasOwnProperty(dependency)) {
4447 trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt);
4448 }
4449
4450 isListening[dependency] = true;
4451 }
4452 }
4453}
4454
4455function isListeningToAllDependencies(registrationName, mountAt) {
4456 var isListening = getListeningForDocument(mountAt);
4457 var dependencies = registrationNameDependencies[registrationName];
4458 for (var i = 0; i < dependencies.length; i++) {
4459 var dependency = dependencies[i];
4460 if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
4461 return false;
4462 }
4463 }
4464 return true;
4465}
4466
4467/**
4468 * Copyright (c) 2013-present, Facebook, Inc.
4469 *
4470 * This source code is licensed under the MIT license found in the
4471 * LICENSE file in the root directory of this source tree.
4472 *
4473 * @typechecks
4474 */
4475
4476/* eslint-disable fb-www/typeof-undefined */
4477
4478/**
4479 * Same as document.activeElement but wraps in a try-catch block. In IE it is
4480 * not safe to call document.activeElement if there is nothing focused.
4481 *
4482 * The activeElement will be null only if the document or document body is not
4483 * yet defined.
4484 *
4485 * @param {?DOMDocument} doc Defaults to current document.
4486 * @return {?DOMElement}
4487 */
4488function getActiveElement(doc) /*?DOMElement*/{
4489 doc = doc || (typeof document !== 'undefined' ? document : undefined);
4490 if (typeof doc === 'undefined') {
4491 return null;
4492 }
4493 try {
4494 return doc.activeElement || doc.body;
4495 } catch (e) {
4496 return doc.body;
4497 }
4498}
4499
4500var getActiveElement_1 = getActiveElement;
4501
4502/**
4503 * Copyright (c) 2013-present, Facebook, Inc.
4504 *
4505 * This source code is licensed under the MIT license found in the
4506 * LICENSE file in the root directory of this source tree.
4507 *
4508 * @typechecks
4509 *
4510 */
4511
4512/*eslint-disable no-self-compare */
4513
4514
4515
4516var hasOwnProperty = Object.prototype.hasOwnProperty;
4517
4518/**
4519 * inlined Object.is polyfill to avoid requiring consumers ship their own
4520 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
4521 */
4522function is(x, y) {
4523 // SameValue algorithm
4524 if (x === y) {
4525 // Steps 1-5, 7-10
4526 // Steps 6.b-6.e: +0 != -0
4527 // Added the nonzero y check to make Flow happy, but it is redundant
4528 return x !== 0 || y !== 0 || 1 / x === 1 / y;
4529 } else {
4530 // Step 6.a: NaN == NaN
4531 return x !== x && y !== y;
4532 }
4533}
4534
4535/**
4536 * Performs equality by iterating through keys on an object and returning false
4537 * when any key has values which are not strictly equal between the arguments.
4538 * Returns true when the values of all keys are strictly equal.
4539 */
4540function shallowEqual(objA, objB) {
4541 if (is(objA, objB)) {
4542 return true;
4543 }
4544
4545 if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
4546 return false;
4547 }
4548
4549 var keysA = Object.keys(objA);
4550 var keysB = Object.keys(objB);
4551
4552 if (keysA.length !== keysB.length) {
4553 return false;
4554 }
4555
4556 // Test for A's keys different from B.
4557 for (var i = 0; i < keysA.length; i++) {
4558 if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
4559 return false;
4560 }
4561 }
4562
4563 return true;
4564}
4565
4566var shallowEqual_1 = shallowEqual;
4567
4568/**
4569 * Copyright (c) 2013-present, Facebook, Inc.
4570 *
4571 * This source code is licensed under the MIT license found in the
4572 * LICENSE file in the root directory of this source tree.
4573 *
4574 * @typechecks
4575 */
4576
4577/**
4578 * @param {*} object The object to check.
4579 * @return {boolean} Whether or not the object is a DOM node.
4580 */
4581function isNode(object) {
4582 var doc = object ? object.ownerDocument || object : document;
4583 var defaultView = doc.defaultView || window;
4584 return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
4585}
4586
4587var isNode_1 = isNode;
4588
4589/**
4590 * Copyright (c) 2013-present, Facebook, Inc.
4591 *
4592 * This source code is licensed under the MIT license found in the
4593 * LICENSE file in the root directory of this source tree.
4594 *
4595 * @typechecks
4596 */
4597
4598
4599
4600/**
4601 * @param {*} object The object to check.
4602 * @return {boolean} Whether or not the object is a DOM text node.
4603 */
4604function isTextNode(object) {
4605 return isNode_1(object) && object.nodeType == 3;
4606}
4607
4608var isTextNode_1 = isTextNode;
4609
4610/**
4611 * Copyright (c) 2013-present, Facebook, Inc.
4612 *
4613 * This source code is licensed under the MIT license found in the
4614 * LICENSE file in the root directory of this source tree.
4615 *
4616 *
4617 */
4618
4619
4620
4621/*eslint-disable no-bitwise */
4622
4623/**
4624 * Checks if a given DOM node contains or is another DOM node.
4625 */
4626function containsNode(outerNode, innerNode) {
4627 if (!outerNode || !innerNode) {
4628 return false;
4629 } else if (outerNode === innerNode) {
4630 return true;
4631 } else if (isTextNode_1(outerNode)) {
4632 return false;
4633 } else if (isTextNode_1(innerNode)) {
4634 return containsNode(outerNode, innerNode.parentNode);
4635 } else if ('contains' in outerNode) {
4636 return outerNode.contains(innerNode);
4637 } else if (outerNode.compareDocumentPosition) {
4638 return !!(outerNode.compareDocumentPosition(innerNode) & 16);
4639 } else {
4640 return false;
4641 }
4642}
4643
4644var containsNode_1 = containsNode;
4645
4646/**
4647 * Given any node return the first leaf node without children.
4648 *
4649 * @param {DOMElement|DOMTextNode} node
4650 * @return {DOMElement|DOMTextNode}
4651 */
4652function getLeafNode(node) {
4653 while (node && node.firstChild) {
4654 node = node.firstChild;
4655 }
4656 return node;
4657}
4658
4659/**
4660 * Get the next sibling within a container. This will walk up the
4661 * DOM if a node's siblings have been exhausted.
4662 *
4663 * @param {DOMElement|DOMTextNode} node
4664 * @return {?DOMElement|DOMTextNode}
4665 */
4666function getSiblingNode(node) {
4667 while (node) {
4668 if (node.nextSibling) {
4669 return node.nextSibling;
4670 }
4671 node = node.parentNode;
4672 }
4673}
4674
4675/**
4676 * Get object describing the nodes which contain characters at offset.
4677 *
4678 * @param {DOMElement|DOMTextNode} root
4679 * @param {number} offset
4680 * @return {?object}
4681 */
4682function getNodeForCharacterOffset(root, offset) {
4683 var node = getLeafNode(root);
4684 var nodeStart = 0;
4685 var nodeEnd = 0;
4686
4687 while (node) {
4688 if (node.nodeType === TEXT_NODE) {
4689 nodeEnd = nodeStart + node.textContent.length;
4690
4691 if (nodeStart <= offset && nodeEnd >= offset) {
4692 return {
4693 node: node,
4694 offset: offset - nodeStart
4695 };
4696 }
4697
4698 nodeStart = nodeEnd;
4699 }
4700
4701 node = getLeafNode(getSiblingNode(node));
4702 }
4703}
4704
4705/**
4706 * @param {DOMElement} outerNode
4707 * @return {?object}
4708 */
4709function getOffsets(outerNode) {
4710 var selection = window.getSelection && window.getSelection();
4711
4712 if (!selection || selection.rangeCount === 0) {
4713 return null;
4714 }
4715
4716 var anchorNode = selection.anchorNode,
4717 anchorOffset = selection.anchorOffset,
4718 focusNode = selection.focusNode,
4719 focusOffset = selection.focusOffset;
4720
4721 // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the
4722 // up/down buttons on an <input type="number">. Anonymous divs do not seem to
4723 // expose properties, triggering a "Permission denied error" if any of its
4724 // properties are accessed. The only seemingly possible way to avoid erroring
4725 // is to access a property that typically works for non-anonymous divs and
4726 // catch any error that may otherwise arise. See
4727 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
4728
4729 try {
4730 /* eslint-disable no-unused-expressions */
4731 anchorNode.nodeType;
4732 focusNode.nodeType;
4733 /* eslint-enable no-unused-expressions */
4734 } catch (e) {
4735 return null;
4736 }
4737
4738 return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset);
4739}
4740
4741/**
4742 * Returns {start, end} where `start` is the character/codepoint index of
4743 * (anchorNode, anchorOffset) within the textContent of `outerNode`, and
4744 * `end` is the index of (focusNode, focusOffset).
4745 *
4746 * Returns null if you pass in garbage input but we should probably just crash.
4747 *
4748 * Exported only for testing.
4749 */
4750function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) {
4751 var length = 0;
4752 var start = -1;
4753 var end = -1;
4754 var indexWithinAnchor = 0;
4755 var indexWithinFocus = 0;
4756 var node = outerNode;
4757 var parentNode = null;
4758
4759 outer: while (true) {
4760 var next = null;
4761
4762 while (true) {
4763 if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) {
4764 start = length + anchorOffset;
4765 }
4766 if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) {
4767 end = length + focusOffset;
4768 }
4769
4770 if (node.nodeType === TEXT_NODE) {
4771 length += node.nodeValue.length;
4772 }
4773
4774 if ((next = node.firstChild) === null) {
4775 break;
4776 }
4777 // Moving from `node` to its first child `next`.
4778 parentNode = node;
4779 node = next;
4780 }
4781
4782 while (true) {
4783 if (node === outerNode) {
4784 // If `outerNode` has children, this is always the second time visiting
4785 // it. If it has no children, this is still the first loop, and the only
4786 // valid selection is anchorNode and focusNode both equal to this node
4787 // and both offsets 0, in which case we will have handled above.
4788 break outer;
4789 }
4790 if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) {
4791 start = length;
4792 }
4793 if (parentNode === focusNode && ++indexWithinFocus === focusOffset) {
4794 end = length;
4795 }
4796 if ((next = node.nextSibling) !== null) {
4797 break;
4798 }
4799 node = parentNode;
4800 parentNode = node.parentNode;
4801 }
4802
4803 // Moving from `node` to its next sibling `next`.
4804 node = next;
4805 }
4806
4807 if (start === -1 || end === -1) {
4808 // This should never happen. (Would happen if the anchor/focus nodes aren't
4809 // actually inside the passed-in node.)
4810 return null;
4811 }
4812
4813 return {
4814 start: start,
4815 end: end
4816 };
4817}
4818
4819/**
4820 * In modern non-IE browsers, we can support both forward and backward
4821 * selections.
4822 *
4823 * Note: IE10+ supports the Selection object, but it does not support
4824 * the `extend` method, which means that even in modern IE, it's not possible
4825 * to programmatically create a backward selection. Thus, for all IE
4826 * versions, we use the old IE API to create our selections.
4827 *
4828 * @param {DOMElement|DOMTextNode} node
4829 * @param {object} offsets
4830 */
4831function setOffsets(node, offsets) {
4832 if (!window.getSelection) {
4833 return;
4834 }
4835
4836 var selection = window.getSelection();
4837 var length = node[getTextContentAccessor()].length;
4838 var start = Math.min(offsets.start, length);
4839 var end = offsets.end === undefined ? start : Math.min(offsets.end, length);
4840
4841 // IE 11 uses modern selection, but doesn't support the extend method.
4842 // Flip backward selections, so we can set with a single range.
4843 if (!selection.extend && start > end) {
4844 var temp = end;
4845 end = start;
4846 start = temp;
4847 }
4848
4849 var startMarker = getNodeForCharacterOffset(node, start);
4850 var endMarker = getNodeForCharacterOffset(node, end);
4851
4852 if (startMarker && endMarker) {
4853 if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) {
4854 return;
4855 }
4856 var range = document.createRange();
4857 range.setStart(startMarker.node, startMarker.offset);
4858 selection.removeAllRanges();
4859
4860 if (start > end) {
4861 selection.addRange(range);
4862 selection.extend(endMarker.node, endMarker.offset);
4863 } else {
4864 range.setEnd(endMarker.node, endMarker.offset);
4865 selection.addRange(range);
4866 }
4867 }
4868}
4869
4870function isInDocument(node) {
4871 return containsNode_1(document.documentElement, node);
4872}
4873
4874/**
4875 * @ReactInputSelection: React input selection module. Based on Selection.js,
4876 * but modified to be suitable for react and has a couple of bug fixes (doesn't
4877 * assume buttons have range selections allowed).
4878 * Input selection module for React.
4879 */
4880
4881function hasSelectionCapabilities(elem) {
4882 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
4883 return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');
4884}
4885
4886function getSelectionInformation() {
4887 var focusedElem = getActiveElement_1();
4888 return {
4889 focusedElem: focusedElem,
4890 selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection$1(focusedElem) : null
4891 };
4892}
4893
4894/**
4895 * @restoreSelection: If any selection information was potentially lost,
4896 * restore it. This is useful when performing operations that could remove dom
4897 * nodes and place them back in, resulting in focus being lost.
4898 */
4899function restoreSelection(priorSelectionInformation) {
4900 var curFocusedElem = getActiveElement_1();
4901 var priorFocusedElem = priorSelectionInformation.focusedElem;
4902 var priorSelectionRange = priorSelectionInformation.selectionRange;
4903 if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
4904 if (hasSelectionCapabilities(priorFocusedElem)) {
4905 setSelection(priorFocusedElem, priorSelectionRange);
4906 }
4907
4908 // Focusing a node can change the scroll position, which is undesirable
4909 var ancestors = [];
4910 var ancestor = priorFocusedElem;
4911 while (ancestor = ancestor.parentNode) {
4912 if (ancestor.nodeType === ELEMENT_NODE) {
4913 ancestors.push({
4914 element: ancestor,
4915 left: ancestor.scrollLeft,
4916 top: ancestor.scrollTop
4917 });
4918 }
4919 }
4920
4921 priorFocusedElem.focus();
4922
4923 for (var i = 0; i < ancestors.length; i++) {
4924 var info = ancestors[i];
4925 info.element.scrollLeft = info.left;
4926 info.element.scrollTop = info.top;
4927 }
4928 }
4929}
4930
4931/**
4932 * @getSelection: Gets the selection bounds of a focused textarea, input or
4933 * contentEditable node.
4934 * -@input: Look up selection bounds of this input
4935 * -@return {start: selectionStart, end: selectionEnd}
4936 */
4937function getSelection$1(input) {
4938 var selection = void 0;
4939
4940 if ('selectionStart' in input) {
4941 // Modern browser with input or textarea.
4942 selection = {
4943 start: input.selectionStart,
4944 end: input.selectionEnd
4945 };
4946 } else {
4947 // Content editable or old IE textarea.
4948 selection = getOffsets(input);
4949 }
4950
4951 return selection || { start: 0, end: 0 };
4952}
4953
4954/**
4955 * @setSelection: Sets the selection bounds of a textarea or input and focuses
4956 * the input.
4957 * -@input Set selection bounds of this input or textarea
4958 * -@offsets Object of same form that is returned from get*
4959 */
4960function setSelection(input, offsets) {
4961 var start = offsets.start,
4962 end = offsets.end;
4963
4964 if (end === undefined) {
4965 end = start;
4966 }
4967
4968 if ('selectionStart' in input) {
4969 input.selectionStart = start;
4970 input.selectionEnd = Math.min(end, input.value.length);
4971 } else {
4972 setOffsets(input, offsets);
4973 }
4974}
4975
4976var skipSelectionChangeEvent = ExecutionEnvironment_1.canUseDOM && 'documentMode' in document && document.documentMode <= 11;
4977
4978var eventTypes$3 = {
4979 select: {
4980 phasedRegistrationNames: {
4981 bubbled: 'onSelect',
4982 captured: 'onSelectCapture'
4983 },
4984 dependencies: ['topBlur', 'topContextMenu', 'topFocus', 'topKeyDown', 'topKeyUp', 'topMouseDown', 'topMouseUp', 'topSelectionChange']
4985 }
4986};
4987
4988var activeElement$1 = null;
4989var activeElementInst$1 = null;
4990var lastSelection = null;
4991var mouseDown = false;
4992
4993/**
4994 * Get an object which is a unique representation of the current selection.
4995 *
4996 * The return value will not be consistent across nodes or browsers, but
4997 * two identical selections on the same node will return identical objects.
4998 *
4999 * @param {DOMElement} node
5000 * @return {object}
5001 */
5002function getSelection(node) {
5003 if ('selectionStart' in node && hasSelectionCapabilities(node)) {
5004 return {
5005 start: node.selectionStart,
5006 end: node.selectionEnd
5007 };
5008 } else if (window.getSelection) {
5009 var selection = window.getSelection();
5010 return {
5011 anchorNode: selection.anchorNode,
5012 anchorOffset: selection.anchorOffset,
5013 focusNode: selection.focusNode,
5014 focusOffset: selection.focusOffset
5015 };
5016 }
5017}
5018
5019/**
5020 * Poll selection to see whether it's changed.
5021 *
5022 * @param {object} nativeEvent
5023 * @return {?SyntheticEvent}
5024 */
5025function constructSelectEvent(nativeEvent, nativeEventTarget) {
5026 // Ensure we have the right element, and that the user is not dragging a
5027 // selection (this matches native `select` event behavior). In HTML5, select
5028 // fires only on input and textarea thus if there's no focused element we
5029 // won't dispatch.
5030 if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement_1()) {
5031 return null;
5032 }
5033
5034 // Only fire when selection has actually changed.
5035 var currentSelection = getSelection(activeElement$1);
5036 if (!lastSelection || !shallowEqual_1(lastSelection, currentSelection)) {
5037 lastSelection = currentSelection;
5038
5039 var syntheticEvent = SyntheticEvent$1.getPooled(eventTypes$3.select, activeElementInst$1, nativeEvent, nativeEventTarget);
5040
5041 syntheticEvent.type = 'select';
5042 syntheticEvent.target = activeElement$1;
5043
5044 accumulateTwoPhaseDispatches(syntheticEvent);
5045
5046 return syntheticEvent;
5047 }
5048
5049 return null;
5050}
5051
5052/**
5053 * This plugin creates an `onSelect` event that normalizes select events
5054 * across form elements.
5055 *
5056 * Supported elements are:
5057 * - input (see `isTextInputElement`)
5058 * - textarea
5059 * - contentEditable
5060 *
5061 * This differs from native browser implementations in the following ways:
5062 * - Fires on contentEditable fields as well as inputs.
5063 * - Fires for collapsed selection.
5064 * - Fires after user input.
5065 */
5066var SelectEventPlugin = {
5067 eventTypes: eventTypes$3,
5068
5069 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
5070 var doc = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget.document : nativeEventTarget.nodeType === DOCUMENT_NODE ? nativeEventTarget : nativeEventTarget.ownerDocument;
5071 // Track whether all listeners exists for this plugin. If none exist, we do
5072 // not extract events. See #3639.
5073 if (!doc || !isListeningToAllDependencies('onSelect', doc)) {
5074 return null;
5075 }
5076
5077 var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
5078
5079 switch (topLevelType) {
5080 // Track the input node that has focus.
5081 case 'topFocus':
5082 if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {
5083 activeElement$1 = targetNode;
5084 activeElementInst$1 = targetInst;
5085 lastSelection = null;
5086 }
5087 break;
5088 case 'topBlur':
5089 activeElement$1 = null;
5090 activeElementInst$1 = null;
5091 lastSelection = null;
5092 break;
5093 // Don't fire the event while the user is dragging. This matches the
5094 // semantics of the native select event.
5095 case 'topMouseDown':
5096 mouseDown = true;
5097 break;
5098 case 'topContextMenu':
5099 case 'topMouseUp':
5100 mouseDown = false;
5101 return constructSelectEvent(nativeEvent, nativeEventTarget);
5102 // Chrome and IE fire non-standard event when selection is changed (and
5103 // sometimes when it hasn't). IE's event fires out of order with respect
5104 // to key and input events on deletion, so we discard it.
5105 //
5106 // Firefox doesn't support selectionchange, so check selection status
5107 // after each key entry. The selection changes after keydown and before
5108 // keyup, but we check on keydown as well in the case of holding down a
5109 // key, when multiple keydown events are fired but only one keyup is.
5110 // This is also our approach for IE handling, for the reason above.
5111 case 'topSelectionChange':
5112 if (skipSelectionChangeEvent) {
5113 break;
5114 }
5115 // falls through
5116 case 'topKeyDown':
5117 case 'topKeyUp':
5118 return constructSelectEvent(nativeEvent, nativeEventTarget);
5119 }
5120
5121 return null;
5122 }
5123};
5124
5125/**
5126 * @interface Event
5127 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
5128 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
5129 */
5130var SyntheticAnimationEvent = SyntheticEvent$1.extend({
5131 animationName: null,
5132 elapsedTime: null,
5133 pseudoElement: null
5134});
5135
5136/**
5137 * @interface Event
5138 * @see http://www.w3.org/TR/clipboard-apis/
5139 */
5140var SyntheticClipboardEvent = SyntheticEvent$1.extend({
5141 clipboardData: function (event) {
5142 return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
5143 }
5144});
5145
5146/**
5147 * @interface FocusEvent
5148 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5149 */
5150var SyntheticFocusEvent = SyntheticUIEvent.extend({
5151 relatedTarget: null
5152});
5153
5154/**
5155 * `charCode` represents the actual "character code" and is safe to use with
5156 * `String.fromCharCode`. As such, only keys that correspond to printable
5157 * characters produce a valid `charCode`, the only exception to this is Enter.
5158 * The Tab-key is considered non-printable and does not have a `charCode`,
5159 * presumably because it does not produce a tab-character in browsers.
5160 *
5161 * @param {object} nativeEvent Native browser event.
5162 * @return {number} Normalized `charCode` property.
5163 */
5164function getEventCharCode(nativeEvent) {
5165 var charCode = void 0;
5166 var keyCode = nativeEvent.keyCode;
5167
5168 if ('charCode' in nativeEvent) {
5169 charCode = nativeEvent.charCode;
5170
5171 // FF does not set `charCode` for the Enter-key, check against `keyCode`.
5172 if (charCode === 0 && keyCode === 13) {
5173 charCode = 13;
5174 }
5175 } else {
5176 // IE8 does not implement `charCode`, but `keyCode` has the correct value.
5177 charCode = keyCode;
5178 }
5179
5180 // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
5181 // Must not discard the (non-)printable Enter-key.
5182 if (charCode >= 32 || charCode === 13) {
5183 return charCode;
5184 }
5185
5186 return 0;
5187}
5188
5189/**
5190 * Normalization of deprecated HTML5 `key` values
5191 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
5192 */
5193var normalizeKey = {
5194 Esc: 'Escape',
5195 Spacebar: ' ',
5196 Left: 'ArrowLeft',
5197 Up: 'ArrowUp',
5198 Right: 'ArrowRight',
5199 Down: 'ArrowDown',
5200 Del: 'Delete',
5201 Win: 'OS',
5202 Menu: 'ContextMenu',
5203 Apps: 'ContextMenu',
5204 Scroll: 'ScrollLock',
5205 MozPrintableKey: 'Unidentified'
5206};
5207
5208/**
5209 * Translation from legacy `keyCode` to HTML5 `key`
5210 * Only special keys supported, all others depend on keyboard layout or browser
5211 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
5212 */
5213var translateToKey = {
5214 '8': 'Backspace',
5215 '9': 'Tab',
5216 '12': 'Clear',
5217 '13': 'Enter',
5218 '16': 'Shift',
5219 '17': 'Control',
5220 '18': 'Alt',
5221 '19': 'Pause',
5222 '20': 'CapsLock',
5223 '27': 'Escape',
5224 '32': ' ',
5225 '33': 'PageUp',
5226 '34': 'PageDown',
5227 '35': 'End',
5228 '36': 'Home',
5229 '37': 'ArrowLeft',
5230 '38': 'ArrowUp',
5231 '39': 'ArrowRight',
5232 '40': 'ArrowDown',
5233 '45': 'Insert',
5234 '46': 'Delete',
5235 '112': 'F1',
5236 '113': 'F2',
5237 '114': 'F3',
5238 '115': 'F4',
5239 '116': 'F5',
5240 '117': 'F6',
5241 '118': 'F7',
5242 '119': 'F8',
5243 '120': 'F9',
5244 '121': 'F10',
5245 '122': 'F11',
5246 '123': 'F12',
5247 '144': 'NumLock',
5248 '145': 'ScrollLock',
5249 '224': 'Meta'
5250};
5251
5252/**
5253 * @param {object} nativeEvent Native browser event.
5254 * @return {string} Normalized `key` property.
5255 */
5256function getEventKey(nativeEvent) {
5257 if (nativeEvent.key) {
5258 // Normalize inconsistent values reported by browsers due to
5259 // implementations of a working draft specification.
5260
5261 // FireFox implements `key` but returns `MozPrintableKey` for all
5262 // printable characters (normalized to `Unidentified`), ignore it.
5263 var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
5264 if (key !== 'Unidentified') {
5265 return key;
5266 }
5267 }
5268
5269 // Browser does not implement `key`, polyfill as much of it as we can.
5270 if (nativeEvent.type === 'keypress') {
5271 var charCode = getEventCharCode(nativeEvent);
5272
5273 // The enter-key is technically both printable and non-printable and can
5274 // thus be captured by `keypress`, no other non-printable key should.
5275 return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
5276 }
5277 if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
5278 // While user keyboard layout determines the actual meaning of each
5279 // `keyCode` value, almost all function keys have a universal value.
5280 return translateToKey[nativeEvent.keyCode] || 'Unidentified';
5281 }
5282 return '';
5283}
5284
5285/**
5286 * @interface KeyboardEvent
5287 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5288 */
5289var SyntheticKeyboardEvent = SyntheticUIEvent.extend({
5290 key: getEventKey,
5291 location: null,
5292 ctrlKey: null,
5293 shiftKey: null,
5294 altKey: null,
5295 metaKey: null,
5296 repeat: null,
5297 locale: null,
5298 getModifierState: getEventModifierState,
5299 // Legacy Interface
5300 charCode: function (event) {
5301 // `charCode` is the result of a KeyPress event and represents the value of
5302 // the actual printable character.
5303
5304 // KeyPress is deprecated, but its replacement is not yet final and not
5305 // implemented in any major browser. Only KeyPress has charCode.
5306 if (event.type === 'keypress') {
5307 return getEventCharCode(event);
5308 }
5309 return 0;
5310 },
5311 keyCode: function (event) {
5312 // `keyCode` is the result of a KeyDown/Up event and represents the value of
5313 // physical keyboard key.
5314
5315 // The actual meaning of the value depends on the users' keyboard layout
5316 // which cannot be detected. Assuming that it is a US keyboard layout
5317 // provides a surprisingly accurate mapping for US and European users.
5318 // Due to this, it is left to the user to implement at this time.
5319 if (event.type === 'keydown' || event.type === 'keyup') {
5320 return event.keyCode;
5321 }
5322 return 0;
5323 },
5324 which: function (event) {
5325 // `which` is an alias for either `keyCode` or `charCode` depending on the
5326 // type of the event.
5327 if (event.type === 'keypress') {
5328 return getEventCharCode(event);
5329 }
5330 if (event.type === 'keydown' || event.type === 'keyup') {
5331 return event.keyCode;
5332 }
5333 return 0;
5334 }
5335});
5336
5337/**
5338 * @interface DragEvent
5339 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5340 */
5341var SyntheticDragEvent = SyntheticMouseEvent.extend({
5342 dataTransfer: null
5343});
5344
5345/**
5346 * @interface TouchEvent
5347 * @see http://www.w3.org/TR/touch-events/
5348 */
5349var SyntheticTouchEvent = SyntheticUIEvent.extend({
5350 touches: null,
5351 targetTouches: null,
5352 changedTouches: null,
5353 altKey: null,
5354 metaKey: null,
5355 ctrlKey: null,
5356 shiftKey: null,
5357 getModifierState: getEventModifierState
5358});
5359
5360/**
5361 * @interface Event
5362 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
5363 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
5364 */
5365var SyntheticTransitionEvent = SyntheticEvent$1.extend({
5366 propertyName: null,
5367 elapsedTime: null,
5368 pseudoElement: null
5369});
5370
5371/**
5372 * @interface WheelEvent
5373 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5374 */
5375var SyntheticWheelEvent = SyntheticMouseEvent.extend({
5376 deltaX: function (event) {
5377 return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
5378 'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
5379 },
5380 deltaY: function (event) {
5381 return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
5382 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
5383 'wheelDelta' in event ? -event.wheelDelta : 0;
5384 },
5385
5386 deltaZ: null,
5387
5388 // Browsers without "deltaMode" is reporting in raw wheel delta where one
5389 // notch on the scroll is always +/- 120, roughly equivalent to pixels.
5390 // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
5391 // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
5392 deltaMode: null
5393});
5394
5395/**
5396 * Turns
5397 * ['abort', ...]
5398 * into
5399 * eventTypes = {
5400 * 'abort': {
5401 * phasedRegistrationNames: {
5402 * bubbled: 'onAbort',
5403 * captured: 'onAbortCapture',
5404 * },
5405 * dependencies: ['topAbort'],
5406 * },
5407 * ...
5408 * };
5409 * topLevelEventsToDispatchConfig = {
5410 * 'topAbort': { sameConfig }
5411 * };
5412 */
5413var eventTypes$4 = {};
5414var topLevelEventsToDispatchConfig = {};
5415['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) {
5416 var capitalizedEvent = event[0].toUpperCase() + event.slice(1);
5417 var onEvent = 'on' + capitalizedEvent;
5418 var topEvent = 'top' + capitalizedEvent;
5419
5420 var type = {
5421 phasedRegistrationNames: {
5422 bubbled: onEvent,
5423 captured: onEvent + 'Capture'
5424 },
5425 dependencies: [topEvent]
5426 };
5427 eventTypes$4[event] = type;
5428 topLevelEventsToDispatchConfig[topEvent] = type;
5429});
5430
5431// Only used in DEV for exhaustiveness validation.
5432var 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'];
5433
5434var SimpleEventPlugin = {
5435 eventTypes: eventTypes$4,
5436
5437 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
5438 var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
5439 if (!dispatchConfig) {
5440 return null;
5441 }
5442 var EventConstructor = void 0;
5443 switch (topLevelType) {
5444 case 'topKeyPress':
5445 // Firefox creates a keypress event for function keys too. This removes
5446 // the unwanted keypress events. Enter is however both printable and
5447 // non-printable. One would expect Tab to be as well (but it isn't).
5448 if (getEventCharCode(nativeEvent) === 0) {
5449 return null;
5450 }
5451 /* falls through */
5452 case 'topKeyDown':
5453 case 'topKeyUp':
5454 EventConstructor = SyntheticKeyboardEvent;
5455 break;
5456 case 'topBlur':
5457 case 'topFocus':
5458 EventConstructor = SyntheticFocusEvent;
5459 break;
5460 case 'topClick':
5461 // Firefox creates a click event on right mouse clicks. This removes the
5462 // unwanted click events.
5463 if (nativeEvent.button === 2) {
5464 return null;
5465 }
5466 /* falls through */
5467 case 'topDoubleClick':
5468 case 'topMouseDown':
5469 case 'topMouseMove':
5470 case 'topMouseUp':
5471 // TODO: Disabled elements should not respond to mouse events
5472 /* falls through */
5473 case 'topMouseOut':
5474 case 'topMouseOver':
5475 case 'topContextMenu':
5476 EventConstructor = SyntheticMouseEvent;
5477 break;
5478 case 'topDrag':
5479 case 'topDragEnd':
5480 case 'topDragEnter':
5481 case 'topDragExit':
5482 case 'topDragLeave':
5483 case 'topDragOver':
5484 case 'topDragStart':
5485 case 'topDrop':
5486 EventConstructor = SyntheticDragEvent;
5487 break;
5488 case 'topTouchCancel':
5489 case 'topTouchEnd':
5490 case 'topTouchMove':
5491 case 'topTouchStart':
5492 EventConstructor = SyntheticTouchEvent;
5493 break;
5494 case 'topAnimationEnd':
5495 case 'topAnimationIteration':
5496 case 'topAnimationStart':
5497 EventConstructor = SyntheticAnimationEvent;
5498 break;
5499 case 'topTransitionEnd':
5500 EventConstructor = SyntheticTransitionEvent;
5501 break;
5502 case 'topScroll':
5503 EventConstructor = SyntheticUIEvent;
5504 break;
5505 case 'topWheel':
5506 EventConstructor = SyntheticWheelEvent;
5507 break;
5508 case 'topCopy':
5509 case 'topCut':
5510 case 'topPaste':
5511 EventConstructor = SyntheticClipboardEvent;
5512 break;
5513 default:
5514 {
5515 if (knownHTMLTopLevelTypes.indexOf(topLevelType) === -1) {
5516 warning_1(false, 'SimpleEventPlugin: Unhandled event type, `%s`. This warning ' + 'is likely caused by a bug in React. Please file an issue.', topLevelType);
5517 }
5518 }
5519 // HTML Events
5520 // @see http://www.w3.org/TR/html5/index.html#events-0
5521 EventConstructor = SyntheticEvent$1;
5522 break;
5523 }
5524 var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
5525 accumulateTwoPhaseDispatches(event);
5526 return event;
5527 }
5528};
5529
5530setHandleTopLevel(handleTopLevel);
5531
5532/**
5533 * Inject modules for resolving DOM hierarchy and plugin ordering.
5534 */
5535injection.injectEventPluginOrder(DOMEventPluginOrder);
5536injection$1.injectComponentTree(ReactDOMComponentTree);
5537
5538/**
5539 * Some important event plugins included by default (without having to require
5540 * them).
5541 */
5542injection.injectEventPluginsByName({
5543 SimpleEventPlugin: SimpleEventPlugin,
5544 EnterLeaveEventPlugin: EnterLeaveEventPlugin,
5545 ChangeEventPlugin: ChangeEventPlugin,
5546 SelectEventPlugin: SelectEventPlugin,
5547 BeforeInputEventPlugin: BeforeInputEventPlugin
5548});
5549
5550/**
5551 * Copyright (c) 2013-present, Facebook, Inc.
5552 *
5553 * This source code is licensed under the MIT license found in the
5554 * LICENSE file in the root directory of this source tree.
5555 *
5556 */
5557
5558
5559
5560var emptyObject = {};
5561
5562{
5563 Object.freeze(emptyObject);
5564}
5565
5566var emptyObject_1 = emptyObject;
5567
5568var valueStack = [];
5569
5570var fiberStack = void 0;
5571
5572{
5573 fiberStack = [];
5574}
5575
5576var index = -1;
5577
5578function createCursor(defaultValue) {
5579 return {
5580 current: defaultValue
5581 };
5582}
5583
5584
5585
5586function pop(cursor, fiber) {
5587 if (index < 0) {
5588 {
5589 warning_1(false, 'Unexpected pop.');
5590 }
5591 return;
5592 }
5593
5594 {
5595 if (fiber !== fiberStack[index]) {
5596 warning_1(false, 'Unexpected Fiber popped.');
5597 }
5598 }
5599
5600 cursor.current = valueStack[index];
5601
5602 valueStack[index] = null;
5603
5604 {
5605 fiberStack[index] = null;
5606 }
5607
5608 index--;
5609}
5610
5611function push(cursor, value, fiber) {
5612 index++;
5613
5614 valueStack[index] = cursor.current;
5615
5616 {
5617 fiberStack[index] = fiber;
5618 }
5619
5620 cursor.current = value;
5621}
5622
5623function reset$1() {
5624 while (index > -1) {
5625 valueStack[index] = null;
5626
5627 {
5628 fiberStack[index] = null;
5629 }
5630
5631 index--;
5632 }
5633}
5634
5635var enableAsyncSubtreeAPI = true;
5636var enableAsyncSchedulingByDefaultInReactDOM = false;
5637// Exports ReactDOM.createRoot
5638var enableCreateRoot = false;
5639var enableUserTimingAPI = true;
5640
5641// Mutating mode (React DOM, React ART, React Native):
5642var enableMutatingReconciler = true;
5643// Experimental noop mode (currently unused):
5644var enableNoopReconciler = false;
5645// Experimental persistent mode (CS):
5646var enablePersistentReconciler = false;
5647
5648// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
5649var debugRenderPhaseSideEffects = false;
5650
5651// Only used in www builds.
5652
5653// Prefix measurements so that it's possible to filter them.
5654// Longer prefixes are hard to read in DevTools.
5655var reactEmoji = '\u269B';
5656var warningEmoji = '\u26D4';
5657var supportsUserTiming = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function';
5658
5659// Keep track of current fiber so that we know the path to unwind on pause.
5660// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them?
5661var currentFiber = null;
5662// If we're in the middle of user code, which fiber and method is it?
5663// Reusing `currentFiber` would be confusing for this because user code fiber
5664// can change during commit phase too, but we don't need to unwind it (since
5665// lifecycles in the commit phase don't resemble a tree).
5666var currentPhase = null;
5667var currentPhaseFiber = null;
5668// Did lifecycle hook schedule an update? This is often a performance problem,
5669// so we will keep track of it, and include it in the report.
5670// Track commits caused by cascading updates.
5671var isCommitting = false;
5672var hasScheduledUpdateInCurrentCommit = false;
5673var hasScheduledUpdateInCurrentPhase = false;
5674var commitCountInCurrentWorkLoop = 0;
5675var effectCountInCurrentCommit = 0;
5676var isWaitingForCallback = false;
5677// During commits, we only show a measurement once per method name
5678// to avoid stretch the commit phase with measurement overhead.
5679var labelsInCurrentCommit = new Set();
5680
5681var formatMarkName = function (markName) {
5682 return reactEmoji + ' ' + markName;
5683};
5684
5685var formatLabel = function (label, warning) {
5686 var prefix = warning ? warningEmoji + ' ' : reactEmoji + ' ';
5687 var suffix = warning ? ' Warning: ' + warning : '';
5688 return '' + prefix + label + suffix;
5689};
5690
5691var beginMark = function (markName) {
5692 performance.mark(formatMarkName(markName));
5693};
5694
5695var clearMark = function (markName) {
5696 performance.clearMarks(formatMarkName(markName));
5697};
5698
5699var endMark = function (label, markName, warning) {
5700 var formattedMarkName = formatMarkName(markName);
5701 var formattedLabel = formatLabel(label, warning);
5702 try {
5703 performance.measure(formattedLabel, formattedMarkName);
5704 } catch (err) {}
5705 // If previous mark was missing for some reason, this will throw.
5706 // This could only happen if React crashed in an unexpected place earlier.
5707 // Don't pile on with more errors.
5708
5709 // Clear marks immediately to avoid growing buffer.
5710 performance.clearMarks(formattedMarkName);
5711 performance.clearMeasures(formattedLabel);
5712};
5713
5714var getFiberMarkName = function (label, debugID) {
5715 return label + ' (#' + debugID + ')';
5716};
5717
5718var getFiberLabel = function (componentName, isMounted, phase) {
5719 if (phase === null) {
5720 // These are composite component total time measurements.
5721 return componentName + ' [' + (isMounted ? 'update' : 'mount') + ']';
5722 } else {
5723 // Composite component methods.
5724 return componentName + '.' + phase;
5725 }
5726};
5727
5728var beginFiberMark = function (fiber, phase) {
5729 var componentName = getComponentName(fiber) || 'Unknown';
5730 var debugID = fiber._debugID;
5731 var isMounted = fiber.alternate !== null;
5732 var label = getFiberLabel(componentName, isMounted, phase);
5733
5734 if (isCommitting && labelsInCurrentCommit.has(label)) {
5735 // During the commit phase, we don't show duplicate labels because
5736 // there is a fixed overhead for every measurement, and we don't
5737 // want to stretch the commit phase beyond necessary.
5738 return false;
5739 }
5740 labelsInCurrentCommit.add(label);
5741
5742 var markName = getFiberMarkName(label, debugID);
5743 beginMark(markName);
5744 return true;
5745};
5746
5747var clearFiberMark = function (fiber, phase) {
5748 var componentName = getComponentName(fiber) || 'Unknown';
5749 var debugID = fiber._debugID;
5750 var isMounted = fiber.alternate !== null;
5751 var label = getFiberLabel(componentName, isMounted, phase);
5752 var markName = getFiberMarkName(label, debugID);
5753 clearMark(markName);
5754};
5755
5756var endFiberMark = function (fiber, phase, warning) {
5757 var componentName = getComponentName(fiber) || 'Unknown';
5758 var debugID = fiber._debugID;
5759 var isMounted = fiber.alternate !== null;
5760 var label = getFiberLabel(componentName, isMounted, phase);
5761 var markName = getFiberMarkName(label, debugID);
5762 endMark(label, markName, warning);
5763};
5764
5765var shouldIgnoreFiber = function (fiber) {
5766 // Host components should be skipped in the timeline.
5767 // We could check typeof fiber.type, but does this work with RN?
5768 switch (fiber.tag) {
5769 case HostRoot:
5770 case HostComponent:
5771 case HostText:
5772 case HostPortal:
5773 case CallComponent:
5774 case ReturnComponent:
5775 case Fragment:
5776 return true;
5777 default:
5778 return false;
5779 }
5780};
5781
5782var clearPendingPhaseMeasurement = function () {
5783 if (currentPhase !== null && currentPhaseFiber !== null) {
5784 clearFiberMark(currentPhaseFiber, currentPhase);
5785 }
5786 currentPhaseFiber = null;
5787 currentPhase = null;
5788 hasScheduledUpdateInCurrentPhase = false;
5789};
5790
5791var pauseTimers = function () {
5792 // Stops all currently active measurements so that they can be resumed
5793 // if we continue in a later deferred loop from the same unit of work.
5794 var fiber = currentFiber;
5795 while (fiber) {
5796 if (fiber._debugIsCurrentlyTiming) {
5797 endFiberMark(fiber, null, null);
5798 }
5799 fiber = fiber['return'];
5800 }
5801};
5802
5803var resumeTimersRecursively = function (fiber) {
5804 if (fiber['return'] !== null) {
5805 resumeTimersRecursively(fiber['return']);
5806 }
5807 if (fiber._debugIsCurrentlyTiming) {
5808 beginFiberMark(fiber, null);
5809 }
5810};
5811
5812var resumeTimers = function () {
5813 // Resumes all measurements that were active during the last deferred loop.
5814 if (currentFiber !== null) {
5815 resumeTimersRecursively(currentFiber);
5816 }
5817};
5818
5819function recordEffect() {
5820 if (enableUserTimingAPI) {
5821 effectCountInCurrentCommit++;
5822 }
5823}
5824
5825function recordScheduleUpdate() {
5826 if (enableUserTimingAPI) {
5827 if (isCommitting) {
5828 hasScheduledUpdateInCurrentCommit = true;
5829 }
5830 if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') {
5831 hasScheduledUpdateInCurrentPhase = true;
5832 }
5833 }
5834}
5835
5836function startRequestCallbackTimer() {
5837 if (enableUserTimingAPI) {
5838 if (supportsUserTiming && !isWaitingForCallback) {
5839 isWaitingForCallback = true;
5840 beginMark('(Waiting for async callback...)');
5841 }
5842 }
5843}
5844
5845function stopRequestCallbackTimer(didExpire) {
5846 if (enableUserTimingAPI) {
5847 if (supportsUserTiming) {
5848 isWaitingForCallback = false;
5849 var warning = didExpire ? 'React was blocked by main thread' : null;
5850 endMark('(Waiting for async callback...)', '(Waiting for async callback...)', warning);
5851 }
5852 }
5853}
5854
5855function startWorkTimer(fiber) {
5856 if (enableUserTimingAPI) {
5857 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5858 return;
5859 }
5860 // If we pause, this is the fiber to unwind from.
5861 currentFiber = fiber;
5862 if (!beginFiberMark(fiber, null)) {
5863 return;
5864 }
5865 fiber._debugIsCurrentlyTiming = true;
5866 }
5867}
5868
5869function cancelWorkTimer(fiber) {
5870 if (enableUserTimingAPI) {
5871 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5872 return;
5873 }
5874 // Remember we shouldn't complete measurement for this fiber.
5875 // Otherwise flamechart will be deep even for small updates.
5876 fiber._debugIsCurrentlyTiming = false;
5877 clearFiberMark(fiber, null);
5878 }
5879}
5880
5881function stopWorkTimer(fiber) {
5882 if (enableUserTimingAPI) {
5883 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5884 return;
5885 }
5886 // If we pause, its parent is the fiber to unwind from.
5887 currentFiber = fiber['return'];
5888 if (!fiber._debugIsCurrentlyTiming) {
5889 return;
5890 }
5891 fiber._debugIsCurrentlyTiming = false;
5892 endFiberMark(fiber, null, null);
5893 }
5894}
5895
5896function stopFailedWorkTimer(fiber) {
5897 if (enableUserTimingAPI) {
5898 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5899 return;
5900 }
5901 // If we pause, its parent is the fiber to unwind from.
5902 currentFiber = fiber['return'];
5903 if (!fiber._debugIsCurrentlyTiming) {
5904 return;
5905 }
5906 fiber._debugIsCurrentlyTiming = false;
5907 var warning = 'An error was thrown inside this error boundary';
5908 endFiberMark(fiber, null, warning);
5909 }
5910}
5911
5912function startPhaseTimer(fiber, phase) {
5913 if (enableUserTimingAPI) {
5914 if (!supportsUserTiming) {
5915 return;
5916 }
5917 clearPendingPhaseMeasurement();
5918 if (!beginFiberMark(fiber, phase)) {
5919 return;
5920 }
5921 currentPhaseFiber = fiber;
5922 currentPhase = phase;
5923 }
5924}
5925
5926function stopPhaseTimer() {
5927 if (enableUserTimingAPI) {
5928 if (!supportsUserTiming) {
5929 return;
5930 }
5931 if (currentPhase !== null && currentPhaseFiber !== null) {
5932 var warning = hasScheduledUpdateInCurrentPhase ? 'Scheduled a cascading update' : null;
5933 endFiberMark(currentPhaseFiber, currentPhase, warning);
5934 }
5935 currentPhase = null;
5936 currentPhaseFiber = null;
5937 }
5938}
5939
5940function startWorkLoopTimer(nextUnitOfWork) {
5941 if (enableUserTimingAPI) {
5942 currentFiber = nextUnitOfWork;
5943 if (!supportsUserTiming) {
5944 return;
5945 }
5946 commitCountInCurrentWorkLoop = 0;
5947 // This is top level call.
5948 // Any other measurements are performed within.
5949 beginMark('(React Tree Reconciliation)');
5950 // Resume any measurements that were in progress during the last loop.
5951 resumeTimers();
5952 }
5953}
5954
5955function stopWorkLoopTimer(interruptedBy) {
5956 if (enableUserTimingAPI) {
5957 if (!supportsUserTiming) {
5958 return;
5959 }
5960 var warning = null;
5961 if (interruptedBy !== null) {
5962 if (interruptedBy.tag === HostRoot) {
5963 warning = 'A top-level update interrupted the previous render';
5964 } else {
5965 var componentName = getComponentName(interruptedBy) || 'Unknown';
5966 warning = 'An update to ' + componentName + ' interrupted the previous render';
5967 }
5968 } else if (commitCountInCurrentWorkLoop > 1) {
5969 warning = 'There were cascading updates';
5970 }
5971 commitCountInCurrentWorkLoop = 0;
5972 // Pause any measurements until the next loop.
5973 pauseTimers();
5974 endMark('(React Tree Reconciliation)', '(React Tree Reconciliation)', warning);
5975 }
5976}
5977
5978function startCommitTimer() {
5979 if (enableUserTimingAPI) {
5980 if (!supportsUserTiming) {
5981 return;
5982 }
5983 isCommitting = true;
5984 hasScheduledUpdateInCurrentCommit = false;
5985 labelsInCurrentCommit.clear();
5986 beginMark('(Committing Changes)');
5987 }
5988}
5989
5990function stopCommitTimer() {
5991 if (enableUserTimingAPI) {
5992 if (!supportsUserTiming) {
5993 return;
5994 }
5995
5996 var warning = null;
5997 if (hasScheduledUpdateInCurrentCommit) {
5998 warning = 'Lifecycle hook scheduled a cascading update';
5999 } else if (commitCountInCurrentWorkLoop > 0) {
6000 warning = 'Caused by a cascading update in earlier commit';
6001 }
6002 hasScheduledUpdateInCurrentCommit = false;
6003 commitCountInCurrentWorkLoop++;
6004 isCommitting = false;
6005 labelsInCurrentCommit.clear();
6006
6007 endMark('(Committing Changes)', '(Committing Changes)', warning);
6008 }
6009}
6010
6011function startCommitHostEffectsTimer() {
6012 if (enableUserTimingAPI) {
6013 if (!supportsUserTiming) {
6014 return;
6015 }
6016 effectCountInCurrentCommit = 0;
6017 beginMark('(Committing Host Effects)');
6018 }
6019}
6020
6021function stopCommitHostEffectsTimer() {
6022 if (enableUserTimingAPI) {
6023 if (!supportsUserTiming) {
6024 return;
6025 }
6026 var count = effectCountInCurrentCommit;
6027 effectCountInCurrentCommit = 0;
6028 endMark('(Committing Host Effects: ' + count + ' Total)', '(Committing Host Effects)', null);
6029 }
6030}
6031
6032function startCommitLifeCyclesTimer() {
6033 if (enableUserTimingAPI) {
6034 if (!supportsUserTiming) {
6035 return;
6036 }
6037 effectCountInCurrentCommit = 0;
6038 beginMark('(Calling Lifecycle Methods)');
6039 }
6040}
6041
6042function stopCommitLifeCyclesTimer() {
6043 if (enableUserTimingAPI) {
6044 if (!supportsUserTiming) {
6045 return;
6046 }
6047 var count = effectCountInCurrentCommit;
6048 effectCountInCurrentCommit = 0;
6049 endMark('(Calling Lifecycle Methods: ' + count + ' Total)', '(Calling Lifecycle Methods)', null);
6050 }
6051}
6052
6053var warnedAboutMissingGetChildContext = void 0;
6054
6055{
6056 warnedAboutMissingGetChildContext = {};
6057}
6058
6059// A cursor to the current merged context object on the stack.
6060var contextStackCursor = createCursor(emptyObject_1);
6061// A cursor to a boolean indicating whether the context has changed.
6062var didPerformWorkStackCursor = createCursor(false);
6063// Keep track of the previous context object that was on the stack.
6064// We use this to get access to the parent context after we have already
6065// pushed the next context provider, and now need to merge their contexts.
6066var previousContext = emptyObject_1;
6067
6068function getUnmaskedContext(workInProgress) {
6069 var hasOwnContext = isContextProvider(workInProgress);
6070 if (hasOwnContext) {
6071 // If the fiber is a context provider itself, when we read its context
6072 // we have already pushed its own child context on the stack. A context
6073 // provider should not "see" its own child context. Therefore we read the
6074 // previous (parent) context instead for a context provider.
6075 return previousContext;
6076 }
6077 return contextStackCursor.current;
6078}
6079
6080function cacheContext(workInProgress, unmaskedContext, maskedContext) {
6081 var instance = workInProgress.stateNode;
6082 instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
6083 instance.__reactInternalMemoizedMaskedChildContext = maskedContext;
6084}
6085
6086function getMaskedContext(workInProgress, unmaskedContext) {
6087 var type = workInProgress.type;
6088 var contextTypes = type.contextTypes;
6089 if (!contextTypes) {
6090 return emptyObject_1;
6091 }
6092
6093 // Avoid recreating masked context unless unmasked context has changed.
6094 // Failing to do this will result in unnecessary calls to componentWillReceiveProps.
6095 // This may trigger infinite loops if componentWillReceiveProps calls setState.
6096 var instance = workInProgress.stateNode;
6097 if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) {
6098 return instance.__reactInternalMemoizedMaskedChildContext;
6099 }
6100
6101 var context = {};
6102 for (var key in contextTypes) {
6103 context[key] = unmaskedContext[key];
6104 }
6105
6106 {
6107 var name = getComponentName(workInProgress) || 'Unknown';
6108 checkPropTypes_1(contextTypes, context, 'context', name, ReactDebugCurrentFiber.getCurrentFiberStackAddendum);
6109 }
6110
6111 // Cache unmasked context so we can avoid recreating masked context unless necessary.
6112 // Context is created before the class component is instantiated so check for instance.
6113 if (instance) {
6114 cacheContext(workInProgress, unmaskedContext, context);
6115 }
6116
6117 return context;
6118}
6119
6120function hasContextChanged() {
6121 return didPerformWorkStackCursor.current;
6122}
6123
6124function isContextConsumer(fiber) {
6125 return fiber.tag === ClassComponent && fiber.type.contextTypes != null;
6126}
6127
6128function isContextProvider(fiber) {
6129 return fiber.tag === ClassComponent && fiber.type.childContextTypes != null;
6130}
6131
6132function popContextProvider(fiber) {
6133 if (!isContextProvider(fiber)) {
6134 return;
6135 }
6136
6137 pop(didPerformWorkStackCursor, fiber);
6138 pop(contextStackCursor, fiber);
6139}
6140
6141function popTopLevelContextObject(fiber) {
6142 pop(didPerformWorkStackCursor, fiber);
6143 pop(contextStackCursor, fiber);
6144}
6145
6146function pushTopLevelContextObject(fiber, context, didChange) {
6147 !(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;
6148
6149 push(contextStackCursor, context, fiber);
6150 push(didPerformWorkStackCursor, didChange, fiber);
6151}
6152
6153function processChildContext(fiber, parentContext) {
6154 var instance = fiber.stateNode;
6155 var childContextTypes = fiber.type.childContextTypes;
6156
6157 // TODO (bvaughn) Replace this behavior with an invariant() in the future.
6158 // It has only been added in Fiber to match the (unintentional) behavior in Stack.
6159 if (typeof instance.getChildContext !== 'function') {
6160 {
6161 var componentName = getComponentName(fiber) || 'Unknown';
6162
6163 if (!warnedAboutMissingGetChildContext[componentName]) {
6164 warnedAboutMissingGetChildContext[componentName] = true;
6165 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);
6166 }
6167 }
6168 return parentContext;
6169 }
6170
6171 var childContext = void 0;
6172 {
6173 ReactDebugCurrentFiber.setCurrentPhase('getChildContext');
6174 }
6175 startPhaseTimer(fiber, 'getChildContext');
6176 childContext = instance.getChildContext();
6177 stopPhaseTimer();
6178 {
6179 ReactDebugCurrentFiber.setCurrentPhase(null);
6180 }
6181 for (var contextKey in childContext) {
6182 !(contextKey in childContextTypes) ? invariant_1(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', getComponentName(fiber) || 'Unknown', contextKey) : void 0;
6183 }
6184 {
6185 var name = getComponentName(fiber) || 'Unknown';
6186 checkPropTypes_1(childContextTypes, childContext, 'child context', name,
6187 // In practice, there is one case in which we won't get a stack. It's when
6188 // somebody calls unstable_renderSubtreeIntoContainer() and we process
6189 // context from the parent component instance. The stack will be missing
6190 // because it's outside of the reconciliation, and so the pointer has not
6191 // been set. This is rare and doesn't matter. We'll also remove that API.
6192 ReactDebugCurrentFiber.getCurrentFiberStackAddendum);
6193 }
6194
6195 return _assign({}, parentContext, childContext);
6196}
6197
6198function pushContextProvider(workInProgress) {
6199 if (!isContextProvider(workInProgress)) {
6200 return false;
6201 }
6202
6203 var instance = workInProgress.stateNode;
6204 // We push the context as early as possible to ensure stack integrity.
6205 // If the instance does not exist yet, we will push null at first,
6206 // and replace it on the stack later when invalidating the context.
6207 var memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyObject_1;
6208
6209 // Remember the parent context so we can merge with it later.
6210 // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates.
6211 previousContext = contextStackCursor.current;
6212 push(contextStackCursor, memoizedMergedChildContext, workInProgress);
6213 push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress);
6214
6215 return true;
6216}
6217
6218function invalidateContextProvider(workInProgress, didChange) {
6219 var instance = workInProgress.stateNode;
6220 !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;
6221
6222 if (didChange) {
6223 // Merge parent and own context.
6224 // Skip this if we're not updating due to sCU.
6225 // This avoids unnecessarily recomputing memoized values.
6226 var mergedContext = processChildContext(workInProgress, previousContext);
6227 instance.__reactInternalMemoizedMergedChildContext = mergedContext;
6228
6229 // Replace the old (or empty) context with the new one.
6230 // It is important to unwind the context in the reverse order.
6231 pop(didPerformWorkStackCursor, workInProgress);
6232 pop(contextStackCursor, workInProgress);
6233 // Now push the new context and mark that it has changed.
6234 push(contextStackCursor, mergedContext, workInProgress);
6235 push(didPerformWorkStackCursor, didChange, workInProgress);
6236 } else {
6237 pop(didPerformWorkStackCursor, workInProgress);
6238 push(didPerformWorkStackCursor, didChange, workInProgress);
6239 }
6240}
6241
6242function resetContext() {
6243 previousContext = emptyObject_1;
6244 contextStackCursor.current = emptyObject_1;
6245 didPerformWorkStackCursor.current = false;
6246}
6247
6248function findCurrentUnmaskedContext(fiber) {
6249 // Currently this is only used with renderSubtreeIntoContainer; not sure if it
6250 // makes sense elsewhere
6251 !(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;
6252
6253 var node = fiber;
6254 while (node.tag !== HostRoot) {
6255 if (isContextProvider(node)) {
6256 return node.stateNode.__reactInternalMemoizedMergedChildContext;
6257 }
6258 var parent = node['return'];
6259 !parent ? invariant_1(false, 'Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue.') : void 0;
6260 node = parent;
6261 }
6262 return node.stateNode.context;
6263}
6264
6265var NoWork = 0; // TODO: Use an opaque type once ESLint et al support the syntax
6266
6267var Sync = 1;
6268var Never = 2147483647; // Max int32: Math.pow(2, 31) - 1
6269
6270var UNIT_SIZE = 10;
6271var MAGIC_NUMBER_OFFSET = 2;
6272
6273// 1 unit of expiration time represents 10ms.
6274function msToExpirationTime(ms) {
6275 // Always add an offset so that we don't clash with the magic number for NoWork.
6276 return (ms / UNIT_SIZE | 0) + MAGIC_NUMBER_OFFSET;
6277}
6278
6279function expirationTimeToMs(expirationTime) {
6280 return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
6281}
6282
6283function ceiling(num, precision) {
6284 return ((num / precision | 0) + 1) * precision;
6285}
6286
6287function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) {
6288 return ceiling(currentTime + expirationInMs / UNIT_SIZE, bucketSizeMs / UNIT_SIZE);
6289}
6290
6291var NoContext = 0;
6292var AsyncUpdates = 1;
6293
6294var hasBadMapPolyfill = void 0;
6295
6296{
6297 hasBadMapPolyfill = false;
6298 try {
6299 var nonExtensibleObject = Object.preventExtensions({});
6300 var testMap = new Map([[nonExtensibleObject, null]]);
6301 var testSet = new Set([nonExtensibleObject]);
6302 // This is necessary for Rollup to not consider these unused.
6303 // https://github.com/rollup/rollup/issues/1771
6304 // TODO: we can remove these if Rollup fixes the bug.
6305 testMap.set(0, 0);
6306 testSet.add(0);
6307 } catch (e) {
6308 // TODO: Consider warning about bad polyfills
6309 hasBadMapPolyfill = true;
6310 }
6311}
6312
6313// A Fiber is work on a Component that needs to be done or was done. There can
6314// be more than one per component.
6315
6316
6317var debugCounter = void 0;
6318
6319{
6320 debugCounter = 1;
6321}
6322
6323function FiberNode(tag, pendingProps, key, internalContextTag) {
6324 // Instance
6325 this.tag = tag;
6326 this.key = key;
6327 this.type = null;
6328 this.stateNode = null;
6329
6330 // Fiber
6331 this['return'] = null;
6332 this.child = null;
6333 this.sibling = null;
6334 this.index = 0;
6335
6336 this.ref = null;
6337
6338 this.pendingProps = pendingProps;
6339 this.memoizedProps = null;
6340 this.updateQueue = null;
6341 this.memoizedState = null;
6342
6343 this.internalContextTag = internalContextTag;
6344
6345 // Effects
6346 this.effectTag = NoEffect;
6347 this.nextEffect = null;
6348
6349 this.firstEffect = null;
6350 this.lastEffect = null;
6351
6352 this.expirationTime = NoWork;
6353
6354 this.alternate = null;
6355
6356 {
6357 this._debugID = debugCounter++;
6358 this._debugSource = null;
6359 this._debugOwner = null;
6360 this._debugIsCurrentlyTiming = false;
6361 if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
6362 Object.preventExtensions(this);
6363 }
6364 }
6365}
6366
6367// This is a constructor function, rather than a POJO constructor, still
6368// please ensure we do the following:
6369// 1) Nobody should add any instance methods on this. Instance methods can be
6370// more difficult to predict when they get optimized and they are almost
6371// never inlined properly in static compilers.
6372// 2) Nobody should rely on `instanceof Fiber` for type testing. We should
6373// always know when it is a fiber.
6374// 3) We might want to experiment with using numeric keys since they are easier
6375// to optimize in a non-JIT environment.
6376// 4) We can easily go from a constructor to a createFiber object literal if that
6377// is faster.
6378// 5) It should be easy to port this to a C struct and keep a C implementation
6379// compatible.
6380var createFiber = function (tag, pendingProps, key, internalContextTag) {
6381 // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
6382 return new FiberNode(tag, pendingProps, key, internalContextTag);
6383};
6384
6385function shouldConstruct(Component) {
6386 return !!(Component.prototype && Component.prototype.isReactComponent);
6387}
6388
6389// This is used to create an alternate fiber to do work on.
6390function createWorkInProgress(current, pendingProps, expirationTime) {
6391 var workInProgress = current.alternate;
6392 if (workInProgress === null) {
6393 // We use a double buffering pooling technique because we know that we'll
6394 // only ever need at most two versions of a tree. We pool the "other" unused
6395 // node that we're free to reuse. This is lazily created to avoid allocating
6396 // extra objects for things that are never updated. It also allow us to
6397 // reclaim the extra memory if needed.
6398 workInProgress = createFiber(current.tag, pendingProps, current.key, current.internalContextTag);
6399 workInProgress.type = current.type;
6400 workInProgress.stateNode = current.stateNode;
6401
6402 {
6403 // DEV-only fields
6404 workInProgress._debugID = current._debugID;
6405 workInProgress._debugSource = current._debugSource;
6406 workInProgress._debugOwner = current._debugOwner;
6407 }
6408
6409 workInProgress.alternate = current;
6410 current.alternate = workInProgress;
6411 } else {
6412 workInProgress.pendingProps = pendingProps;
6413
6414 // We already have an alternate.
6415 // Reset the effect tag.
6416 workInProgress.effectTag = NoEffect;
6417
6418 // The effect list is no longer valid.
6419 workInProgress.nextEffect = null;
6420 workInProgress.firstEffect = null;
6421 workInProgress.lastEffect = null;
6422 }
6423
6424 workInProgress.expirationTime = expirationTime;
6425
6426 workInProgress.child = current.child;
6427 workInProgress.memoizedProps = current.memoizedProps;
6428 workInProgress.memoizedState = current.memoizedState;
6429 workInProgress.updateQueue = current.updateQueue;
6430
6431 // These will be overridden during the parent's reconciliation
6432 workInProgress.sibling = current.sibling;
6433 workInProgress.index = current.index;
6434 workInProgress.ref = current.ref;
6435
6436 return workInProgress;
6437}
6438
6439function createHostRootFiber(isAsync) {
6440 var internalContextTag = isAsync ? AsyncUpdates : NoContext;
6441 return createFiber(HostRoot, null, null, internalContextTag);
6442}
6443
6444function createFiberFromElement(element, internalContextTag, expirationTime) {
6445 var owner = null;
6446 {
6447 owner = element._owner;
6448 }
6449
6450 var fiber = void 0;
6451 var type = element.type;
6452 var key = element.key;
6453 var pendingProps = element.props;
6454 if (typeof type === 'function') {
6455 fiber = shouldConstruct(type) ? createFiber(ClassComponent, pendingProps, key, internalContextTag) : createFiber(IndeterminateComponent, pendingProps, key, internalContextTag);
6456 fiber.type = type;
6457 } else if (typeof type === 'string') {
6458 fiber = createFiber(HostComponent, pendingProps, key, internalContextTag);
6459 fiber.type = type;
6460 } else {
6461 switch (type) {
6462 case REACT_FRAGMENT_TYPE:
6463 return createFiberFromFragment(pendingProps.children, internalContextTag, expirationTime, key);
6464 case REACT_CALL_TYPE:
6465 fiber = createFiber(CallComponent, pendingProps, key, internalContextTag);
6466 fiber.type = REACT_CALL_TYPE;
6467 break;
6468 case REACT_RETURN_TYPE:
6469 fiber = createFiber(ReturnComponent, pendingProps, key, internalContextTag);
6470 fiber.type = REACT_RETURN_TYPE;
6471 break;
6472 default:
6473 {
6474 if (typeof type === 'object' && type !== null && typeof type.tag === 'number') {
6475 // Currently assumed to be a continuation and therefore is a
6476 // fiber already.
6477 // TODO: The yield system is currently broken for updates in some
6478 // cases. The reified yield stores a fiber, but we don't know which
6479 // fiber that is; the current or a workInProgress? When the
6480 // continuation gets rendered here we don't know if we can reuse that
6481 // fiber or if we need to clone it. There is probably a clever way to
6482 // restructure this.
6483 fiber = type;
6484 fiber.pendingProps = pendingProps;
6485 } else {
6486 var info = '';
6487 {
6488 if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
6489 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.';
6490 }
6491 var ownerName = owner ? getComponentName(owner) : null;
6492 if (ownerName) {
6493 info += '\n\nCheck the render method of `' + ownerName + '`.';
6494 }
6495 }
6496 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);
6497 }
6498 }
6499 }
6500 }
6501
6502 {
6503 fiber._debugSource = element._source;
6504 fiber._debugOwner = element._owner;
6505 }
6506
6507 fiber.expirationTime = expirationTime;
6508
6509 return fiber;
6510}
6511
6512function createFiberFromFragment(elements, internalContextTag, expirationTime, key) {
6513 var fiber = createFiber(Fragment, elements, key, internalContextTag);
6514 fiber.expirationTime = expirationTime;
6515 return fiber;
6516}
6517
6518function createFiberFromText(content, internalContextTag, expirationTime) {
6519 var fiber = createFiber(HostText, content, null, internalContextTag);
6520 fiber.expirationTime = expirationTime;
6521 return fiber;
6522}
6523
6524function createFiberFromHostInstanceForDeletion() {
6525 var fiber = createFiber(HostComponent, null, null, NoContext);
6526 fiber.type = 'DELETED';
6527 return fiber;
6528}
6529
6530function createFiberFromPortal(portal, internalContextTag, expirationTime) {
6531 var pendingProps = portal.children !== null ? portal.children : [];
6532 var fiber = createFiber(HostPortal, pendingProps, portal.key, internalContextTag);
6533 fiber.expirationTime = expirationTime;
6534 fiber.stateNode = {
6535 containerInfo: portal.containerInfo,
6536 pendingChildren: null, // Used by persistent updates
6537 implementation: portal.implementation
6538 };
6539 return fiber;
6540}
6541
6542// TODO: This should be lifted into the renderer.
6543
6544
6545function createFiberRoot(containerInfo, isAsync, hydrate) {
6546 // Cyclic construction. This cheats the type system right now because
6547 // stateNode is any.
6548 var uninitializedFiber = createHostRootFiber(isAsync);
6549 var root = {
6550 current: uninitializedFiber,
6551 containerInfo: containerInfo,
6552 pendingChildren: null,
6553 remainingExpirationTime: NoWork,
6554 isReadyForCommit: false,
6555 finishedWork: null,
6556 context: null,
6557 pendingContext: null,
6558 hydrate: hydrate,
6559 firstBatch: null,
6560 nextScheduledRoot: null
6561 };
6562 uninitializedFiber.stateNode = root;
6563 return root;
6564}
6565
6566var onCommitFiberRoot = null;
6567var onCommitFiberUnmount = null;
6568var hasLoggedError = false;
6569
6570function catchErrors(fn) {
6571 return function (arg) {
6572 try {
6573 return fn(arg);
6574 } catch (err) {
6575 if (true && !hasLoggedError) {
6576 hasLoggedError = true;
6577 warning_1(false, 'React DevTools encountered an error: %s', err);
6578 }
6579 }
6580 };
6581}
6582
6583function injectInternals(internals) {
6584 if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
6585 // No DevTools
6586 return false;
6587 }
6588 var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;
6589 if (hook.isDisabled) {
6590 // This isn't a real property on the hook, but it can be set to opt out
6591 // of DevTools integration and associated warnings and logs.
6592 // https://github.com/facebook/react/issues/3877
6593 return true;
6594 }
6595 if (!hook.supportsFiber) {
6596 {
6597 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');
6598 }
6599 // DevTools exists, even though it doesn't support Fiber.
6600 return true;
6601 }
6602 try {
6603 var rendererID = hook.inject(internals);
6604 // We have successfully injected, so now it is safe to set up hooks.
6605 onCommitFiberRoot = catchErrors(function (root) {
6606 return hook.onCommitFiberRoot(rendererID, root);
6607 });
6608 onCommitFiberUnmount = catchErrors(function (fiber) {
6609 return hook.onCommitFiberUnmount(rendererID, fiber);
6610 });
6611 } catch (err) {
6612 // Catch all errors because it is unsafe to throw during initialization.
6613 {
6614 warning_1(false, 'React DevTools encountered an error: %s.', err);
6615 }
6616 }
6617 // DevTools exists
6618 return true;
6619}
6620
6621function onCommitRoot(root) {
6622 if (typeof onCommitFiberRoot === 'function') {
6623 onCommitFiberRoot(root);
6624 }
6625}
6626
6627function onCommitUnmount(fiber) {
6628 if (typeof onCommitFiberUnmount === 'function') {
6629 onCommitFiberUnmount(fiber);
6630 }
6631}
6632
6633var didWarnUpdateInsideUpdate = void 0;
6634
6635{
6636 didWarnUpdateInsideUpdate = false;
6637}
6638
6639// Callbacks are not validated until invocation
6640
6641
6642// Singly linked-list of updates. When an update is scheduled, it is added to
6643// the queue of the current fiber and the work-in-progress fiber. The two queues
6644// are separate but they share a persistent structure.
6645//
6646// During reconciliation, updates are removed from the work-in-progress fiber,
6647// but they remain on the current fiber. That ensures that if a work-in-progress
6648// is aborted, the aborted updates are recovered by cloning from current.
6649//
6650// The work-in-progress queue is always a subset of the current queue.
6651//
6652// When the tree is committed, the work-in-progress becomes the current.
6653
6654
6655function createUpdateQueue(baseState) {
6656 var queue = {
6657 baseState: baseState,
6658 expirationTime: NoWork,
6659 first: null,
6660 last: null,
6661 callbackList: null,
6662 hasForceUpdate: false,
6663 isInitialized: false
6664 };
6665 {
6666 queue.isProcessing = false;
6667 }
6668 return queue;
6669}
6670
6671function insertUpdateIntoQueue(queue, update) {
6672 // Append the update to the end of the list.
6673 if (queue.last === null) {
6674 // Queue is empty
6675 queue.first = queue.last = update;
6676 } else {
6677 queue.last.next = update;
6678 queue.last = update;
6679 }
6680 if (queue.expirationTime === NoWork || queue.expirationTime > update.expirationTime) {
6681 queue.expirationTime = update.expirationTime;
6682 }
6683}
6684
6685function insertUpdateIntoFiber(fiber, update) {
6686 // We'll have at least one and at most two distinct update queues.
6687 var alternateFiber = fiber.alternate;
6688 var queue1 = fiber.updateQueue;
6689 if (queue1 === null) {
6690 // TODO: We don't know what the base state will be until we begin work.
6691 // It depends on which fiber is the next current. Initialize with an empty
6692 // base state, then set to the memoizedState when rendering. Not super
6693 // happy with this approach.
6694 queue1 = fiber.updateQueue = createUpdateQueue(null);
6695 }
6696
6697 var queue2 = void 0;
6698 if (alternateFiber !== null) {
6699 queue2 = alternateFiber.updateQueue;
6700 if (queue2 === null) {
6701 queue2 = alternateFiber.updateQueue = createUpdateQueue(null);
6702 }
6703 } else {
6704 queue2 = null;
6705 }
6706 queue2 = queue2 !== queue1 ? queue2 : null;
6707
6708 // Warn if an update is scheduled from inside an updater function.
6709 {
6710 if ((queue1.isProcessing || queue2 !== null && queue2.isProcessing) && !didWarnUpdateInsideUpdate) {
6711 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.');
6712 didWarnUpdateInsideUpdate = true;
6713 }
6714 }
6715
6716 // If there's only one queue, add the update to that queue and exit.
6717 if (queue2 === null) {
6718 insertUpdateIntoQueue(queue1, update);
6719 return;
6720 }
6721
6722 // If either queue is empty, we need to add to both queues.
6723 if (queue1.last === null || queue2.last === null) {
6724 insertUpdateIntoQueue(queue1, update);
6725 insertUpdateIntoQueue(queue2, update);
6726 return;
6727 }
6728
6729 // If both lists are not empty, the last update is the same for both lists
6730 // because of structural sharing. So, we should only append to one of
6731 // the lists.
6732 insertUpdateIntoQueue(queue1, update);
6733 // But we still need to update the `last` pointer of queue2.
6734 queue2.last = update;
6735}
6736
6737function getUpdateExpirationTime(fiber) {
6738 if (fiber.tag !== ClassComponent && fiber.tag !== HostRoot) {
6739 return NoWork;
6740 }
6741 var updateQueue = fiber.updateQueue;
6742 if (updateQueue === null) {
6743 return NoWork;
6744 }
6745 return updateQueue.expirationTime;
6746}
6747
6748function getStateFromUpdate(update, instance, prevState, props) {
6749 var partialState = update.partialState;
6750 if (typeof partialState === 'function') {
6751 var updateFn = partialState;
6752
6753 // Invoke setState callback an extra time to help detect side-effects.
6754 if (debugRenderPhaseSideEffects) {
6755 updateFn.call(instance, prevState, props);
6756 }
6757
6758 return updateFn.call(instance, prevState, props);
6759 } else {
6760 return partialState;
6761 }
6762}
6763
6764function processUpdateQueue(current, workInProgress, queue, instance, props, renderExpirationTime) {
6765 if (current !== null && current.updateQueue === queue) {
6766 // We need to create a work-in-progress queue, by cloning the current queue.
6767 var currentQueue = queue;
6768 queue = workInProgress.updateQueue = {
6769 baseState: currentQueue.baseState,
6770 expirationTime: currentQueue.expirationTime,
6771 first: currentQueue.first,
6772 last: currentQueue.last,
6773 isInitialized: currentQueue.isInitialized,
6774 // These fields are no longer valid because they were already committed.
6775 // Reset them.
6776 callbackList: null,
6777 hasForceUpdate: false
6778 };
6779 }
6780
6781 {
6782 // Set this flag so we can warn if setState is called inside the update
6783 // function of another setState.
6784 queue.isProcessing = true;
6785 }
6786
6787 // Reset the remaining expiration time. If we skip over any updates, we'll
6788 // increase this accordingly.
6789 queue.expirationTime = NoWork;
6790
6791 // TODO: We don't know what the base state will be until we begin work.
6792 // It depends on which fiber is the next current. Initialize with an empty
6793 // base state, then set to the memoizedState when rendering. Not super
6794 // happy with this approach.
6795 var state = void 0;
6796 if (queue.isInitialized) {
6797 state = queue.baseState;
6798 } else {
6799 state = queue.baseState = workInProgress.memoizedState;
6800 queue.isInitialized = true;
6801 }
6802 var dontMutatePrevState = true;
6803 var update = queue.first;
6804 var didSkip = false;
6805 while (update !== null) {
6806 var updateExpirationTime = update.expirationTime;
6807 if (updateExpirationTime > renderExpirationTime) {
6808 // This update does not have sufficient priority. Skip it.
6809 var remainingExpirationTime = queue.expirationTime;
6810 if (remainingExpirationTime === NoWork || remainingExpirationTime > updateExpirationTime) {
6811 // Update the remaining expiration time.
6812 queue.expirationTime = updateExpirationTime;
6813 }
6814 if (!didSkip) {
6815 didSkip = true;
6816 queue.baseState = state;
6817 }
6818 // Continue to the next update.
6819 update = update.next;
6820 continue;
6821 }
6822
6823 // This update does have sufficient priority.
6824
6825 // If no previous updates were skipped, drop this update from the queue by
6826 // advancing the head of the list.
6827 if (!didSkip) {
6828 queue.first = update.next;
6829 if (queue.first === null) {
6830 queue.last = null;
6831 }
6832 }
6833
6834 // Process the update
6835 var _partialState = void 0;
6836 if (update.isReplace) {
6837 state = getStateFromUpdate(update, instance, state, props);
6838 dontMutatePrevState = true;
6839 } else {
6840 _partialState = getStateFromUpdate(update, instance, state, props);
6841 if (_partialState) {
6842 if (dontMutatePrevState) {
6843 // $FlowFixMe: Idk how to type this properly.
6844 state = _assign({}, state, _partialState);
6845 } else {
6846 state = _assign(state, _partialState);
6847 }
6848 dontMutatePrevState = false;
6849 }
6850 }
6851 if (update.isForced) {
6852 queue.hasForceUpdate = true;
6853 }
6854 if (update.callback !== null) {
6855 // Append to list of callbacks.
6856 var _callbackList = queue.callbackList;
6857 if (_callbackList === null) {
6858 _callbackList = queue.callbackList = [];
6859 }
6860 _callbackList.push(update);
6861 }
6862 update = update.next;
6863 }
6864
6865 if (queue.callbackList !== null) {
6866 workInProgress.effectTag |= Callback;
6867 } else if (queue.first === null && !queue.hasForceUpdate) {
6868 // The queue is empty. We can reset it.
6869 workInProgress.updateQueue = null;
6870 }
6871
6872 if (!didSkip) {
6873 didSkip = true;
6874 queue.baseState = state;
6875 }
6876
6877 {
6878 // No longer processing.
6879 queue.isProcessing = false;
6880 }
6881
6882 return state;
6883}
6884
6885function commitCallbacks(queue, context) {
6886 var callbackList = queue.callbackList;
6887 if (callbackList === null) {
6888 return;
6889 }
6890 // Set the list to null to make sure they don't get called more than once.
6891 queue.callbackList = null;
6892 for (var i = 0; i < callbackList.length; i++) {
6893 var update = callbackList[i];
6894 var _callback = update.callback;
6895 // This update might be processed again. Clear the callback so it's only
6896 // called once.
6897 update.callback = null;
6898 !(typeof _callback === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback) : void 0;
6899 _callback.call(context);
6900 }
6901}
6902
6903var fakeInternalInstance = {};
6904var isArray = Array.isArray;
6905
6906var didWarnAboutStateAssignmentForComponent = void 0;
6907var warnOnInvalidCallback$1 = void 0;
6908
6909{
6910 didWarnAboutStateAssignmentForComponent = {};
6911
6912 warnOnInvalidCallback$1 = function (callback, callerName) {
6913 warning_1(callback === null || typeof callback === 'function', '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
6914 };
6915
6916 // This is so gross but it's at least non-critical and can be removed if
6917 // it causes problems. This is meant to give a nicer error message for
6918 // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component,
6919 // ...)) which otherwise throws a "_processChildContext is not a function"
6920 // exception.
6921 Object.defineProperty(fakeInternalInstance, '_processChildContext', {
6922 enumerable: false,
6923 value: function () {
6924 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).');
6925 }
6926 });
6927 Object.freeze(fakeInternalInstance);
6928}
6929
6930var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState) {
6931 // Class component state updater
6932 var updater = {
6933 isMounted: isMounted,
6934 enqueueSetState: function (instance, partialState, callback) {
6935 var fiber = get(instance);
6936 callback = callback === undefined ? null : callback;
6937 {
6938 warnOnInvalidCallback$1(callback, 'setState');
6939 }
6940 var expirationTime = computeExpirationForFiber(fiber);
6941 var update = {
6942 expirationTime: expirationTime,
6943 partialState: partialState,
6944 callback: callback,
6945 isReplace: false,
6946 isForced: false,
6947 nextCallback: null,
6948 next: null
6949 };
6950 insertUpdateIntoFiber(fiber, update);
6951 scheduleWork(fiber, expirationTime);
6952 },
6953 enqueueReplaceState: function (instance, state, callback) {
6954 var fiber = get(instance);
6955 callback = callback === undefined ? null : callback;
6956 {
6957 warnOnInvalidCallback$1(callback, 'replaceState');
6958 }
6959 var expirationTime = computeExpirationForFiber(fiber);
6960 var update = {
6961 expirationTime: expirationTime,
6962 partialState: state,
6963 callback: callback,
6964 isReplace: true,
6965 isForced: false,
6966 nextCallback: null,
6967 next: null
6968 };
6969 insertUpdateIntoFiber(fiber, update);
6970 scheduleWork(fiber, expirationTime);
6971 },
6972 enqueueForceUpdate: function (instance, callback) {
6973 var fiber = get(instance);
6974 callback = callback === undefined ? null : callback;
6975 {
6976 warnOnInvalidCallback$1(callback, 'forceUpdate');
6977 }
6978 var expirationTime = computeExpirationForFiber(fiber);
6979 var update = {
6980 expirationTime: expirationTime,
6981 partialState: null,
6982 callback: callback,
6983 isReplace: false,
6984 isForced: true,
6985 nextCallback: null,
6986 next: null
6987 };
6988 insertUpdateIntoFiber(fiber, update);
6989 scheduleWork(fiber, expirationTime);
6990 }
6991 };
6992
6993 function checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext) {
6994 if (oldProps === null || workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate) {
6995 // If the workInProgress already has an Update effect, return true
6996 return true;
6997 }
6998
6999 var instance = workInProgress.stateNode;
7000 var type = workInProgress.type;
7001 if (typeof instance.shouldComponentUpdate === 'function') {
7002 startPhaseTimer(workInProgress, 'shouldComponentUpdate');
7003 var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, newContext);
7004 stopPhaseTimer();
7005
7006 // Simulate an async bailout/interruption by invoking lifecycle twice.
7007 if (debugRenderPhaseSideEffects) {
7008 instance.shouldComponentUpdate(newProps, newState, newContext);
7009 }
7010
7011 {
7012 warning_1(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentName(workInProgress) || 'Unknown');
7013 }
7014
7015 return shouldUpdate;
7016 }
7017
7018 if (type.prototype && type.prototype.isPureReactComponent) {
7019 return !shallowEqual_1(oldProps, newProps) || !shallowEqual_1(oldState, newState);
7020 }
7021
7022 return true;
7023 }
7024
7025 function checkClassInstance(workInProgress) {
7026 var instance = workInProgress.stateNode;
7027 var type = workInProgress.type;
7028 {
7029 var name = getComponentName(workInProgress);
7030 var renderPresent = instance.render;
7031
7032 if (!renderPresent) {
7033 if (type.prototype && typeof type.prototype.render === 'function') {
7034 warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name);
7035 } else {
7036 warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name);
7037 }
7038 }
7039
7040 var noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state;
7041 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);
7042 var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved;
7043 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);
7044 var noInstancePropTypes = !instance.propTypes;
7045 warning_1(noInstancePropTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name);
7046 var noInstanceContextTypes = !instance.contextTypes;
7047 warning_1(noInstanceContextTypes, 'contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name);
7048 var noComponentShouldUpdate = typeof instance.componentShouldUpdate !== 'function';
7049 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);
7050 if (type.prototype && type.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') {
7051 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');
7052 }
7053 var noComponentDidUnmount = typeof instance.componentDidUnmount !== 'function';
7054 warning_1(noComponentDidUnmount, '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name);
7055 var noComponentDidReceiveProps = typeof instance.componentDidReceiveProps !== 'function';
7056 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);
7057 var noComponentWillRecieveProps = typeof instance.componentWillRecieveProps !== 'function';
7058 warning_1(noComponentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name);
7059 var hasMutatedProps = instance.props !== workInProgress.pendingProps;
7060 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);
7061 var noInstanceDefaultProps = !instance.defaultProps;
7062 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);
7063 }
7064
7065 var state = instance.state;
7066 if (state && (typeof state !== 'object' || isArray(state))) {
7067 warning_1(false, '%s.state: must be set to an object or null', getComponentName(workInProgress));
7068 }
7069 if (typeof instance.getChildContext === 'function') {
7070 warning_1(typeof workInProgress.type.childContextTypes === 'object', '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', getComponentName(workInProgress));
7071 }
7072 }
7073
7074 function resetInputPointers(workInProgress, instance) {
7075 instance.props = workInProgress.memoizedProps;
7076 instance.state = workInProgress.memoizedState;
7077 }
7078
7079 function adoptClassInstance(workInProgress, instance) {
7080 instance.updater = updater;
7081 workInProgress.stateNode = instance;
7082 // The instance needs access to the fiber so that it can schedule updates
7083 set(instance, workInProgress);
7084 {
7085 instance._reactInternalInstance = fakeInternalInstance;
7086 }
7087 }
7088
7089 function constructClassInstance(workInProgress, props) {
7090 var ctor = workInProgress.type;
7091 var unmaskedContext = getUnmaskedContext(workInProgress);
7092 var needsContext = isContextConsumer(workInProgress);
7093 var context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject_1;
7094 var instance = new ctor(props, context);
7095 adoptClassInstance(workInProgress, instance);
7096
7097 // Cache unmasked context so we can avoid recreating masked context unless necessary.
7098 // ReactFiberContext usually updates this cache but can't for newly-created instances.
7099 if (needsContext) {
7100 cacheContext(workInProgress, unmaskedContext, context);
7101 }
7102
7103 return instance;
7104 }
7105
7106 function callComponentWillMount(workInProgress, instance) {
7107 startPhaseTimer(workInProgress, 'componentWillMount');
7108 var oldState = instance.state;
7109 instance.componentWillMount();
7110 stopPhaseTimer();
7111
7112 if (oldState !== instance.state) {
7113 {
7114 warning_1(false, '%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentName(workInProgress));
7115 }
7116 updater.enqueueReplaceState(instance, instance.state, null);
7117 }
7118 }
7119
7120 function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) {
7121 startPhaseTimer(workInProgress, 'componentWillReceiveProps');
7122 var oldState = instance.state;
7123 instance.componentWillReceiveProps(newProps, newContext);
7124 stopPhaseTimer();
7125
7126 // Simulate an async bailout/interruption by invoking lifecycle twice.
7127 if (debugRenderPhaseSideEffects) {
7128 instance.componentWillReceiveProps(newProps, newContext);
7129 }
7130
7131 if (instance.state !== oldState) {
7132 {
7133 var componentName = getComponentName(workInProgress) || 'Component';
7134 if (!didWarnAboutStateAssignmentForComponent[componentName]) {
7135 warning_1(false, '%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', componentName);
7136 didWarnAboutStateAssignmentForComponent[componentName] = true;
7137 }
7138 }
7139 updater.enqueueReplaceState(instance, instance.state, null);
7140 }
7141 }
7142
7143 // Invokes the mount life-cycles on a previously never rendered instance.
7144 function mountClassInstance(workInProgress, renderExpirationTime) {
7145 var current = workInProgress.alternate;
7146
7147 {
7148 checkClassInstance(workInProgress);
7149 }
7150
7151 var instance = workInProgress.stateNode;
7152 var state = instance.state || null;
7153 var props = workInProgress.pendingProps;
7154 var unmaskedContext = getUnmaskedContext(workInProgress);
7155
7156 instance.props = props;
7157 instance.state = workInProgress.memoizedState = state;
7158 instance.refs = emptyObject_1;
7159 instance.context = getMaskedContext(workInProgress, unmaskedContext);
7160
7161 if (enableAsyncSubtreeAPI && workInProgress.type != null && workInProgress.type.prototype != null && workInProgress.type.prototype.unstable_isAsyncReactComponent === true) {
7162 workInProgress.internalContextTag |= AsyncUpdates;
7163 }
7164
7165 if (typeof instance.componentWillMount === 'function') {
7166 callComponentWillMount(workInProgress, instance);
7167 // If we had additional state updates during this life-cycle, let's
7168 // process them now.
7169 var updateQueue = workInProgress.updateQueue;
7170 if (updateQueue !== null) {
7171 instance.state = processUpdateQueue(current, workInProgress, updateQueue, instance, props, renderExpirationTime);
7172 }
7173 }
7174 if (typeof instance.componentDidMount === 'function') {
7175 workInProgress.effectTag |= Update;
7176 }
7177 }
7178
7179 // Called on a preexisting class instance. Returns false if a resumed render
7180 // could be reused.
7181 // function resumeMountClassInstance(
7182 // workInProgress: Fiber,
7183 // priorityLevel: PriorityLevel,
7184 // ): boolean {
7185 // const instance = workInProgress.stateNode;
7186 // resetInputPointers(workInProgress, instance);
7187
7188 // let newState = workInProgress.memoizedState;
7189 // let newProps = workInProgress.pendingProps;
7190 // if (!newProps) {
7191 // // If there isn't any new props, then we'll reuse the memoized props.
7192 // // This could be from already completed work.
7193 // newProps = workInProgress.memoizedProps;
7194 // invariant(
7195 // newProps != null,
7196 // 'There should always be pending or memoized props. This error is ' +
7197 // 'likely caused by a bug in React. Please file an issue.',
7198 // );
7199 // }
7200 // const newUnmaskedContext = getUnmaskedContext(workInProgress);
7201 // const newContext = getMaskedContext(workInProgress, newUnmaskedContext);
7202
7203 // const oldContext = instance.context;
7204 // const oldProps = workInProgress.memoizedProps;
7205
7206 // if (
7207 // typeof instance.componentWillReceiveProps === 'function' &&
7208 // (oldProps !== newProps || oldContext !== newContext)
7209 // ) {
7210 // callComponentWillReceiveProps(
7211 // workInProgress,
7212 // instance,
7213 // newProps,
7214 // newContext,
7215 // );
7216 // }
7217
7218 // // Process the update queue before calling shouldComponentUpdate
7219 // const updateQueue = workInProgress.updateQueue;
7220 // if (updateQueue !== null) {
7221 // newState = processUpdateQueue(
7222 // workInProgress,
7223 // updateQueue,
7224 // instance,
7225 // newState,
7226 // newProps,
7227 // priorityLevel,
7228 // );
7229 // }
7230
7231 // // TODO: Should we deal with a setState that happened after the last
7232 // // componentWillMount and before this componentWillMount? Probably
7233 // // unsupported anyway.
7234
7235 // if (
7236 // !checkShouldComponentUpdate(
7237 // workInProgress,
7238 // workInProgress.memoizedProps,
7239 // newProps,
7240 // workInProgress.memoizedState,
7241 // newState,
7242 // newContext,
7243 // )
7244 // ) {
7245 // // Update the existing instance's state, props, and context pointers even
7246 // // though we're bailing out.
7247 // instance.props = newProps;
7248 // instance.state = newState;
7249 // instance.context = newContext;
7250 // return false;
7251 // }
7252
7253 // // Update the input pointers now so that they are correct when we call
7254 // // componentWillMount
7255 // instance.props = newProps;
7256 // instance.state = newState;
7257 // instance.context = newContext;
7258
7259 // if (typeof instance.componentWillMount === 'function') {
7260 // callComponentWillMount(workInProgress, instance);
7261 // // componentWillMount may have called setState. Process the update queue.
7262 // const newUpdateQueue = workInProgress.updateQueue;
7263 // if (newUpdateQueue !== null) {
7264 // newState = processUpdateQueue(
7265 // workInProgress,
7266 // newUpdateQueue,
7267 // instance,
7268 // newState,
7269 // newProps,
7270 // priorityLevel,
7271 // );
7272 // }
7273 // }
7274
7275 // if (typeof instance.componentDidMount === 'function') {
7276 // workInProgress.effectTag |= Update;
7277 // }
7278
7279 // instance.state = newState;
7280
7281 // return true;
7282 // }
7283
7284 // Invokes the update life-cycles and returns false if it shouldn't rerender.
7285 function updateClassInstance(current, workInProgress, renderExpirationTime) {
7286 var instance = workInProgress.stateNode;
7287 resetInputPointers(workInProgress, instance);
7288
7289 var oldProps = workInProgress.memoizedProps;
7290 var newProps = workInProgress.pendingProps;
7291 var oldContext = instance.context;
7292 var newUnmaskedContext = getUnmaskedContext(workInProgress);
7293 var newContext = getMaskedContext(workInProgress, newUnmaskedContext);
7294
7295 // Note: During these life-cycles, instance.props/instance.state are what
7296 // ever the previously attempted to render - not the "current". However,
7297 // during componentDidUpdate we pass the "current" props.
7298
7299 if (typeof instance.componentWillReceiveProps === 'function' && (oldProps !== newProps || oldContext !== newContext)) {
7300 callComponentWillReceiveProps(workInProgress, instance, newProps, newContext);
7301 }
7302
7303 // Compute the next state using the memoized state and the update queue.
7304 var oldState = workInProgress.memoizedState;
7305 // TODO: Previous state can be null.
7306 var newState = void 0;
7307 if (workInProgress.updateQueue !== null) {
7308 newState = processUpdateQueue(current, workInProgress, workInProgress.updateQueue, instance, newProps, renderExpirationTime);
7309 } else {
7310 newState = oldState;
7311 }
7312
7313 if (oldProps === newProps && oldState === newState && !hasContextChanged() && !(workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate)) {
7314 // If an update was already in progress, we should schedule an Update
7315 // effect even though we're bailing out, so that cWU/cDU are called.
7316 if (typeof instance.componentDidUpdate === 'function') {
7317 if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
7318 workInProgress.effectTag |= Update;
7319 }
7320 }
7321 return false;
7322 }
7323
7324 var shouldUpdate = checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext);
7325
7326 if (shouldUpdate) {
7327 if (typeof instance.componentWillUpdate === 'function') {
7328 startPhaseTimer(workInProgress, 'componentWillUpdate');
7329 instance.componentWillUpdate(newProps, newState, newContext);
7330 stopPhaseTimer();
7331
7332 // Simulate an async bailout/interruption by invoking lifecycle twice.
7333 if (debugRenderPhaseSideEffects) {
7334 instance.componentWillUpdate(newProps, newState, newContext);
7335 }
7336 }
7337 if (typeof instance.componentDidUpdate === 'function') {
7338 workInProgress.effectTag |= Update;
7339 }
7340 } else {
7341 // If an update was already in progress, we should schedule an Update
7342 // effect even though we're bailing out, so that cWU/cDU are called.
7343 if (typeof instance.componentDidUpdate === 'function') {
7344 if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
7345 workInProgress.effectTag |= Update;
7346 }
7347 }
7348
7349 // If shouldComponentUpdate returned false, we should still update the
7350 // memoized props/state to indicate that this work can be reused.
7351 memoizeProps(workInProgress, newProps);
7352 memoizeState(workInProgress, newState);
7353 }
7354
7355 // Update the existing instance's state, props, and context pointers even
7356 // if shouldComponentUpdate returns false.
7357 instance.props = newProps;
7358 instance.state = newState;
7359 instance.context = newContext;
7360
7361 return shouldUpdate;
7362 }
7363
7364 return {
7365 adoptClassInstance: adoptClassInstance,
7366 constructClassInstance: constructClassInstance,
7367 mountClassInstance: mountClassInstance,
7368 // resumeMountClassInstance,
7369 updateClassInstance: updateClassInstance
7370 };
7371};
7372
7373var getCurrentFiberStackAddendum$2 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
7374
7375
7376var didWarnAboutMaps = void 0;
7377var ownerHasKeyUseWarning = void 0;
7378var ownerHasFunctionTypeWarning = void 0;
7379var warnForMissingKey = function (child) {};
7380
7381{
7382 didWarnAboutMaps = false;
7383 /**
7384 * Warn if there's no key explicitly set on dynamic arrays of children or
7385 * object keys are not valid. This allows us to keep track of children between
7386 * updates.
7387 */
7388 ownerHasKeyUseWarning = {};
7389 ownerHasFunctionTypeWarning = {};
7390
7391 warnForMissingKey = function (child) {
7392 if (child === null || typeof child !== 'object') {
7393 return;
7394 }
7395 if (!child._store || child._store.validated || child.key != null) {
7396 return;
7397 }
7398 !(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;
7399 child._store.validated = true;
7400
7401 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$2() || '');
7402 if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
7403 return;
7404 }
7405 ownerHasKeyUseWarning[currentComponentErrorInfo] = true;
7406
7407 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$2());
7408 };
7409}
7410
7411var isArray$1 = Array.isArray;
7412
7413function coerceRef(current, element) {
7414 var mixedRef = element.ref;
7415 if (mixedRef !== null && typeof mixedRef !== 'function') {
7416 if (element._owner) {
7417 var owner = element._owner;
7418 var inst = void 0;
7419 if (owner) {
7420 var ownerFiber = owner;
7421 !(ownerFiber.tag === ClassComponent) ? invariant_1(false, 'Stateless function components cannot have refs.') : void 0;
7422 inst = ownerFiber.stateNode;
7423 }
7424 !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;
7425 var stringRef = '' + mixedRef;
7426 // Check if previous string ref matches new string ref
7427 if (current !== null && current.ref !== null && current.ref._stringRef === stringRef) {
7428 return current.ref;
7429 }
7430 var ref = function (value) {
7431 var refs = inst.refs === emptyObject_1 ? inst.refs = {} : inst.refs;
7432 if (value === null) {
7433 delete refs[stringRef];
7434 } else {
7435 refs[stringRef] = value;
7436 }
7437 };
7438 ref._stringRef = stringRef;
7439 return ref;
7440 } else {
7441 !(typeof mixedRef === 'string') ? invariant_1(false, 'Expected ref to be a function or a string.') : void 0;
7442 !element._owner ? invariant_1(false, 'Element ref was specified as a string (%s) but no owner was set. You may have multiple copies of React loaded. (details: https://fb.me/react-refs-must-have-owner).', mixedRef) : void 0;
7443 }
7444 }
7445 return mixedRef;
7446}
7447
7448function throwOnInvalidObjectType(returnFiber, newChild) {
7449 if (returnFiber.type !== 'textarea') {
7450 var addendum = '';
7451 {
7452 addendum = ' If you meant to render a collection of children, use an array ' + 'instead.' + (getCurrentFiberStackAddendum$2() || '');
7453 }
7454 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);
7455 }
7456}
7457
7458function warnOnFunctionType() {
7459 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$2() || '');
7460
7461 if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) {
7462 return;
7463 }
7464 ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true;
7465
7466 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$2() || '');
7467}
7468
7469// This wrapper function exists because I expect to clone the code in each path
7470// to be able to optimize each path individually by branching early. This needs
7471// a compiler or we can do it manually. Helpers that don't need this branching
7472// live outside of this function.
7473function ChildReconciler(shouldTrackSideEffects) {
7474 function deleteChild(returnFiber, childToDelete) {
7475 if (!shouldTrackSideEffects) {
7476 // Noop.
7477 return;
7478 }
7479 // Deletions are added in reversed order so we add it to the front.
7480 // At this point, the return fiber's effect list is empty except for
7481 // deletions, so we can just append the deletion to the list. The remaining
7482 // effects aren't added until the complete phase. Once we implement
7483 // resuming, this may not be true.
7484 var last = returnFiber.lastEffect;
7485 if (last !== null) {
7486 last.nextEffect = childToDelete;
7487 returnFiber.lastEffect = childToDelete;
7488 } else {
7489 returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
7490 }
7491 childToDelete.nextEffect = null;
7492 childToDelete.effectTag = Deletion;
7493 }
7494
7495 function deleteRemainingChildren(returnFiber, currentFirstChild) {
7496 if (!shouldTrackSideEffects) {
7497 // Noop.
7498 return null;
7499 }
7500
7501 // TODO: For the shouldClone case, this could be micro-optimized a bit by
7502 // assuming that after the first child we've already added everything.
7503 var childToDelete = currentFirstChild;
7504 while (childToDelete !== null) {
7505 deleteChild(returnFiber, childToDelete);
7506 childToDelete = childToDelete.sibling;
7507 }
7508 return null;
7509 }
7510
7511 function mapRemainingChildren(returnFiber, currentFirstChild) {
7512 // Add the remaining children to a temporary map so that we can find them by
7513 // keys quickly. Implicit (null) keys get added to this set with their index
7514 var existingChildren = new Map();
7515
7516 var existingChild = currentFirstChild;
7517 while (existingChild !== null) {
7518 if (existingChild.key !== null) {
7519 existingChildren.set(existingChild.key, existingChild);
7520 } else {
7521 existingChildren.set(existingChild.index, existingChild);
7522 }
7523 existingChild = existingChild.sibling;
7524 }
7525 return existingChildren;
7526 }
7527
7528 function useFiber(fiber, pendingProps, expirationTime) {
7529 // We currently set sibling to null and index to 0 here because it is easy
7530 // to forget to do before returning it. E.g. for the single child case.
7531 var clone = createWorkInProgress(fiber, pendingProps, expirationTime);
7532 clone.index = 0;
7533 clone.sibling = null;
7534 return clone;
7535 }
7536
7537 function placeChild(newFiber, lastPlacedIndex, newIndex) {
7538 newFiber.index = newIndex;
7539 if (!shouldTrackSideEffects) {
7540 // Noop.
7541 return lastPlacedIndex;
7542 }
7543 var current = newFiber.alternate;
7544 if (current !== null) {
7545 var oldIndex = current.index;
7546 if (oldIndex < lastPlacedIndex) {
7547 // This is a move.
7548 newFiber.effectTag = Placement;
7549 return lastPlacedIndex;
7550 } else {
7551 // This item can stay in place.
7552 return oldIndex;
7553 }
7554 } else {
7555 // This is an insertion.
7556 newFiber.effectTag = Placement;
7557 return lastPlacedIndex;
7558 }
7559 }
7560
7561 function placeSingleChild(newFiber) {
7562 // This is simpler for the single child case. We only need to do a
7563 // placement for inserting new children.
7564 if (shouldTrackSideEffects && newFiber.alternate === null) {
7565 newFiber.effectTag = Placement;
7566 }
7567 return newFiber;
7568 }
7569
7570 function updateTextNode(returnFiber, current, textContent, expirationTime) {
7571 if (current === null || current.tag !== HostText) {
7572 // Insert
7573 var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime);
7574 created['return'] = returnFiber;
7575 return created;
7576 } else {
7577 // Update
7578 var existing = useFiber(current, textContent, expirationTime);
7579 existing['return'] = returnFiber;
7580 return existing;
7581 }
7582 }
7583
7584 function updateElement(returnFiber, current, element, expirationTime) {
7585 if (current !== null && current.type === element.type) {
7586 // Move based on index
7587 var existing = useFiber(current, element.props, expirationTime);
7588 existing.ref = coerceRef(current, element);
7589 existing['return'] = returnFiber;
7590 {
7591 existing._debugSource = element._source;
7592 existing._debugOwner = element._owner;
7593 }
7594 return existing;
7595 } else {
7596 // Insert
7597 var created = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime);
7598 created.ref = coerceRef(current, element);
7599 created['return'] = returnFiber;
7600 return created;
7601 }
7602 }
7603
7604 function updatePortal(returnFiber, current, portal, expirationTime) {
7605 if (current === null || current.tag !== HostPortal || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) {
7606 // Insert
7607 var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime);
7608 created['return'] = returnFiber;
7609 return created;
7610 } else {
7611 // Update
7612 var existing = useFiber(current, portal.children || [], expirationTime);
7613 existing['return'] = returnFiber;
7614 return existing;
7615 }
7616 }
7617
7618 function updateFragment(returnFiber, current, fragment, expirationTime, key) {
7619 if (current === null || current.tag !== Fragment) {
7620 // Insert
7621 var created = createFiberFromFragment(fragment, returnFiber.internalContextTag, expirationTime, key);
7622 created['return'] = returnFiber;
7623 return created;
7624 } else {
7625 // Update
7626 var existing = useFiber(current, fragment, expirationTime);
7627 existing['return'] = returnFiber;
7628 return existing;
7629 }
7630 }
7631
7632 function createChild(returnFiber, newChild, expirationTime) {
7633 if (typeof newChild === 'string' || typeof newChild === 'number') {
7634 // Text nodes don't have keys. If the previous node is implicitly keyed
7635 // we can continue to replace it without aborting even if it is not a text
7636 // node.
7637 var created = createFiberFromText('' + newChild, returnFiber.internalContextTag, expirationTime);
7638 created['return'] = returnFiber;
7639 return created;
7640 }
7641
7642 if (typeof newChild === 'object' && newChild !== null) {
7643 switch (newChild.$$typeof) {
7644 case REACT_ELEMENT_TYPE:
7645 {
7646 var _created = createFiberFromElement(newChild, returnFiber.internalContextTag, expirationTime);
7647 _created.ref = coerceRef(null, newChild);
7648 _created['return'] = returnFiber;
7649 return _created;
7650 }
7651 case REACT_PORTAL_TYPE:
7652 {
7653 var _created2 = createFiberFromPortal(newChild, returnFiber.internalContextTag, expirationTime);
7654 _created2['return'] = returnFiber;
7655 return _created2;
7656 }
7657 }
7658
7659 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7660 var _created3 = createFiberFromFragment(newChild, returnFiber.internalContextTag, expirationTime, null);
7661 _created3['return'] = returnFiber;
7662 return _created3;
7663 }
7664
7665 throwOnInvalidObjectType(returnFiber, newChild);
7666 }
7667
7668 {
7669 if (typeof newChild === 'function') {
7670 warnOnFunctionType();
7671 }
7672 }
7673
7674 return null;
7675 }
7676
7677 function updateSlot(returnFiber, oldFiber, newChild, expirationTime) {
7678 // Update the fiber if the keys match, otherwise return null.
7679
7680 var key = oldFiber !== null ? oldFiber.key : null;
7681
7682 if (typeof newChild === 'string' || typeof newChild === 'number') {
7683 // Text nodes don't have keys. If the previous node is implicitly keyed
7684 // we can continue to replace it without aborting even if it is not a text
7685 // node.
7686 if (key !== null) {
7687 return null;
7688 }
7689 return updateTextNode(returnFiber, oldFiber, '' + newChild, expirationTime);
7690 }
7691
7692 if (typeof newChild === 'object' && newChild !== null) {
7693 switch (newChild.$$typeof) {
7694 case REACT_ELEMENT_TYPE:
7695 {
7696 if (newChild.key === key) {
7697 if (newChild.type === REACT_FRAGMENT_TYPE) {
7698 return updateFragment(returnFiber, oldFiber, newChild.props.children, expirationTime, key);
7699 }
7700 return updateElement(returnFiber, oldFiber, newChild, expirationTime);
7701 } else {
7702 return null;
7703 }
7704 }
7705 case REACT_PORTAL_TYPE:
7706 {
7707 if (newChild.key === key) {
7708 return updatePortal(returnFiber, oldFiber, newChild, expirationTime);
7709 } else {
7710 return null;
7711 }
7712 }
7713 }
7714
7715 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7716 if (key !== null) {
7717 return null;
7718 }
7719
7720 return updateFragment(returnFiber, oldFiber, newChild, expirationTime, null);
7721 }
7722
7723 throwOnInvalidObjectType(returnFiber, newChild);
7724 }
7725
7726 {
7727 if (typeof newChild === 'function') {
7728 warnOnFunctionType();
7729 }
7730 }
7731
7732 return null;
7733 }
7734
7735 function updateFromMap(existingChildren, returnFiber, newIdx, newChild, expirationTime) {
7736 if (typeof newChild === 'string' || typeof newChild === 'number') {
7737 // Text nodes don't have keys, so we neither have to check the old nor
7738 // new node for the key. If both are text nodes, they match.
7739 var matchedFiber = existingChildren.get(newIdx) || null;
7740 return updateTextNode(returnFiber, matchedFiber, '' + newChild, expirationTime);
7741 }
7742
7743 if (typeof newChild === 'object' && newChild !== null) {
7744 switch (newChild.$$typeof) {
7745 case REACT_ELEMENT_TYPE:
7746 {
7747 var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
7748 if (newChild.type === REACT_FRAGMENT_TYPE) {
7749 return updateFragment(returnFiber, _matchedFiber, newChild.props.children, expirationTime, newChild.key);
7750 }
7751 return updateElement(returnFiber, _matchedFiber, newChild, expirationTime);
7752 }
7753 case REACT_PORTAL_TYPE:
7754 {
7755 var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
7756 return updatePortal(returnFiber, _matchedFiber2, newChild, expirationTime);
7757 }
7758 }
7759
7760 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7761 var _matchedFiber3 = existingChildren.get(newIdx) || null;
7762 return updateFragment(returnFiber, _matchedFiber3, newChild, expirationTime, null);
7763 }
7764
7765 throwOnInvalidObjectType(returnFiber, newChild);
7766 }
7767
7768 {
7769 if (typeof newChild === 'function') {
7770 warnOnFunctionType();
7771 }
7772 }
7773
7774 return null;
7775 }
7776
7777 /**
7778 * Warns if there is a duplicate or missing key
7779 */
7780 function warnOnInvalidKey(child, knownKeys) {
7781 {
7782 if (typeof child !== 'object' || child === null) {
7783 return knownKeys;
7784 }
7785 switch (child.$$typeof) {
7786 case REACT_ELEMENT_TYPE:
7787 case REACT_PORTAL_TYPE:
7788 warnForMissingKey(child);
7789 var key = child.key;
7790 if (typeof key !== 'string') {
7791 break;
7792 }
7793 if (knownKeys === null) {
7794 knownKeys = new Set();
7795 knownKeys.add(key);
7796 break;
7797 }
7798 if (!knownKeys.has(key)) {
7799 knownKeys.add(key);
7800 break;
7801 }
7802 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$2());
7803 break;
7804 default:
7805 break;
7806 }
7807 }
7808 return knownKeys;
7809 }
7810
7811 function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, expirationTime) {
7812 // This algorithm can't optimize by searching from boths ends since we
7813 // don't have backpointers on fibers. I'm trying to see how far we can get
7814 // with that model. If it ends up not being worth the tradeoffs, we can
7815 // add it later.
7816
7817 // Even with a two ended optimization, we'd want to optimize for the case
7818 // where there are few changes and brute force the comparison instead of
7819 // going for the Map. It'd like to explore hitting that path first in
7820 // forward-only mode and only go for the Map once we notice that we need
7821 // lots of look ahead. This doesn't handle reversal as well as two ended
7822 // search but that's unusual. Besides, for the two ended optimization to
7823 // work on Iterables, we'd need to copy the whole set.
7824
7825 // In this first iteration, we'll just live with hitting the bad case
7826 // (adding everything to a Map) in for every insert/move.
7827
7828 // If you change this code, also update reconcileChildrenIterator() which
7829 // uses the same algorithm.
7830
7831 {
7832 // First, validate keys.
7833 var knownKeys = null;
7834 for (var i = 0; i < newChildren.length; i++) {
7835 var child = newChildren[i];
7836 knownKeys = warnOnInvalidKey(child, knownKeys);
7837 }
7838 }
7839
7840 var resultingFirstChild = null;
7841 var previousNewFiber = null;
7842
7843 var oldFiber = currentFirstChild;
7844 var lastPlacedIndex = 0;
7845 var newIdx = 0;
7846 var nextOldFiber = null;
7847 for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) {
7848 if (oldFiber.index > newIdx) {
7849 nextOldFiber = oldFiber;
7850 oldFiber = null;
7851 } else {
7852 nextOldFiber = oldFiber.sibling;
7853 }
7854 var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], expirationTime);
7855 if (newFiber === null) {
7856 // TODO: This breaks on empty slots like null children. That's
7857 // unfortunate because it triggers the slow path all the time. We need
7858 // a better way to communicate whether this was a miss or null,
7859 // boolean, undefined, etc.
7860 if (oldFiber === null) {
7861 oldFiber = nextOldFiber;
7862 }
7863 break;
7864 }
7865 if (shouldTrackSideEffects) {
7866 if (oldFiber && newFiber.alternate === null) {
7867 // We matched the slot, but we didn't reuse the existing fiber, so we
7868 // need to delete the existing child.
7869 deleteChild(returnFiber, oldFiber);
7870 }
7871 }
7872 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
7873 if (previousNewFiber === null) {
7874 // TODO: Move out of the loop. This only happens for the first run.
7875 resultingFirstChild = newFiber;
7876 } else {
7877 // TODO: Defer siblings if we're not at the right index for this slot.
7878 // I.e. if we had null values before, then we want to defer this
7879 // for each null value. However, we also don't want to call updateSlot
7880 // with the previous one.
7881 previousNewFiber.sibling = newFiber;
7882 }
7883 previousNewFiber = newFiber;
7884 oldFiber = nextOldFiber;
7885 }
7886
7887 if (newIdx === newChildren.length) {
7888 // We've reached the end of the new children. We can delete the rest.
7889 deleteRemainingChildren(returnFiber, oldFiber);
7890 return resultingFirstChild;
7891 }
7892
7893 if (oldFiber === null) {
7894 // If we don't have any more existing children we can choose a fast path
7895 // since the rest will all be insertions.
7896 for (; newIdx < newChildren.length; newIdx++) {
7897 var _newFiber = createChild(returnFiber, newChildren[newIdx], expirationTime);
7898 if (!_newFiber) {
7899 continue;
7900 }
7901 lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx);
7902 if (previousNewFiber === null) {
7903 // TODO: Move out of the loop. This only happens for the first run.
7904 resultingFirstChild = _newFiber;
7905 } else {
7906 previousNewFiber.sibling = _newFiber;
7907 }
7908 previousNewFiber = _newFiber;
7909 }
7910 return resultingFirstChild;
7911 }
7912
7913 // Add all children to a key map for quick lookups.
7914 var existingChildren = mapRemainingChildren(returnFiber, oldFiber);
7915
7916 // Keep scanning and use the map to restore deleted items as moves.
7917 for (; newIdx < newChildren.length; newIdx++) {
7918 var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], expirationTime);
7919 if (_newFiber2) {
7920 if (shouldTrackSideEffects) {
7921 if (_newFiber2.alternate !== null) {
7922 // The new fiber is a work in progress, but if there exists a
7923 // current, that means that we reused the fiber. We need to delete
7924 // it from the child list so that we don't add it to the deletion
7925 // list.
7926 existingChildren['delete'](_newFiber2.key === null ? newIdx : _newFiber2.key);
7927 }
7928 }
7929 lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx);
7930 if (previousNewFiber === null) {
7931 resultingFirstChild = _newFiber2;
7932 } else {
7933 previousNewFiber.sibling = _newFiber2;
7934 }
7935 previousNewFiber = _newFiber2;
7936 }
7937 }
7938
7939 if (shouldTrackSideEffects) {
7940 // Any existing children that weren't consumed above were deleted. We need
7941 // to add them to the deletion list.
7942 existingChildren.forEach(function (child) {
7943 return deleteChild(returnFiber, child);
7944 });
7945 }
7946
7947 return resultingFirstChild;
7948 }
7949
7950 function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, expirationTime) {
7951 // This is the same implementation as reconcileChildrenArray(),
7952 // but using the iterator instead.
7953
7954 var iteratorFn = getIteratorFn(newChildrenIterable);
7955 !(typeof iteratorFn === 'function') ? invariant_1(false, 'An object is not an iterable. This error is likely caused by a bug in React. Please file an issue.') : void 0;
7956
7957 {
7958 // Warn about using Maps as children
7959 if (typeof newChildrenIterable.entries === 'function') {
7960 var possibleMap = newChildrenIterable;
7961 if (possibleMap.entries === iteratorFn) {
7962 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$2());
7963 didWarnAboutMaps = true;
7964 }
7965 }
7966
7967 // First, validate keys.
7968 // We'll get a different iterator later for the main pass.
7969 var _newChildren = iteratorFn.call(newChildrenIterable);
7970 if (_newChildren) {
7971 var knownKeys = null;
7972 var _step = _newChildren.next();
7973 for (; !_step.done; _step = _newChildren.next()) {
7974 var child = _step.value;
7975 knownKeys = warnOnInvalidKey(child, knownKeys);
7976 }
7977 }
7978 }
7979
7980 var newChildren = iteratorFn.call(newChildrenIterable);
7981 !(newChildren != null) ? invariant_1(false, 'An iterable object provided no iterator.') : void 0;
7982
7983 var resultingFirstChild = null;
7984 var previousNewFiber = null;
7985
7986 var oldFiber = currentFirstChild;
7987 var lastPlacedIndex = 0;
7988 var newIdx = 0;
7989 var nextOldFiber = null;
7990
7991 var step = newChildren.next();
7992 for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) {
7993 if (oldFiber.index > newIdx) {
7994 nextOldFiber = oldFiber;
7995 oldFiber = null;
7996 } else {
7997 nextOldFiber = oldFiber.sibling;
7998 }
7999 var newFiber = updateSlot(returnFiber, oldFiber, step.value, expirationTime);
8000 if (newFiber === null) {
8001 // TODO: This breaks on empty slots like null children. That's
8002 // unfortunate because it triggers the slow path all the time. We need
8003 // a better way to communicate whether this was a miss or null,
8004 // boolean, undefined, etc.
8005 if (!oldFiber) {
8006 oldFiber = nextOldFiber;
8007 }
8008 break;
8009 }
8010 if (shouldTrackSideEffects) {
8011 if (oldFiber && newFiber.alternate === null) {
8012 // We matched the slot, but we didn't reuse the existing fiber, so we
8013 // need to delete the existing child.
8014 deleteChild(returnFiber, oldFiber);
8015 }
8016 }
8017 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
8018 if (previousNewFiber === null) {
8019 // TODO: Move out of the loop. This only happens for the first run.
8020 resultingFirstChild = newFiber;
8021 } else {
8022 // TODO: Defer siblings if we're not at the right index for this slot.
8023 // I.e. if we had null values before, then we want to defer this
8024 // for each null value. However, we also don't want to call updateSlot
8025 // with the previous one.
8026 previousNewFiber.sibling = newFiber;
8027 }
8028 previousNewFiber = newFiber;
8029 oldFiber = nextOldFiber;
8030 }
8031
8032 if (step.done) {
8033 // We've reached the end of the new children. We can delete the rest.
8034 deleteRemainingChildren(returnFiber, oldFiber);
8035 return resultingFirstChild;
8036 }
8037
8038 if (oldFiber === null) {
8039 // If we don't have any more existing children we can choose a fast path
8040 // since the rest will all be insertions.
8041 for (; !step.done; newIdx++, step = newChildren.next()) {
8042 var _newFiber3 = createChild(returnFiber, step.value, expirationTime);
8043 if (_newFiber3 === null) {
8044 continue;
8045 }
8046 lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx);
8047 if (previousNewFiber === null) {
8048 // TODO: Move out of the loop. This only happens for the first run.
8049 resultingFirstChild = _newFiber3;
8050 } else {
8051 previousNewFiber.sibling = _newFiber3;
8052 }
8053 previousNewFiber = _newFiber3;
8054 }
8055 return resultingFirstChild;
8056 }
8057
8058 // Add all children to a key map for quick lookups.
8059 var existingChildren = mapRemainingChildren(returnFiber, oldFiber);
8060
8061 // Keep scanning and use the map to restore deleted items as moves.
8062 for (; !step.done; newIdx++, step = newChildren.next()) {
8063 var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, expirationTime);
8064 if (_newFiber4 !== null) {
8065 if (shouldTrackSideEffects) {
8066 if (_newFiber4.alternate !== null) {
8067 // The new fiber is a work in progress, but if there exists a
8068 // current, that means that we reused the fiber. We need to delete
8069 // it from the child list so that we don't add it to the deletion
8070 // list.
8071 existingChildren['delete'](_newFiber4.key === null ? newIdx : _newFiber4.key);
8072 }
8073 }
8074 lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx);
8075 if (previousNewFiber === null) {
8076 resultingFirstChild = _newFiber4;
8077 } else {
8078 previousNewFiber.sibling = _newFiber4;
8079 }
8080 previousNewFiber = _newFiber4;
8081 }
8082 }
8083
8084 if (shouldTrackSideEffects) {
8085 // Any existing children that weren't consumed above were deleted. We need
8086 // to add them to the deletion list.
8087 existingChildren.forEach(function (child) {
8088 return deleteChild(returnFiber, child);
8089 });
8090 }
8091
8092 return resultingFirstChild;
8093 }
8094
8095 function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, expirationTime) {
8096 // There's no need to check for keys on text nodes since we don't have a
8097 // way to define them.
8098 if (currentFirstChild !== null && currentFirstChild.tag === HostText) {
8099 // We already have an existing node so let's just update it and delete
8100 // the rest.
8101 deleteRemainingChildren(returnFiber, currentFirstChild.sibling);
8102 var existing = useFiber(currentFirstChild, textContent, expirationTime);
8103 existing['return'] = returnFiber;
8104 return existing;
8105 }
8106 // The existing first child is not a text node so we need to create one
8107 // and delete the existing ones.
8108 deleteRemainingChildren(returnFiber, currentFirstChild);
8109 var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime);
8110 created['return'] = returnFiber;
8111 return created;
8112 }
8113
8114 function reconcileSingleElement(returnFiber, currentFirstChild, element, expirationTime) {
8115 var key = element.key;
8116 var child = currentFirstChild;
8117 while (child !== null) {
8118 // TODO: If key === null and child.key === null, then this only applies to
8119 // the first item in the list.
8120 if (child.key === key) {
8121 if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.type === element.type) {
8122 deleteRemainingChildren(returnFiber, child.sibling);
8123 var existing = useFiber(child, element.type === REACT_FRAGMENT_TYPE ? element.props.children : element.props, expirationTime);
8124 existing.ref = coerceRef(child, element);
8125 existing['return'] = returnFiber;
8126 {
8127 existing._debugSource = element._source;
8128 existing._debugOwner = element._owner;
8129 }
8130 return existing;
8131 } else {
8132 deleteRemainingChildren(returnFiber, child);
8133 break;
8134 }
8135 } else {
8136 deleteChild(returnFiber, child);
8137 }
8138 child = child.sibling;
8139 }
8140
8141 if (element.type === REACT_FRAGMENT_TYPE) {
8142 var created = createFiberFromFragment(element.props.children, returnFiber.internalContextTag, expirationTime, element.key);
8143 created['return'] = returnFiber;
8144 return created;
8145 } else {
8146 var _created4 = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime);
8147 _created4.ref = coerceRef(currentFirstChild, element);
8148 _created4['return'] = returnFiber;
8149 return _created4;
8150 }
8151 }
8152
8153 function reconcileSinglePortal(returnFiber, currentFirstChild, portal, expirationTime) {
8154 var key = portal.key;
8155 var child = currentFirstChild;
8156 while (child !== null) {
8157 // TODO: If key === null and child.key === null, then this only applies to
8158 // the first item in the list.
8159 if (child.key === key) {
8160 if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) {
8161 deleteRemainingChildren(returnFiber, child.sibling);
8162 var existing = useFiber(child, portal.children || [], expirationTime);
8163 existing['return'] = returnFiber;
8164 return existing;
8165 } else {
8166 deleteRemainingChildren(returnFiber, child);
8167 break;
8168 }
8169 } else {
8170 deleteChild(returnFiber, child);
8171 }
8172 child = child.sibling;
8173 }
8174
8175 var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime);
8176 created['return'] = returnFiber;
8177 return created;
8178 }
8179
8180 // This API will tag the children with the side-effect of the reconciliation
8181 // itself. They will be added to the side-effect list as we pass through the
8182 // children and the parent.
8183 function reconcileChildFibers(returnFiber, currentFirstChild, newChild, expirationTime) {
8184 // This function is not recursive.
8185 // If the top level item is an array, we treat it as a set of children,
8186 // not as a fragment. Nested arrays on the other hand will be treated as
8187 // fragment nodes. Recursion happens at the normal flow.
8188
8189 // Handle top level unkeyed fragments as if they were arrays.
8190 // This leads to an ambiguity between <>{[...]}</> and <>...</>.
8191 // We treat the ambiguous cases above the same.
8192 if (typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null) {
8193 newChild = newChild.props.children;
8194 }
8195
8196 // Handle object types
8197 var isObject = typeof newChild === 'object' && newChild !== null;
8198
8199 if (isObject) {
8200 switch (newChild.$$typeof) {
8201 case REACT_ELEMENT_TYPE:
8202 return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, expirationTime));
8203 case REACT_PORTAL_TYPE:
8204 return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, expirationTime));
8205 }
8206 }
8207
8208 if (typeof newChild === 'string' || typeof newChild === 'number') {
8209 return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, expirationTime));
8210 }
8211
8212 if (isArray$1(newChild)) {
8213 return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, expirationTime);
8214 }
8215
8216 if (getIteratorFn(newChild)) {
8217 return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, expirationTime);
8218 }
8219
8220 if (isObject) {
8221 throwOnInvalidObjectType(returnFiber, newChild);
8222 }
8223
8224 {
8225 if (typeof newChild === 'function') {
8226 warnOnFunctionType();
8227 }
8228 }
8229 if (typeof newChild === 'undefined') {
8230 // If the new child is undefined, and the return fiber is a composite
8231 // component, throw an error. If Fiber return types are disabled,
8232 // we already threw above.
8233 switch (returnFiber.tag) {
8234 case ClassComponent:
8235 {
8236 {
8237 var instance = returnFiber.stateNode;
8238 if (instance.render._isMockFunction) {
8239 // We allow auto-mocks to proceed as if they're returning null.
8240 break;
8241 }
8242 }
8243 }
8244 // Intentionally fall through to the next case, which handles both
8245 // functions and classes
8246 // eslint-disable-next-lined no-fallthrough
8247 case FunctionalComponent:
8248 {
8249 var Component = returnFiber.type;
8250 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');
8251 }
8252 }
8253 }
8254
8255 // Remaining cases are all treated as empty.
8256 return deleteRemainingChildren(returnFiber, currentFirstChild);
8257 }
8258
8259 return reconcileChildFibers;
8260}
8261
8262var reconcileChildFibers = ChildReconciler(true);
8263var mountChildFibers = ChildReconciler(false);
8264
8265function cloneChildFibers(current, workInProgress) {
8266 !(current === null || workInProgress.child === current.child) ? invariant_1(false, 'Resuming work not yet implemented.') : void 0;
8267
8268 if (workInProgress.child === null) {
8269 return;
8270 }
8271
8272 var currentChild = workInProgress.child;
8273 var newChild = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
8274 workInProgress.child = newChild;
8275
8276 newChild['return'] = workInProgress;
8277 while (currentChild.sibling !== null) {
8278 currentChild = currentChild.sibling;
8279 newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
8280 newChild['return'] = workInProgress;
8281 }
8282 newChild.sibling = null;
8283}
8284
8285var warnedAboutStatelessRefs = void 0;
8286
8287{
8288 warnedAboutStatelessRefs = {};
8289}
8290
8291var ReactFiberBeginWork = function (config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber) {
8292 var shouldSetTextContent = config.shouldSetTextContent,
8293 useSyncScheduling = config.useSyncScheduling,
8294 shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree;
8295 var pushHostContext = hostContext.pushHostContext,
8296 pushHostContainer = hostContext.pushHostContainer;
8297 var enterHydrationState = hydrationContext.enterHydrationState,
8298 resetHydrationState = hydrationContext.resetHydrationState,
8299 tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance;
8300
8301 var _ReactFiberClassCompo = ReactFiberClassComponent(scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState),
8302 adoptClassInstance = _ReactFiberClassCompo.adoptClassInstance,
8303 constructClassInstance = _ReactFiberClassCompo.constructClassInstance,
8304 mountClassInstance = _ReactFiberClassCompo.mountClassInstance,
8305 updateClassInstance = _ReactFiberClassCompo.updateClassInstance;
8306
8307 // TODO: Remove this and use reconcileChildrenAtExpirationTime directly.
8308
8309
8310 function reconcileChildren(current, workInProgress, nextChildren) {
8311 reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, workInProgress.expirationTime);
8312 }
8313
8314 function reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, renderExpirationTime) {
8315 if (current === null) {
8316 // If this is a fresh new component that hasn't been rendered yet, we
8317 // won't update its child set by applying minimal side-effects. Instead,
8318 // we will add them all to the child before it gets rendered. That means
8319 // we can optimize this reconciliation pass by not tracking side-effects.
8320 workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
8321 } else {
8322 // If the current child is the same as the work in progress, it means that
8323 // we haven't yet started any work on these children. Therefore, we use
8324 // the clone algorithm to create a copy of all the current children.
8325
8326 // If we had any progressed work already, that is invalid at this point so
8327 // let's throw it out.
8328 workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderExpirationTime);
8329 }
8330 }
8331
8332 function updateFragment(current, workInProgress) {
8333 var nextChildren = workInProgress.pendingProps;
8334 if (hasContextChanged()) {
8335 // Normally we can bail out on props equality but if context has changed
8336 // we don't do the bailout and we have to reuse existing props instead.
8337 } else if (nextChildren === null || workInProgress.memoizedProps === nextChildren) {
8338 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8339 }
8340 reconcileChildren(current, workInProgress, nextChildren);
8341 memoizeProps(workInProgress, nextChildren);
8342 return workInProgress.child;
8343 }
8344
8345 function markRef(current, workInProgress) {
8346 var ref = workInProgress.ref;
8347 if (ref !== null && (!current || current.ref !== ref)) {
8348 // Schedule a Ref effect
8349 workInProgress.effectTag |= Ref;
8350 }
8351 }
8352
8353 function updateFunctionalComponent(current, workInProgress) {
8354 var fn = workInProgress.type;
8355 var nextProps = workInProgress.pendingProps;
8356
8357 if (hasContextChanged()) {
8358 // Normally we can bail out on props equality but if context has changed
8359 // we don't do the bailout and we have to reuse existing props instead.
8360 } else {
8361 if (workInProgress.memoizedProps === nextProps) {
8362 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8363 }
8364 // TODO: consider bringing fn.shouldComponentUpdate() back.
8365 // It used to be here.
8366 }
8367
8368 var unmaskedContext = getUnmaskedContext(workInProgress);
8369 var context = getMaskedContext(workInProgress, unmaskedContext);
8370
8371 var nextChildren = void 0;
8372
8373 {
8374 ReactCurrentOwner.current = workInProgress;
8375 ReactDebugCurrentFiber.setCurrentPhase('render');
8376 nextChildren = fn(nextProps, context);
8377 ReactDebugCurrentFiber.setCurrentPhase(null);
8378 }
8379 // React DevTools reads this flag.
8380 workInProgress.effectTag |= PerformedWork;
8381 reconcileChildren(current, workInProgress, nextChildren);
8382 memoizeProps(workInProgress, nextProps);
8383 return workInProgress.child;
8384 }
8385
8386 function updateClassComponent(current, workInProgress, renderExpirationTime) {
8387 // Push context providers early to prevent context stack mismatches.
8388 // During mounting we don't know the child context yet as the instance doesn't exist.
8389 // We will invalidate the child context in finishClassComponent() right after rendering.
8390 var hasContext = pushContextProvider(workInProgress);
8391
8392 var shouldUpdate = void 0;
8393 if (current === null) {
8394 if (!workInProgress.stateNode) {
8395 // In the initial pass we might need to construct the instance.
8396 constructClassInstance(workInProgress, workInProgress.pendingProps);
8397 mountClassInstance(workInProgress, renderExpirationTime);
8398
8399 // Simulate an async bailout/interruption by invoking lifecycle twice.
8400 // We do this here rather than inside of ReactFiberClassComponent,
8401 // To more realistically simulate the interruption behavior of async,
8402 // Which would never call componentWillMount() twice on the same instance.
8403 if (debugRenderPhaseSideEffects) {
8404 constructClassInstance(workInProgress, workInProgress.pendingProps);
8405 mountClassInstance(workInProgress, renderExpirationTime);
8406 }
8407
8408 shouldUpdate = true;
8409 } else {
8410 invariant_1(false, 'Resuming work not yet implemented.');
8411 // In a resume, we'll already have an instance we can reuse.
8412 // shouldUpdate = resumeMountClassInstance(workInProgress, renderExpirationTime);
8413 }
8414 } else {
8415 shouldUpdate = updateClassInstance(current, workInProgress, renderExpirationTime);
8416 }
8417 return finishClassComponent(current, workInProgress, shouldUpdate, hasContext);
8418 }
8419
8420 function finishClassComponent(current, workInProgress, shouldUpdate, hasContext) {
8421 // Refs should update even if shouldComponentUpdate returns false
8422 markRef(current, workInProgress);
8423
8424 if (!shouldUpdate) {
8425 // Context providers should defer to sCU for rendering
8426 if (hasContext) {
8427 invalidateContextProvider(workInProgress, false);
8428 }
8429
8430 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8431 }
8432
8433 var instance = workInProgress.stateNode;
8434
8435 // Rerender
8436 ReactCurrentOwner.current = workInProgress;
8437 var nextChildren = void 0;
8438 {
8439 ReactDebugCurrentFiber.setCurrentPhase('render');
8440 nextChildren = instance.render();
8441 if (debugRenderPhaseSideEffects) {
8442 instance.render();
8443 }
8444 ReactDebugCurrentFiber.setCurrentPhase(null);
8445 }
8446 // React DevTools reads this flag.
8447 workInProgress.effectTag |= PerformedWork;
8448 reconcileChildren(current, workInProgress, nextChildren);
8449 // Memoize props and state using the values we just used to render.
8450 // TODO: Restructure so we never read values from the instance.
8451 memoizeState(workInProgress, instance.state);
8452 memoizeProps(workInProgress, instance.props);
8453
8454 // The context might have changed so we need to recalculate it.
8455 if (hasContext) {
8456 invalidateContextProvider(workInProgress, true);
8457 }
8458
8459 return workInProgress.child;
8460 }
8461
8462 function pushHostRootContext(workInProgress) {
8463 var root = workInProgress.stateNode;
8464 if (root.pendingContext) {
8465 pushTopLevelContextObject(workInProgress, root.pendingContext, root.pendingContext !== root.context);
8466 } else if (root.context) {
8467 // Should always be set
8468 pushTopLevelContextObject(workInProgress, root.context, false);
8469 }
8470 pushHostContainer(workInProgress, root.containerInfo);
8471 }
8472
8473 function updateHostRoot(current, workInProgress, renderExpirationTime) {
8474 pushHostRootContext(workInProgress);
8475 var updateQueue = workInProgress.updateQueue;
8476 if (updateQueue !== null) {
8477 var prevState = workInProgress.memoizedState;
8478 var state = processUpdateQueue(current, workInProgress, updateQueue, null, null, renderExpirationTime);
8479 if (prevState === state) {
8480 // If the state is the same as before, that's a bailout because we had
8481 // no work that expires at this time.
8482 resetHydrationState();
8483 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8484 }
8485 var element = state.element;
8486 var root = workInProgress.stateNode;
8487 if ((current === null || current.child === null) && root.hydrate && enterHydrationState(workInProgress)) {
8488 // If we don't have any current children this might be the first pass.
8489 // We always try to hydrate. If this isn't a hydration pass there won't
8490 // be any children to hydrate which is effectively the same thing as
8491 // not hydrating.
8492
8493 // This is a bit of a hack. We track the host root as a placement to
8494 // know that we're currently in a mounting state. That way isMounted
8495 // works as expected. We must reset this before committing.
8496 // TODO: Delete this when we delete isMounted and findDOMNode.
8497 workInProgress.effectTag |= Placement;
8498
8499 // Ensure that children mount into this root without tracking
8500 // side-effects. This ensures that we don't store Placement effects on
8501 // nodes that will be hydrated.
8502 workInProgress.child = mountChildFibers(workInProgress, null, element, renderExpirationTime);
8503 } else {
8504 // Otherwise reset hydration state in case we aborted and resumed another
8505 // root.
8506 resetHydrationState();
8507 reconcileChildren(current, workInProgress, element);
8508 }
8509 memoizeState(workInProgress, state);
8510 return workInProgress.child;
8511 }
8512 resetHydrationState();
8513 // If there is no update queue, that's a bailout because the root has no props.
8514 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8515 }
8516
8517 function updateHostComponent(current, workInProgress, renderExpirationTime) {
8518 pushHostContext(workInProgress);
8519
8520 if (current === null) {
8521 tryToClaimNextHydratableInstance(workInProgress);
8522 }
8523
8524 var type = workInProgress.type;
8525 var memoizedProps = workInProgress.memoizedProps;
8526 var nextProps = workInProgress.pendingProps;
8527 var prevProps = current !== null ? current.memoizedProps : null;
8528
8529 if (hasContextChanged()) {
8530 // Normally we can bail out on props equality but if context has changed
8531 // we don't do the bailout and we have to reuse existing props instead.
8532 } else if (memoizedProps === nextProps) {
8533 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8534 }
8535
8536 var nextChildren = nextProps.children;
8537 var isDirectTextChild = shouldSetTextContent(type, nextProps);
8538
8539 if (isDirectTextChild) {
8540 // We special case a direct text child of a host node. This is a common
8541 // case. We won't handle it as a reified child. We will instead handle
8542 // this in the host environment that also have access to this prop. That
8543 // avoids allocating another HostText fiber and traversing it.
8544 nextChildren = null;
8545 } else if (prevProps && shouldSetTextContent(type, prevProps)) {
8546 // If we're switching from a direct text child to a normal child, or to
8547 // empty, we need to schedule the text content to be reset.
8548 workInProgress.effectTag |= ContentReset;
8549 }
8550
8551 markRef(current, workInProgress);
8552
8553 // Check the host config to see if the children are offscreen/hidden.
8554 if (renderExpirationTime !== Never && !useSyncScheduling && shouldDeprioritizeSubtree(type, nextProps)) {
8555 // Down-prioritize the children.
8556 workInProgress.expirationTime = Never;
8557 // Bailout and come back to this fiber later.
8558 return null;
8559 }
8560
8561 reconcileChildren(current, workInProgress, nextChildren);
8562 memoizeProps(workInProgress, nextProps);
8563 return workInProgress.child;
8564 }
8565
8566 function updateHostText(current, workInProgress) {
8567 if (current === null) {
8568 tryToClaimNextHydratableInstance(workInProgress);
8569 }
8570 var nextProps = workInProgress.pendingProps;
8571 memoizeProps(workInProgress, nextProps);
8572 // Nothing to do here. This is terminal. We'll do the completion step
8573 // immediately after.
8574 return null;
8575 }
8576
8577 function mountIndeterminateComponent(current, workInProgress, renderExpirationTime) {
8578 !(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;
8579 var fn = workInProgress.type;
8580 var props = workInProgress.pendingProps;
8581 var unmaskedContext = getUnmaskedContext(workInProgress);
8582 var context = getMaskedContext(workInProgress, unmaskedContext);
8583
8584 var value = void 0;
8585
8586 {
8587 if (fn.prototype && typeof fn.prototype.render === 'function') {
8588 var componentName = getComponentName(workInProgress);
8589 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);
8590 }
8591 ReactCurrentOwner.current = workInProgress;
8592 value = fn(props, context);
8593 }
8594 // React DevTools reads this flag.
8595 workInProgress.effectTag |= PerformedWork;
8596
8597 if (typeof value === 'object' && value !== null && typeof value.render === 'function') {
8598 // Proceed under the assumption that this is a class instance
8599 workInProgress.tag = ClassComponent;
8600
8601 // Push context providers early to prevent context stack mismatches.
8602 // During mounting we don't know the child context yet as the instance doesn't exist.
8603 // We will invalidate the child context in finishClassComponent() right after rendering.
8604 var hasContext = pushContextProvider(workInProgress);
8605 adoptClassInstance(workInProgress, value);
8606 mountClassInstance(workInProgress, renderExpirationTime);
8607 return finishClassComponent(current, workInProgress, true, hasContext);
8608 } else {
8609 // Proceed under the assumption that this is a functional component
8610 workInProgress.tag = FunctionalComponent;
8611 {
8612 var Component = workInProgress.type;
8613
8614 if (Component) {
8615 warning_1(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component');
8616 }
8617 if (workInProgress.ref !== null) {
8618 var info = '';
8619 var ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
8620 if (ownerName) {
8621 info += '\n\nCheck the render method of `' + ownerName + '`.';
8622 }
8623
8624 var warningKey = ownerName || workInProgress._debugID || '';
8625 var debugSource = workInProgress._debugSource;
8626 if (debugSource) {
8627 warningKey = debugSource.fileName + ':' + debugSource.lineNumber;
8628 }
8629 if (!warnedAboutStatelessRefs[warningKey]) {
8630 warnedAboutStatelessRefs[warningKey] = true;
8631 warning_1(false, 'Stateless function components cannot be given refs. ' + 'Attempts to access this ref will fail.%s%s', info, ReactDebugCurrentFiber.getCurrentFiberStackAddendum());
8632 }
8633 }
8634 }
8635 reconcileChildren(current, workInProgress, value);
8636 memoizeProps(workInProgress, props);
8637 return workInProgress.child;
8638 }
8639 }
8640
8641 function updateCallComponent(current, workInProgress, renderExpirationTime) {
8642 var nextProps = workInProgress.pendingProps;
8643 if (hasContextChanged()) {
8644 // Normally we can bail out on props equality but if context has changed
8645 // we don't do the bailout and we have to reuse existing props instead.
8646 } else if (workInProgress.memoizedProps === nextProps) {
8647 nextProps = workInProgress.memoizedProps;
8648 // TODO: When bailing out, we might need to return the stateNode instead
8649 // of the child. To check it for work.
8650 // return bailoutOnAlreadyFinishedWork(current, workInProgress);
8651 }
8652
8653 var nextChildren = nextProps.children;
8654
8655 // The following is a fork of reconcileChildrenAtExpirationTime but using
8656 // stateNode to store the child.
8657 if (current === null) {
8658 workInProgress.stateNode = mountChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
8659 } else {
8660 workInProgress.stateNode = reconcileChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
8661 }
8662
8663 memoizeProps(workInProgress, nextProps);
8664 // This doesn't take arbitrary time so we could synchronously just begin
8665 // eagerly do the work of workInProgress.child as an optimization.
8666 return workInProgress.stateNode;
8667 }
8668
8669 function updatePortalComponent(current, workInProgress, renderExpirationTime) {
8670 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
8671 var nextChildren = workInProgress.pendingProps;
8672 if (hasContextChanged()) {
8673 // Normally we can bail out on props equality but if context has changed
8674 // we don't do the bailout and we have to reuse existing props instead.
8675 } else if (workInProgress.memoizedProps === nextChildren) {
8676 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8677 }
8678
8679 if (current === null) {
8680 // Portals are special because we don't append the children during mount
8681 // but at commit. Therefore we need to track insertions which the normal
8682 // flow doesn't do during mount. This doesn't happen at the root because
8683 // the root always starts with a "current" with a null child.
8684 // TODO: Consider unifying this with how the root works.
8685 workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
8686 memoizeProps(workInProgress, nextChildren);
8687 } else {
8688 reconcileChildren(current, workInProgress, nextChildren);
8689 memoizeProps(workInProgress, nextChildren);
8690 }
8691 return workInProgress.child;
8692 }
8693
8694 /*
8695 function reuseChildrenEffects(returnFiber : Fiber, firstChild : Fiber) {
8696 let child = firstChild;
8697 do {
8698 // Ensure that the first and last effect of the parent corresponds
8699 // to the children's first and last effect.
8700 if (!returnFiber.firstEffect) {
8701 returnFiber.firstEffect = child.firstEffect;
8702 }
8703 if (child.lastEffect) {
8704 if (returnFiber.lastEffect) {
8705 returnFiber.lastEffect.nextEffect = child.firstEffect;
8706 }
8707 returnFiber.lastEffect = child.lastEffect;
8708 }
8709 } while (child = child.sibling);
8710 }
8711 */
8712
8713 function bailoutOnAlreadyFinishedWork(current, workInProgress) {
8714 cancelWorkTimer(workInProgress);
8715
8716 // TODO: We should ideally be able to bail out early if the children have no
8717 // more work to do. However, since we don't have a separation of this
8718 // Fiber's priority and its children yet - we don't know without doing lots
8719 // of the same work we do anyway. Once we have that separation we can just
8720 // bail out here if the children has no more work at this priority level.
8721 // if (workInProgress.priorityOfChildren <= priorityLevel) {
8722 // // If there are side-effects in these children that have not yet been
8723 // // committed we need to ensure that they get properly transferred up.
8724 // if (current && current.child !== workInProgress.child) {
8725 // reuseChildrenEffects(workInProgress, child);
8726 // }
8727 // return null;
8728 // }
8729
8730 cloneChildFibers(current, workInProgress);
8731 return workInProgress.child;
8732 }
8733
8734 function bailoutOnLowPriority(current, workInProgress) {
8735 cancelWorkTimer(workInProgress);
8736
8737 // TODO: Handle HostComponent tags here as well and call pushHostContext()?
8738 // See PR 8590 discussion for context
8739 switch (workInProgress.tag) {
8740 case HostRoot:
8741 pushHostRootContext(workInProgress);
8742 break;
8743 case ClassComponent:
8744 pushContextProvider(workInProgress);
8745 break;
8746 case HostPortal:
8747 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
8748 break;
8749 }
8750 // TODO: What if this is currently in progress?
8751 // How can that happen? How is this not being cloned?
8752 return null;
8753 }
8754
8755 // TODO: Delete memoizeProps/State and move to reconcile/bailout instead
8756 function memoizeProps(workInProgress, nextProps) {
8757 workInProgress.memoizedProps = nextProps;
8758 }
8759
8760 function memoizeState(workInProgress, nextState) {
8761 workInProgress.memoizedState = nextState;
8762 // Don't reset the updateQueue, in case there are pending updates. Resetting
8763 // is handled by processUpdateQueue.
8764 }
8765
8766 function beginWork(current, workInProgress, renderExpirationTime) {
8767 if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
8768 return bailoutOnLowPriority(current, workInProgress);
8769 }
8770
8771 switch (workInProgress.tag) {
8772 case IndeterminateComponent:
8773 return mountIndeterminateComponent(current, workInProgress, renderExpirationTime);
8774 case FunctionalComponent:
8775 return updateFunctionalComponent(current, workInProgress);
8776 case ClassComponent:
8777 return updateClassComponent(current, workInProgress, renderExpirationTime);
8778 case HostRoot:
8779 return updateHostRoot(current, workInProgress, renderExpirationTime);
8780 case HostComponent:
8781 return updateHostComponent(current, workInProgress, renderExpirationTime);
8782 case HostText:
8783 return updateHostText(current, workInProgress);
8784 case CallHandlerPhase:
8785 // This is a restart. Reset the tag to the initial phase.
8786 workInProgress.tag = CallComponent;
8787 // Intentionally fall through since this is now the same.
8788 case CallComponent:
8789 return updateCallComponent(current, workInProgress, renderExpirationTime);
8790 case ReturnComponent:
8791 // A return component is just a placeholder, we can just run through the
8792 // next one immediately.
8793 return null;
8794 case HostPortal:
8795 return updatePortalComponent(current, workInProgress, renderExpirationTime);
8796 case Fragment:
8797 return updateFragment(current, workInProgress);
8798 default:
8799 invariant_1(false, 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.');
8800 }
8801 }
8802
8803 function beginFailedWork(current, workInProgress, renderExpirationTime) {
8804 // Push context providers here to avoid a push/pop context mismatch.
8805 switch (workInProgress.tag) {
8806 case ClassComponent:
8807 pushContextProvider(workInProgress);
8808 break;
8809 case HostRoot:
8810 pushHostRootContext(workInProgress);
8811 break;
8812 default:
8813 invariant_1(false, 'Invalid type of work. This error is likely caused by a bug in React. Please file an issue.');
8814 }
8815
8816 // Add an error effect so we can handle the error during the commit phase
8817 workInProgress.effectTag |= Err;
8818
8819 // This is a weird case where we do "resume" work ? work that failed on
8820 // our first attempt. Because we no longer have a notion of "progressed
8821 // deletions," reset the child to the current child to make sure we delete
8822 // it again. TODO: Find a better way to handle this, perhaps during a more
8823 // general overhaul of error handling.
8824 if (current === null) {
8825 workInProgress.child = null;
8826 } else if (workInProgress.child !== current.child) {
8827 workInProgress.child = current.child;
8828 }
8829
8830 if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
8831 return bailoutOnLowPriority(current, workInProgress);
8832 }
8833
8834 // If we don't bail out, we're going be recomputing our children so we need
8835 // to drop our effect list.
8836 workInProgress.firstEffect = null;
8837 workInProgress.lastEffect = null;
8838
8839 // Unmount the current children as if the component rendered null
8840 var nextChildren = null;
8841 reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, renderExpirationTime);
8842
8843 if (workInProgress.tag === ClassComponent) {
8844 var instance = workInProgress.stateNode;
8845 workInProgress.memoizedProps = instance.props;
8846 workInProgress.memoizedState = instance.state;
8847 }
8848
8849 return workInProgress.child;
8850 }
8851
8852 return {
8853 beginWork: beginWork,
8854 beginFailedWork: beginFailedWork
8855 };
8856};
8857
8858var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
8859 var createInstance = config.createInstance,
8860 createTextInstance = config.createTextInstance,
8861 appendInitialChild = config.appendInitialChild,
8862 finalizeInitialChildren = config.finalizeInitialChildren,
8863 prepareUpdate = config.prepareUpdate,
8864 mutation = config.mutation,
8865 persistence = config.persistence;
8866 var getRootHostContainer = hostContext.getRootHostContainer,
8867 popHostContext = hostContext.popHostContext,
8868 getHostContext = hostContext.getHostContext,
8869 popHostContainer = hostContext.popHostContainer;
8870 var prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance,
8871 prepareToHydrateHostTextInstance = hydrationContext.prepareToHydrateHostTextInstance,
8872 popHydrationState = hydrationContext.popHydrationState;
8873
8874
8875 function markUpdate(workInProgress) {
8876 // Tag the fiber with an update effect. This turns a Placement into
8877 // an UpdateAndPlacement.
8878 workInProgress.effectTag |= Update;
8879 }
8880
8881 function markRef(workInProgress) {
8882 workInProgress.effectTag |= Ref;
8883 }
8884
8885 function appendAllReturns(returns, workInProgress) {
8886 var node = workInProgress.stateNode;
8887 if (node) {
8888 node['return'] = workInProgress;
8889 }
8890 while (node !== null) {
8891 if (node.tag === HostComponent || node.tag === HostText || node.tag === HostPortal) {
8892 invariant_1(false, 'A call cannot have host component children.');
8893 } else if (node.tag === ReturnComponent) {
8894 returns.push(node.pendingProps.value);
8895 } else if (node.child !== null) {
8896 node.child['return'] = node;
8897 node = node.child;
8898 continue;
8899 }
8900 while (node.sibling === null) {
8901 if (node['return'] === null || node['return'] === workInProgress) {
8902 return;
8903 }
8904 node = node['return'];
8905 }
8906 node.sibling['return'] = node['return'];
8907 node = node.sibling;
8908 }
8909 }
8910
8911 function moveCallToHandlerPhase(current, workInProgress, renderExpirationTime) {
8912 var props = workInProgress.memoizedProps;
8913 !props ? invariant_1(false, 'Should be resolved by now. This error is likely caused by a bug in React. Please file an issue.') : void 0;
8914
8915 // First step of the call has completed. Now we need to do the second.
8916 // TODO: It would be nice to have a multi stage call represented by a
8917 // single component, or at least tail call optimize nested ones. Currently
8918 // that requires additional fields that we don't want to add to the fiber.
8919 // So this requires nested handlers.
8920 // Note: This doesn't mutate the alternate node. I don't think it needs to
8921 // since this stage is reset for every pass.
8922 workInProgress.tag = CallHandlerPhase;
8923
8924 // Build up the returns.
8925 // TODO: Compare this to a generator or opaque helpers like Children.
8926 var returns = [];
8927 appendAllReturns(returns, workInProgress);
8928 var fn = props.handler;
8929 var childProps = props.props;
8930 var nextChildren = fn(childProps, returns);
8931
8932 var currentFirstChild = current !== null ? current.child : null;
8933 workInProgress.child = reconcileChildFibers(workInProgress, currentFirstChild, nextChildren, renderExpirationTime);
8934 return workInProgress.child;
8935 }
8936
8937 function appendAllChildren(parent, workInProgress) {
8938 // We only have the top Fiber that was created but we need recurse down its
8939 // children to find all the terminal nodes.
8940 var node = workInProgress.child;
8941 while (node !== null) {
8942 if (node.tag === HostComponent || node.tag === HostText) {
8943 appendInitialChild(parent, node.stateNode);
8944 } else if (node.tag === HostPortal) {
8945 // If we have a portal child, then we don't want to traverse
8946 // down its children. Instead, we'll get insertions from each child in
8947 // the portal directly.
8948 } else if (node.child !== null) {
8949 node.child['return'] = node;
8950 node = node.child;
8951 continue;
8952 }
8953 if (node === workInProgress) {
8954 return;
8955 }
8956 while (node.sibling === null) {
8957 if (node['return'] === null || node['return'] === workInProgress) {
8958 return;
8959 }
8960 node = node['return'];
8961 }
8962 node.sibling['return'] = node['return'];
8963 node = node.sibling;
8964 }
8965 }
8966
8967 var updateHostContainer = void 0;
8968 var updateHostComponent = void 0;
8969 var updateHostText = void 0;
8970 if (mutation) {
8971 if (enableMutatingReconciler) {
8972 // Mutation mode
8973 updateHostContainer = function (workInProgress) {
8974 // Noop
8975 };
8976 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance) {
8977 // TODO: Type this specific to this type of component.
8978 workInProgress.updateQueue = updatePayload;
8979 // If the update payload indicates that there is a change or if there
8980 // is a new ref we mark this as an update. All the work is done in commitWork.
8981 if (updatePayload) {
8982 markUpdate(workInProgress);
8983 }
8984 };
8985 updateHostText = function (current, workInProgress, oldText, newText) {
8986 // If the text differs, mark it as an update. All the work in done in commitWork.
8987 if (oldText !== newText) {
8988 markUpdate(workInProgress);
8989 }
8990 };
8991 } else {
8992 invariant_1(false, 'Mutating reconciler is disabled.');
8993 }
8994 } else if (persistence) {
8995 if (enablePersistentReconciler) {
8996 // Persistent host tree mode
8997 var cloneInstance = persistence.cloneInstance,
8998 createContainerChildSet = persistence.createContainerChildSet,
8999 appendChildToContainerChildSet = persistence.appendChildToContainerChildSet,
9000 finalizeContainerChildren = persistence.finalizeContainerChildren;
9001
9002 // An unfortunate fork of appendAllChildren because we have two different parent types.
9003
9004 var appendAllChildrenToContainer = function (containerChildSet, workInProgress) {
9005 // We only have the top Fiber that was created but we need recurse down its
9006 // children to find all the terminal nodes.
9007 var node = workInProgress.child;
9008 while (node !== null) {
9009 if (node.tag === HostComponent || node.tag === HostText) {
9010 appendChildToContainerChildSet(containerChildSet, node.stateNode);
9011 } else if (node.tag === HostPortal) {
9012 // If we have a portal child, then we don't want to traverse
9013 // down its children. Instead, we'll get insertions from each child in
9014 // the portal directly.
9015 } else if (node.child !== null) {
9016 node.child['return'] = node;
9017 node = node.child;
9018 continue;
9019 }
9020 if (node === workInProgress) {
9021 return;
9022 }
9023 while (node.sibling === null) {
9024 if (node['return'] === null || node['return'] === workInProgress) {
9025 return;
9026 }
9027 node = node['return'];
9028 }
9029 node.sibling['return'] = node['return'];
9030 node = node.sibling;
9031 }
9032 };
9033 updateHostContainer = function (workInProgress) {
9034 var portalOrRoot = workInProgress.stateNode;
9035 var childrenUnchanged = workInProgress.firstEffect === null;
9036 if (childrenUnchanged) {
9037 // No changes, just reuse the existing instance.
9038 } else {
9039 var container = portalOrRoot.containerInfo;
9040 var newChildSet = createContainerChildSet(container);
9041 if (finalizeContainerChildren(container, newChildSet)) {
9042 markUpdate(workInProgress);
9043 }
9044 portalOrRoot.pendingChildren = newChildSet;
9045 // If children might have changed, we have to add them all to the set.
9046 appendAllChildrenToContainer(newChildSet, workInProgress);
9047 // Schedule an update on the container to swap out the container.
9048 markUpdate(workInProgress);
9049 }
9050 };
9051 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance) {
9052 // If there are no effects associated with this node, then none of our children had any updates.
9053 // This guarantees that we can reuse all of them.
9054 var childrenUnchanged = workInProgress.firstEffect === null;
9055 var currentInstance = current.stateNode;
9056 if (childrenUnchanged && updatePayload === null) {
9057 // No changes, just reuse the existing instance.
9058 // Note that this might release a previous clone.
9059 workInProgress.stateNode = currentInstance;
9060 } else {
9061 var recyclableInstance = workInProgress.stateNode;
9062 var newInstance = cloneInstance(currentInstance, updatePayload, type, oldProps, newProps, workInProgress, childrenUnchanged, recyclableInstance);
9063 if (finalizeInitialChildren(newInstance, type, newProps, rootContainerInstance)) {
9064 markUpdate(workInProgress);
9065 }
9066 workInProgress.stateNode = newInstance;
9067 if (childrenUnchanged) {
9068 // If there are no other effects in this tree, we need to flag this node as having one.
9069 // Even though we're not going to use it for anything.
9070 // Otherwise parents won't know that there are new children to propagate upwards.
9071 markUpdate(workInProgress);
9072 } else {
9073 // If children might have changed, we have to add them all to the set.
9074 appendAllChildren(newInstance, workInProgress);
9075 }
9076 }
9077 };
9078 updateHostText = function (current, workInProgress, oldText, newText) {
9079 if (oldText !== newText) {
9080 // If the text content differs, we'll create a new text instance for it.
9081 var rootContainerInstance = getRootHostContainer();
9082 var currentHostContext = getHostContext();
9083 workInProgress.stateNode = createTextInstance(newText, rootContainerInstance, currentHostContext, workInProgress);
9084 // We'll have to mark it as having an effect, even though we won't use the effect for anything.
9085 // This lets the parents know that at least one of their children has changed.
9086 markUpdate(workInProgress);
9087 }
9088 };
9089 } else {
9090 invariant_1(false, 'Persistent reconciler is disabled.');
9091 }
9092 } else {
9093 if (enableNoopReconciler) {
9094 // No host operations
9095 updateHostContainer = function (workInProgress) {
9096 // Noop
9097 };
9098 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance) {
9099 // Noop
9100 };
9101 updateHostText = function (current, workInProgress, oldText, newText) {
9102 // Noop
9103 };
9104 } else {
9105 invariant_1(false, 'Noop reconciler is disabled.');
9106 }
9107 }
9108
9109 function completeWork(current, workInProgress, renderExpirationTime) {
9110 var newProps = workInProgress.pendingProps;
9111 switch (workInProgress.tag) {
9112 case FunctionalComponent:
9113 return null;
9114 case ClassComponent:
9115 {
9116 // We are leaving this subtree, so pop context if any.
9117 popContextProvider(workInProgress);
9118 return null;
9119 }
9120 case HostRoot:
9121 {
9122 popHostContainer(workInProgress);
9123 popTopLevelContextObject(workInProgress);
9124 var fiberRoot = workInProgress.stateNode;
9125 if (fiberRoot.pendingContext) {
9126 fiberRoot.context = fiberRoot.pendingContext;
9127 fiberRoot.pendingContext = null;
9128 }
9129
9130 if (current === null || current.child === null) {
9131 // If we hydrated, pop so that we can delete any remaining children
9132 // that weren't hydrated.
9133 popHydrationState(workInProgress);
9134 // This resets the hacky state to fix isMounted before committing.
9135 // TODO: Delete this when we delete isMounted and findDOMNode.
9136 workInProgress.effectTag &= ~Placement;
9137 }
9138 updateHostContainer(workInProgress);
9139 return null;
9140 }
9141 case HostComponent:
9142 {
9143 popHostContext(workInProgress);
9144 var rootContainerInstance = getRootHostContainer();
9145 var type = workInProgress.type;
9146 if (current !== null && workInProgress.stateNode != null) {
9147 // If we have an alternate, that means this is an update and we need to
9148 // schedule a side-effect to do the updates.
9149 var oldProps = current.memoizedProps;
9150 // If we get updated because one of our children updated, we don't
9151 // have newProps so we'll have to reuse them.
9152 // TODO: Split the update API as separate for the props vs. children.
9153 // Even better would be if children weren't special cased at all tho.
9154 var instance = workInProgress.stateNode;
9155 var currentHostContext = getHostContext();
9156 var updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext);
9157
9158 updateHostComponent(current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance);
9159
9160 if (current.ref !== workInProgress.ref) {
9161 markRef(workInProgress);
9162 }
9163 } else {
9164 if (!newProps) {
9165 !(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;
9166 // This can happen when we abort work.
9167 return null;
9168 }
9169
9170 var _currentHostContext = getHostContext();
9171 // TODO: Move createInstance to beginWork and keep it on a context
9172 // "stack" as the parent. Then append children as we go in beginWork
9173 // or completeWork depending on we want to add then top->down or
9174 // bottom->up. Top->down is faster in IE11.
9175 var wasHydrated = popHydrationState(workInProgress);
9176 if (wasHydrated) {
9177 // TODO: Move this and createInstance step into the beginPhase
9178 // to consolidate.
9179 if (prepareToHydrateHostInstance(workInProgress, rootContainerInstance, _currentHostContext)) {
9180 // If changes to the hydrated node needs to be applied at the
9181 // commit-phase we mark this as such.
9182 markUpdate(workInProgress);
9183 }
9184 } else {
9185 var _instance = createInstance(type, newProps, rootContainerInstance, _currentHostContext, workInProgress);
9186
9187 appendAllChildren(_instance, workInProgress);
9188
9189 // Certain renderers require commit-time effects for initial mount.
9190 // (eg DOM renderer supports auto-focus for certain elements).
9191 // Make sure such renderers get scheduled for later work.
9192 if (finalizeInitialChildren(_instance, type, newProps, rootContainerInstance)) {
9193 markUpdate(workInProgress);
9194 }
9195 workInProgress.stateNode = _instance;
9196 }
9197
9198 if (workInProgress.ref !== null) {
9199 // If there is a ref on a host node we need to schedule a callback
9200 markRef(workInProgress);
9201 }
9202 }
9203 return null;
9204 }
9205 case HostText:
9206 {
9207 var newText = newProps;
9208 if (current && workInProgress.stateNode != null) {
9209 var oldText = current.memoizedProps;
9210 // If we have an alternate, that means this is an update and we need
9211 // to schedule a side-effect to do the updates.
9212 updateHostText(current, workInProgress, oldText, newText);
9213 } else {
9214 if (typeof newText !== 'string') {
9215 !(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;
9216 // This can happen when we abort work.
9217 return null;
9218 }
9219 var _rootContainerInstance = getRootHostContainer();
9220 var _currentHostContext2 = getHostContext();
9221 var _wasHydrated = popHydrationState(workInProgress);
9222 if (_wasHydrated) {
9223 if (prepareToHydrateHostTextInstance(workInProgress)) {
9224 markUpdate(workInProgress);
9225 }
9226 } else {
9227 workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext2, workInProgress);
9228 }
9229 }
9230 return null;
9231 }
9232 case CallComponent:
9233 return moveCallToHandlerPhase(current, workInProgress, renderExpirationTime);
9234 case CallHandlerPhase:
9235 // Reset the tag to now be a first phase call.
9236 workInProgress.tag = CallComponent;
9237 return null;
9238 case ReturnComponent:
9239 // Does nothing.
9240 return null;
9241 case Fragment:
9242 return null;
9243 case HostPortal:
9244 popHostContainer(workInProgress);
9245 updateHostContainer(workInProgress);
9246 return null;
9247 // Error cases
9248 case IndeterminateComponent:
9249 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.');
9250 // eslint-disable-next-line no-fallthrough
9251 default:
9252 invariant_1(false, 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.');
9253 }
9254 }
9255
9256 return {
9257 completeWork: completeWork
9258 };
9259};
9260
9261var invokeGuardedCallback$3 = ReactErrorUtils.invokeGuardedCallback;
9262var hasCaughtError$1 = ReactErrorUtils.hasCaughtError;
9263var clearCaughtError$1 = ReactErrorUtils.clearCaughtError;
9264
9265
9266var ReactFiberCommitWork = function (config, captureError) {
9267 var getPublicInstance = config.getPublicInstance,
9268 mutation = config.mutation,
9269 persistence = config.persistence;
9270
9271
9272 var callComponentWillUnmountWithTimer = function (current, instance) {
9273 startPhaseTimer(current, 'componentWillUnmount');
9274 instance.props = current.memoizedProps;
9275 instance.state = current.memoizedState;
9276 instance.componentWillUnmount();
9277 stopPhaseTimer();
9278 };
9279
9280 // Capture errors so they don't interrupt unmounting.
9281 function safelyCallComponentWillUnmount(current, instance) {
9282 {
9283 invokeGuardedCallback$3(null, callComponentWillUnmountWithTimer, null, current, instance);
9284 if (hasCaughtError$1()) {
9285 var unmountError = clearCaughtError$1();
9286 captureError(current, unmountError);
9287 }
9288 }
9289 }
9290
9291 function safelyDetachRef(current) {
9292 var ref = current.ref;
9293 if (ref !== null) {
9294 {
9295 invokeGuardedCallback$3(null, ref, null, null);
9296 if (hasCaughtError$1()) {
9297 var refError = clearCaughtError$1();
9298 captureError(current, refError);
9299 }
9300 }
9301 }
9302 }
9303
9304 function commitLifeCycles(current, finishedWork) {
9305 switch (finishedWork.tag) {
9306 case ClassComponent:
9307 {
9308 var instance = finishedWork.stateNode;
9309 if (finishedWork.effectTag & Update) {
9310 if (current === null) {
9311 startPhaseTimer(finishedWork, 'componentDidMount');
9312 instance.props = finishedWork.memoizedProps;
9313 instance.state = finishedWork.memoizedState;
9314 instance.componentDidMount();
9315 stopPhaseTimer();
9316 } else {
9317 var prevProps = current.memoizedProps;
9318 var prevState = current.memoizedState;
9319 startPhaseTimer(finishedWork, 'componentDidUpdate');
9320 instance.props = finishedWork.memoizedProps;
9321 instance.state = finishedWork.memoizedState;
9322 instance.componentDidUpdate(prevProps, prevState);
9323 stopPhaseTimer();
9324 }
9325 }
9326 var updateQueue = finishedWork.updateQueue;
9327 if (updateQueue !== null) {
9328 commitCallbacks(updateQueue, instance);
9329 }
9330 return;
9331 }
9332 case HostRoot:
9333 {
9334 var _updateQueue = finishedWork.updateQueue;
9335 if (_updateQueue !== null) {
9336 var _instance = finishedWork.child !== null ? finishedWork.child.stateNode : null;
9337 commitCallbacks(_updateQueue, _instance);
9338 }
9339 return;
9340 }
9341 case HostComponent:
9342 {
9343 var _instance2 = finishedWork.stateNode;
9344
9345 // Renderers may schedule work to be done after host components are mounted
9346 // (eg DOM renderer may schedule auto-focus for inputs and form controls).
9347 // These effects should only be committed when components are first mounted,
9348 // aka when there is no current/alternate.
9349 if (current === null && finishedWork.effectTag & Update) {
9350 var type = finishedWork.type;
9351 var props = finishedWork.memoizedProps;
9352 commitMount(_instance2, type, props, finishedWork);
9353 }
9354
9355 return;
9356 }
9357 case HostText:
9358 {
9359 // We have no life-cycles associated with text.
9360 return;
9361 }
9362 case HostPortal:
9363 {
9364 // We have no life-cycles associated with portals.
9365 return;
9366 }
9367 default:
9368 {
9369 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.');
9370 }
9371 }
9372 }
9373
9374 function commitAttachRef(finishedWork) {
9375 var ref = finishedWork.ref;
9376 if (ref !== null) {
9377 var instance = finishedWork.stateNode;
9378 switch (finishedWork.tag) {
9379 case HostComponent:
9380 ref(getPublicInstance(instance));
9381 break;
9382 default:
9383 ref(instance);
9384 }
9385 }
9386 }
9387
9388 function commitDetachRef(current) {
9389 var currentRef = current.ref;
9390 if (currentRef !== null) {
9391 currentRef(null);
9392 }
9393 }
9394
9395 // User-originating errors (lifecycles and refs) should not interrupt
9396 // deletion, so don't let them throw. Host-originating errors should
9397 // interrupt deletion, so it's okay
9398 function commitUnmount(current) {
9399 if (typeof onCommitUnmount === 'function') {
9400 onCommitUnmount(current);
9401 }
9402
9403 switch (current.tag) {
9404 case ClassComponent:
9405 {
9406 safelyDetachRef(current);
9407 var instance = current.stateNode;
9408 if (typeof instance.componentWillUnmount === 'function') {
9409 safelyCallComponentWillUnmount(current, instance);
9410 }
9411 return;
9412 }
9413 case HostComponent:
9414 {
9415 safelyDetachRef(current);
9416 return;
9417 }
9418 case CallComponent:
9419 {
9420 commitNestedUnmounts(current.stateNode);
9421 return;
9422 }
9423 case HostPortal:
9424 {
9425 // TODO: this is recursive.
9426 // We are also not using this parent because
9427 // the portal will get pushed immediately.
9428 if (enableMutatingReconciler && mutation) {
9429 unmountHostComponents(current);
9430 } else if (enablePersistentReconciler && persistence) {
9431 emptyPortalContainer(current);
9432 }
9433 return;
9434 }
9435 }
9436 }
9437
9438 function commitNestedUnmounts(root) {
9439 // While we're inside a removed host node we don't want to call
9440 // removeChild on the inner nodes because they're removed by the top
9441 // call anyway. We also want to call componentWillUnmount on all
9442 // composites before this host node is removed from the tree. Therefore
9443 var node = root;
9444 while (true) {
9445 commitUnmount(node);
9446 // Visit children because they may contain more composite or host nodes.
9447 // Skip portals because commitUnmount() currently visits them recursively.
9448 if (node.child !== null && (
9449 // If we use mutation we drill down into portals using commitUnmount above.
9450 // If we don't use mutation we drill down into portals here instead.
9451 !mutation || node.tag !== HostPortal)) {
9452 node.child['return'] = node;
9453 node = node.child;
9454 continue;
9455 }
9456 if (node === root) {
9457 return;
9458 }
9459 while (node.sibling === null) {
9460 if (node['return'] === null || node['return'] === root) {
9461 return;
9462 }
9463 node = node['return'];
9464 }
9465 node.sibling['return'] = node['return'];
9466 node = node.sibling;
9467 }
9468 }
9469
9470 function detachFiber(current) {
9471 // Cut off the return pointers to disconnect it from the tree. Ideally, we
9472 // should clear the child pointer of the parent alternate to let this
9473 // get GC:ed but we don't know which for sure which parent is the current
9474 // one so we'll settle for GC:ing the subtree of this child. This child
9475 // itself will be GC:ed when the parent updates the next time.
9476 current['return'] = null;
9477 current.child = null;
9478 if (current.alternate) {
9479 current.alternate.child = null;
9480 current.alternate['return'] = null;
9481 }
9482 }
9483
9484 var emptyPortalContainer = void 0;
9485
9486 if (!mutation) {
9487 var commitContainer = void 0;
9488 if (persistence) {
9489 var replaceContainerChildren = persistence.replaceContainerChildren,
9490 createContainerChildSet = persistence.createContainerChildSet;
9491
9492 emptyPortalContainer = function (current) {
9493 var portal = current.stateNode;
9494 var containerInfo = portal.containerInfo;
9495
9496 var emptyChildSet = createContainerChildSet(containerInfo);
9497 replaceContainerChildren(containerInfo, emptyChildSet);
9498 };
9499 commitContainer = function (finishedWork) {
9500 switch (finishedWork.tag) {
9501 case ClassComponent:
9502 {
9503 return;
9504 }
9505 case HostComponent:
9506 {
9507 return;
9508 }
9509 case HostText:
9510 {
9511 return;
9512 }
9513 case HostRoot:
9514 case HostPortal:
9515 {
9516 var portalOrRoot = finishedWork.stateNode;
9517 var containerInfo = portalOrRoot.containerInfo,
9518 _pendingChildren = portalOrRoot.pendingChildren;
9519
9520 replaceContainerChildren(containerInfo, _pendingChildren);
9521 return;
9522 }
9523 default:
9524 {
9525 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.');
9526 }
9527 }
9528 };
9529 } else {
9530 commitContainer = function (finishedWork) {
9531 // Noop
9532 };
9533 }
9534 if (enablePersistentReconciler || enableNoopReconciler) {
9535 return {
9536 commitResetTextContent: function (finishedWork) {},
9537 commitPlacement: function (finishedWork) {},
9538 commitDeletion: function (current) {
9539 // Detach refs and call componentWillUnmount() on the whole subtree.
9540 commitNestedUnmounts(current);
9541 detachFiber(current);
9542 },
9543 commitWork: function (current, finishedWork) {
9544 commitContainer(finishedWork);
9545 },
9546
9547 commitLifeCycles: commitLifeCycles,
9548 commitAttachRef: commitAttachRef,
9549 commitDetachRef: commitDetachRef
9550 };
9551 } else if (persistence) {
9552 invariant_1(false, 'Persistent reconciler is disabled.');
9553 } else {
9554 invariant_1(false, 'Noop reconciler is disabled.');
9555 }
9556 }
9557 var commitMount = mutation.commitMount,
9558 commitUpdate = mutation.commitUpdate,
9559 resetTextContent = mutation.resetTextContent,
9560 commitTextUpdate = mutation.commitTextUpdate,
9561 appendChild = mutation.appendChild,
9562 appendChildToContainer = mutation.appendChildToContainer,
9563 insertBefore = mutation.insertBefore,
9564 insertInContainerBefore = mutation.insertInContainerBefore,
9565 removeChild = mutation.removeChild,
9566 removeChildFromContainer = mutation.removeChildFromContainer;
9567
9568
9569 function getHostParentFiber(fiber) {
9570 var parent = fiber['return'];
9571 while (parent !== null) {
9572 if (isHostParent(parent)) {
9573 return parent;
9574 }
9575 parent = parent['return'];
9576 }
9577 invariant_1(false, 'Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue.');
9578 }
9579
9580 function isHostParent(fiber) {
9581 return fiber.tag === HostComponent || fiber.tag === HostRoot || fiber.tag === HostPortal;
9582 }
9583
9584 function getHostSibling(fiber) {
9585 // We're going to search forward into the tree until we find a sibling host
9586 // node. Unfortunately, if multiple insertions are done in a row we have to
9587 // search past them. This leads to exponential search for the next sibling.
9588 var node = fiber;
9589 siblings: while (true) {
9590 // If we didn't find anything, let's try the next sibling.
9591 while (node.sibling === null) {
9592 if (node['return'] === null || isHostParent(node['return'])) {
9593 // If we pop out of the root or hit the parent the fiber we are the
9594 // last sibling.
9595 return null;
9596 }
9597 node = node['return'];
9598 }
9599 node.sibling['return'] = node['return'];
9600 node = node.sibling;
9601 while (node.tag !== HostComponent && node.tag !== HostText) {
9602 // If it is not host node and, we might have a host node inside it.
9603 // Try to search down until we find one.
9604 if (node.effectTag & Placement) {
9605 // If we don't have a child, try the siblings instead.
9606 continue siblings;
9607 }
9608 // If we don't have a child, try the siblings instead.
9609 // We also skip portals because they are not part of this host tree.
9610 if (node.child === null || node.tag === HostPortal) {
9611 continue siblings;
9612 } else {
9613 node.child['return'] = node;
9614 node = node.child;
9615 }
9616 }
9617 // Check if this host node is stable or about to be placed.
9618 if (!(node.effectTag & Placement)) {
9619 // Found it!
9620 return node.stateNode;
9621 }
9622 }
9623 }
9624
9625 function commitPlacement(finishedWork) {
9626 // Recursively insert all host nodes into the parent.
9627 var parentFiber = getHostParentFiber(finishedWork);
9628 var parent = void 0;
9629 var isContainer = void 0;
9630 switch (parentFiber.tag) {
9631 case HostComponent:
9632 parent = parentFiber.stateNode;
9633 isContainer = false;
9634 break;
9635 case HostRoot:
9636 parent = parentFiber.stateNode.containerInfo;
9637 isContainer = true;
9638 break;
9639 case HostPortal:
9640 parent = parentFiber.stateNode.containerInfo;
9641 isContainer = true;
9642 break;
9643 default:
9644 invariant_1(false, 'Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue.');
9645 }
9646 if (parentFiber.effectTag & ContentReset) {
9647 // Reset the text content of the parent before doing any insertions
9648 resetTextContent(parent);
9649 // Clear ContentReset from the effect tag
9650 parentFiber.effectTag &= ~ContentReset;
9651 }
9652
9653 var before = getHostSibling(finishedWork);
9654 // We only have the top Fiber that was inserted but we need recurse down its
9655 // children to find all the terminal nodes.
9656 var node = finishedWork;
9657 while (true) {
9658 if (node.tag === HostComponent || node.tag === HostText) {
9659 if (before) {
9660 if (isContainer) {
9661 insertInContainerBefore(parent, node.stateNode, before);
9662 } else {
9663 insertBefore(parent, node.stateNode, before);
9664 }
9665 } else {
9666 if (isContainer) {
9667 appendChildToContainer(parent, node.stateNode);
9668 } else {
9669 appendChild(parent, node.stateNode);
9670 }
9671 }
9672 } else if (node.tag === HostPortal) {
9673 // If the insertion itself is a portal, then we don't want to traverse
9674 // down its children. Instead, we'll get insertions from each child in
9675 // the portal directly.
9676 } else if (node.child !== null) {
9677 node.child['return'] = node;
9678 node = node.child;
9679 continue;
9680 }
9681 if (node === finishedWork) {
9682 return;
9683 }
9684 while (node.sibling === null) {
9685 if (node['return'] === null || node['return'] === finishedWork) {
9686 return;
9687 }
9688 node = node['return'];
9689 }
9690 node.sibling['return'] = node['return'];
9691 node = node.sibling;
9692 }
9693 }
9694
9695 function unmountHostComponents(current) {
9696 // We only have the top Fiber that was inserted but we need recurse down its
9697 var node = current;
9698
9699 // Each iteration, currentParent is populated with node's host parent if not
9700 // currentParentIsValid.
9701 var currentParentIsValid = false;
9702 var currentParent = void 0;
9703 var currentParentIsContainer = void 0;
9704
9705 while (true) {
9706 if (!currentParentIsValid) {
9707 var parent = node['return'];
9708 findParent: while (true) {
9709 !(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;
9710 switch (parent.tag) {
9711 case HostComponent:
9712 currentParent = parent.stateNode;
9713 currentParentIsContainer = false;
9714 break findParent;
9715 case HostRoot:
9716 currentParent = parent.stateNode.containerInfo;
9717 currentParentIsContainer = true;
9718 break findParent;
9719 case HostPortal:
9720 currentParent = parent.stateNode.containerInfo;
9721 currentParentIsContainer = true;
9722 break findParent;
9723 }
9724 parent = parent['return'];
9725 }
9726 currentParentIsValid = true;
9727 }
9728
9729 if (node.tag === HostComponent || node.tag === HostText) {
9730 commitNestedUnmounts(node);
9731 // After all the children have unmounted, it is now safe to remove the
9732 // node from the tree.
9733 if (currentParentIsContainer) {
9734 removeChildFromContainer(currentParent, node.stateNode);
9735 } else {
9736 removeChild(currentParent, node.stateNode);
9737 }
9738 // Don't visit children because we already visited them.
9739 } else if (node.tag === HostPortal) {
9740 // When we go into a portal, it becomes the parent to remove from.
9741 // We will reassign it back when we pop the portal on the way up.
9742 currentParent = node.stateNode.containerInfo;
9743 // Visit children because portals might contain host components.
9744 if (node.child !== null) {
9745 node.child['return'] = node;
9746 node = node.child;
9747 continue;
9748 }
9749 } else {
9750 commitUnmount(node);
9751 // Visit children because we may find more host components below.
9752 if (node.child !== null) {
9753 node.child['return'] = node;
9754 node = node.child;
9755 continue;
9756 }
9757 }
9758 if (node === current) {
9759 return;
9760 }
9761 while (node.sibling === null) {
9762 if (node['return'] === null || node['return'] === current) {
9763 return;
9764 }
9765 node = node['return'];
9766 if (node.tag === HostPortal) {
9767 // When we go out of the portal, we need to restore the parent.
9768 // Since we don't keep a stack of them, we will search for it.
9769 currentParentIsValid = false;
9770 }
9771 }
9772 node.sibling['return'] = node['return'];
9773 node = node.sibling;
9774 }
9775 }
9776
9777 function commitDeletion(current) {
9778 // Recursively delete all host nodes from the parent.
9779 // Detach refs and call componentWillUnmount() on the whole subtree.
9780 unmountHostComponents(current);
9781 detachFiber(current);
9782 }
9783
9784 function commitWork(current, finishedWork) {
9785 switch (finishedWork.tag) {
9786 case ClassComponent:
9787 {
9788 return;
9789 }
9790 case HostComponent:
9791 {
9792 var instance = finishedWork.stateNode;
9793 if (instance != null) {
9794 // Commit the work prepared earlier.
9795 var newProps = finishedWork.memoizedProps;
9796 // For hydration we reuse the update path but we treat the oldProps
9797 // as the newProps. The updatePayload will contain the real change in
9798 // this case.
9799 var oldProps = current !== null ? current.memoizedProps : newProps;
9800 var type = finishedWork.type;
9801 // TODO: Type the updateQueue to be specific to host components.
9802 var updatePayload = finishedWork.updateQueue;
9803 finishedWork.updateQueue = null;
9804 if (updatePayload !== null) {
9805 commitUpdate(instance, updatePayload, type, oldProps, newProps, finishedWork);
9806 }
9807 }
9808 return;
9809 }
9810 case HostText:
9811 {
9812 !(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;
9813 var textInstance = finishedWork.stateNode;
9814 var newText = finishedWork.memoizedProps;
9815 // For hydration we reuse the update path but we treat the oldProps
9816 // as the newProps. The updatePayload will contain the real change in
9817 // this case.
9818 var oldText = current !== null ? current.memoizedProps : newText;
9819 commitTextUpdate(textInstance, oldText, newText);
9820 return;
9821 }
9822 case HostRoot:
9823 {
9824 return;
9825 }
9826 default:
9827 {
9828 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.');
9829 }
9830 }
9831 }
9832
9833 function commitResetTextContent(current) {
9834 resetTextContent(current.stateNode);
9835 }
9836
9837 if (enableMutatingReconciler) {
9838 return {
9839 commitResetTextContent: commitResetTextContent,
9840 commitPlacement: commitPlacement,
9841 commitDeletion: commitDeletion,
9842 commitWork: commitWork,
9843 commitLifeCycles: commitLifeCycles,
9844 commitAttachRef: commitAttachRef,
9845 commitDetachRef: commitDetachRef
9846 };
9847 } else {
9848 invariant_1(false, 'Mutating reconciler is disabled.');
9849 }
9850};
9851
9852var NO_CONTEXT = {};
9853
9854var ReactFiberHostContext = function (config) {
9855 var getChildHostContext = config.getChildHostContext,
9856 getRootHostContext = config.getRootHostContext;
9857
9858
9859 var contextStackCursor = createCursor(NO_CONTEXT);
9860 var contextFiberStackCursor = createCursor(NO_CONTEXT);
9861 var rootInstanceStackCursor = createCursor(NO_CONTEXT);
9862
9863 function requiredContext(c) {
9864 !(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;
9865 return c;
9866 }
9867
9868 function getRootHostContainer() {
9869 var rootInstance = requiredContext(rootInstanceStackCursor.current);
9870 return rootInstance;
9871 }
9872
9873 function pushHostContainer(fiber, nextRootInstance) {
9874 // Push current root instance onto the stack;
9875 // This allows us to reset root when portals are popped.
9876 push(rootInstanceStackCursor, nextRootInstance, fiber);
9877
9878 var nextRootContext = getRootHostContext(nextRootInstance);
9879
9880 // Track the context and the Fiber that provided it.
9881 // This enables us to pop only Fibers that provide unique contexts.
9882 push(contextFiberStackCursor, fiber, fiber);
9883 push(contextStackCursor, nextRootContext, fiber);
9884 }
9885
9886 function popHostContainer(fiber) {
9887 pop(contextStackCursor, fiber);
9888 pop(contextFiberStackCursor, fiber);
9889 pop(rootInstanceStackCursor, fiber);
9890 }
9891
9892 function getHostContext() {
9893 var context = requiredContext(contextStackCursor.current);
9894 return context;
9895 }
9896
9897 function pushHostContext(fiber) {
9898 var rootInstance = requiredContext(rootInstanceStackCursor.current);
9899 var context = requiredContext(contextStackCursor.current);
9900 var nextContext = getChildHostContext(context, fiber.type, rootInstance);
9901
9902 // Don't push this Fiber's context unless it's unique.
9903 if (context === nextContext) {
9904 return;
9905 }
9906
9907 // Track the context and the Fiber that provided it.
9908 // This enables us to pop only Fibers that provide unique contexts.
9909 push(contextFiberStackCursor, fiber, fiber);
9910 push(contextStackCursor, nextContext, fiber);
9911 }
9912
9913 function popHostContext(fiber) {
9914 // Do not pop unless this Fiber provided the current context.
9915 // pushHostContext() only pushes Fibers that provide unique contexts.
9916 if (contextFiberStackCursor.current !== fiber) {
9917 return;
9918 }
9919
9920 pop(contextStackCursor, fiber);
9921 pop(contextFiberStackCursor, fiber);
9922 }
9923
9924 function resetHostContainer() {
9925 contextStackCursor.current = NO_CONTEXT;
9926 rootInstanceStackCursor.current = NO_CONTEXT;
9927 }
9928
9929 return {
9930 getHostContext: getHostContext,
9931 getRootHostContainer: getRootHostContainer,
9932 popHostContainer: popHostContainer,
9933 popHostContext: popHostContext,
9934 pushHostContainer: pushHostContainer,
9935 pushHostContext: pushHostContext,
9936 resetHostContainer: resetHostContainer
9937 };
9938};
9939
9940var ReactFiberHydrationContext = function (config) {
9941 var shouldSetTextContent = config.shouldSetTextContent,
9942 hydration = config.hydration;
9943
9944 // If this doesn't have hydration mode.
9945
9946 if (!hydration) {
9947 return {
9948 enterHydrationState: function () {
9949 return false;
9950 },
9951 resetHydrationState: function () {},
9952 tryToClaimNextHydratableInstance: function () {},
9953 prepareToHydrateHostInstance: function () {
9954 invariant_1(false, 'Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.');
9955 },
9956 prepareToHydrateHostTextInstance: function () {
9957 invariant_1(false, 'Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.');
9958 },
9959 popHydrationState: function (fiber) {
9960 return false;
9961 }
9962 };
9963 }
9964
9965 var canHydrateInstance = hydration.canHydrateInstance,
9966 canHydrateTextInstance = hydration.canHydrateTextInstance,
9967 getNextHydratableSibling = hydration.getNextHydratableSibling,
9968 getFirstHydratableChild = hydration.getFirstHydratableChild,
9969 hydrateInstance = hydration.hydrateInstance,
9970 hydrateTextInstance = hydration.hydrateTextInstance,
9971 didNotMatchHydratedContainerTextInstance = hydration.didNotMatchHydratedContainerTextInstance,
9972 didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance,
9973 didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance,
9974 didNotHydrateInstance = hydration.didNotHydrateInstance,
9975 didNotFindHydratableContainerInstance = hydration.didNotFindHydratableContainerInstance,
9976 didNotFindHydratableContainerTextInstance = hydration.didNotFindHydratableContainerTextInstance,
9977 didNotFindHydratableInstance = hydration.didNotFindHydratableInstance,
9978 didNotFindHydratableTextInstance = hydration.didNotFindHydratableTextInstance;
9979
9980 // The deepest Fiber on the stack involved in a hydration context.
9981 // This may have been an insertion or a hydration.
9982
9983 var hydrationParentFiber = null;
9984 var nextHydratableInstance = null;
9985 var isHydrating = false;
9986
9987 function enterHydrationState(fiber) {
9988 var parentInstance = fiber.stateNode.containerInfo;
9989 nextHydratableInstance = getFirstHydratableChild(parentInstance);
9990 hydrationParentFiber = fiber;
9991 isHydrating = true;
9992 return true;
9993 }
9994
9995 function deleteHydratableInstance(returnFiber, instance) {
9996 {
9997 switch (returnFiber.tag) {
9998 case HostRoot:
9999 didNotHydrateContainerInstance(returnFiber.stateNode.containerInfo, instance);
10000 break;
10001 case HostComponent:
10002 didNotHydrateInstance(returnFiber.type, returnFiber.memoizedProps, returnFiber.stateNode, instance);
10003 break;
10004 }
10005 }
10006
10007 var childToDelete = createFiberFromHostInstanceForDeletion();
10008 childToDelete.stateNode = instance;
10009 childToDelete['return'] = returnFiber;
10010 childToDelete.effectTag = Deletion;
10011
10012 // This might seem like it belongs on progressedFirstDeletion. However,
10013 // these children are not part of the reconciliation list of children.
10014 // Even if we abort and rereconcile the children, that will try to hydrate
10015 // again and the nodes are still in the host tree so these will be
10016 // recreated.
10017 if (returnFiber.lastEffect !== null) {
10018 returnFiber.lastEffect.nextEffect = childToDelete;
10019 returnFiber.lastEffect = childToDelete;
10020 } else {
10021 returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
10022 }
10023 }
10024
10025 function insertNonHydratedInstance(returnFiber, fiber) {
10026 fiber.effectTag |= Placement;
10027 {
10028 switch (returnFiber.tag) {
10029 case HostRoot:
10030 {
10031 var parentContainer = returnFiber.stateNode.containerInfo;
10032 switch (fiber.tag) {
10033 case HostComponent:
10034 var type = fiber.type;
10035 var props = fiber.pendingProps;
10036 didNotFindHydratableContainerInstance(parentContainer, type, props);
10037 break;
10038 case HostText:
10039 var text = fiber.pendingProps;
10040 didNotFindHydratableContainerTextInstance(parentContainer, text);
10041 break;
10042 }
10043 break;
10044 }
10045 case HostComponent:
10046 {
10047 var parentType = returnFiber.type;
10048 var parentProps = returnFiber.memoizedProps;
10049 var parentInstance = returnFiber.stateNode;
10050 switch (fiber.tag) {
10051 case HostComponent:
10052 var _type = fiber.type;
10053 var _props = fiber.pendingProps;
10054 didNotFindHydratableInstance(parentType, parentProps, parentInstance, _type, _props);
10055 break;
10056 case HostText:
10057 var _text = fiber.pendingProps;
10058 didNotFindHydratableTextInstance(parentType, parentProps, parentInstance, _text);
10059 break;
10060 }
10061 break;
10062 }
10063 default:
10064 return;
10065 }
10066 }
10067 }
10068
10069 function tryHydrate(fiber, nextInstance) {
10070 switch (fiber.tag) {
10071 case HostComponent:
10072 {
10073 var type = fiber.type;
10074 var props = fiber.pendingProps;
10075 var instance = canHydrateInstance(nextInstance, type, props);
10076 if (instance !== null) {
10077 fiber.stateNode = instance;
10078 return true;
10079 }
10080 return false;
10081 }
10082 case HostText:
10083 {
10084 var text = fiber.pendingProps;
10085 var textInstance = canHydrateTextInstance(nextInstance, text);
10086 if (textInstance !== null) {
10087 fiber.stateNode = textInstance;
10088 return true;
10089 }
10090 return false;
10091 }
10092 default:
10093 return false;
10094 }
10095 }
10096
10097 function tryToClaimNextHydratableInstance(fiber) {
10098 if (!isHydrating) {
10099 return;
10100 }
10101 var nextInstance = nextHydratableInstance;
10102 if (!nextInstance) {
10103 // Nothing to hydrate. Make it an insertion.
10104 insertNonHydratedInstance(hydrationParentFiber, fiber);
10105 isHydrating = false;
10106 hydrationParentFiber = fiber;
10107 return;
10108 }
10109 if (!tryHydrate(fiber, nextInstance)) {
10110 // If we can't hydrate this instance let's try the next one.
10111 // We use this as a heuristic. It's based on intuition and not data so it
10112 // might be flawed or unnecessary.
10113 nextInstance = getNextHydratableSibling(nextInstance);
10114 if (!nextInstance || !tryHydrate(fiber, nextInstance)) {
10115 // Nothing to hydrate. Make it an insertion.
10116 insertNonHydratedInstance(hydrationParentFiber, fiber);
10117 isHydrating = false;
10118 hydrationParentFiber = fiber;
10119 return;
10120 }
10121 // We matched the next one, we'll now assume that the first one was
10122 // superfluous and we'll delete it. Since we can't eagerly delete it
10123 // we'll have to schedule a deletion. To do that, this node needs a dummy
10124 // fiber associated with it.
10125 deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance);
10126 }
10127 hydrationParentFiber = fiber;
10128 nextHydratableInstance = getFirstHydratableChild(nextInstance);
10129 }
10130
10131 function prepareToHydrateHostInstance(fiber, rootContainerInstance, hostContext) {
10132 var instance = fiber.stateNode;
10133 var updatePayload = hydrateInstance(instance, fiber.type, fiber.memoizedProps, rootContainerInstance, hostContext, fiber);
10134 // TODO: Type this specific to this type of component.
10135 fiber.updateQueue = updatePayload;
10136 // If the update payload indicates that there is a change or if there
10137 // is a new ref we mark this as an update.
10138 if (updatePayload !== null) {
10139 return true;
10140 }
10141 return false;
10142 }
10143
10144 function prepareToHydrateHostTextInstance(fiber) {
10145 var textInstance = fiber.stateNode;
10146 var textContent = fiber.memoizedProps;
10147 var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber);
10148 {
10149 if (shouldUpdate) {
10150 // We assume that prepareToHydrateHostTextInstance is called in a context where the
10151 // hydration parent is the parent host component of this host text.
10152 var returnFiber = hydrationParentFiber;
10153 if (returnFiber !== null) {
10154 switch (returnFiber.tag) {
10155 case HostRoot:
10156 {
10157 var parentContainer = returnFiber.stateNode.containerInfo;
10158 didNotMatchHydratedContainerTextInstance(parentContainer, textInstance, textContent);
10159 break;
10160 }
10161 case HostComponent:
10162 {
10163 var parentType = returnFiber.type;
10164 var parentProps = returnFiber.memoizedProps;
10165 var parentInstance = returnFiber.stateNode;
10166 didNotMatchHydratedTextInstance(parentType, parentProps, parentInstance, textInstance, textContent);
10167 break;
10168 }
10169 }
10170 }
10171 }
10172 }
10173 return shouldUpdate;
10174 }
10175
10176 function popToNextHostParent(fiber) {
10177 var parent = fiber['return'];
10178 while (parent !== null && parent.tag !== HostComponent && parent.tag !== HostRoot) {
10179 parent = parent['return'];
10180 }
10181 hydrationParentFiber = parent;
10182 }
10183
10184 function popHydrationState(fiber) {
10185 if (fiber !== hydrationParentFiber) {
10186 // We're deeper than the current hydration context, inside an inserted
10187 // tree.
10188 return false;
10189 }
10190 if (!isHydrating) {
10191 // If we're not currently hydrating but we're in a hydration context, then
10192 // we were an insertion and now need to pop up reenter hydration of our
10193 // siblings.
10194 popToNextHostParent(fiber);
10195 isHydrating = true;
10196 return false;
10197 }
10198
10199 var type = fiber.type;
10200
10201 // If we have any remaining hydratable nodes, we need to delete them now.
10202 // We only do this deeper than head and body since they tend to have random
10203 // other nodes in them. We also ignore components with pure text content in
10204 // side of them.
10205 // TODO: Better heuristic.
10206 if (fiber.tag !== HostComponent || type !== 'head' && type !== 'body' && !shouldSetTextContent(type, fiber.memoizedProps)) {
10207 var nextInstance = nextHydratableInstance;
10208 while (nextInstance) {
10209 deleteHydratableInstance(fiber, nextInstance);
10210 nextInstance = getNextHydratableSibling(nextInstance);
10211 }
10212 }
10213
10214 popToNextHostParent(fiber);
10215 nextHydratableInstance = hydrationParentFiber ? getNextHydratableSibling(fiber.stateNode) : null;
10216 return true;
10217 }
10218
10219 function resetHydrationState() {
10220 hydrationParentFiber = null;
10221 nextHydratableInstance = null;
10222 isHydrating = false;
10223 }
10224
10225 return {
10226 enterHydrationState: enterHydrationState,
10227 resetHydrationState: resetHydrationState,
10228 tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance,
10229 prepareToHydrateHostInstance: prepareToHydrateHostInstance,
10230 prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance,
10231 popHydrationState: popHydrationState
10232 };
10233};
10234
10235// This lets us hook into Fiber to debug what it's doing.
10236// See https://github.com/facebook/react/pull/8033.
10237// This is not part of the public API, not even for React DevTools.
10238// You may only inject a debugTool if you work on React Fiber itself.
10239var ReactFiberInstrumentation = {
10240 debugTool: null
10241};
10242
10243var ReactFiberInstrumentation_1 = ReactFiberInstrumentation;
10244
10245// This module is forked in different environments.
10246// By default, return `true` to log errors to the console.
10247// Forks can return `false` if this isn't desirable.
10248function showErrorDialog(capturedError) {
10249 return true;
10250}
10251
10252function logCapturedError(capturedError) {
10253 var logError = showErrorDialog(capturedError);
10254
10255 // Allow injected showErrorDialog() to prevent default console.error logging.
10256 // This enables renderers like ReactNative to better manage redbox behavior.
10257 if (logError === false) {
10258 return;
10259 }
10260
10261 var error = capturedError.error;
10262 var suppressLogging = error && error.suppressReactErrorLogging;
10263 if (suppressLogging) {
10264 return;
10265 }
10266
10267 {
10268 var componentName = capturedError.componentName,
10269 componentStack = capturedError.componentStack,
10270 errorBoundaryName = capturedError.errorBoundaryName,
10271 errorBoundaryFound = capturedError.errorBoundaryFound,
10272 willRetry = capturedError.willRetry;
10273
10274
10275 var componentNameMessage = componentName ? 'The above error occurred in the <' + componentName + '> component:' : 'The above error occurred in one of your React components:';
10276
10277 var errorBoundaryMessage = void 0;
10278 // errorBoundaryFound check is sufficient; errorBoundaryName check is to satisfy Flow.
10279 if (errorBoundaryFound && errorBoundaryName) {
10280 if (willRetry) {
10281 errorBoundaryMessage = 'React will try to recreate this component tree from scratch ' + ('using the error boundary you provided, ' + errorBoundaryName + '.');
10282 } else {
10283 errorBoundaryMessage = 'This error was initially handled by the error boundary ' + errorBoundaryName + '.\n' + 'Recreating the tree from scratch failed so React will unmount the tree.';
10284 }
10285 } else {
10286 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.';
10287 }
10288 var combinedMessage = '' + componentNameMessage + componentStack + '\n\n' + ('' + errorBoundaryMessage);
10289
10290 // In development, we provide our own message with just the component stack.
10291 // We don't include the original error message and JS stack because the browser
10292 // has already printed it. Even if the application swallows the error, it is still
10293 // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils.
10294 console.error(combinedMessage);
10295 }
10296}
10297
10298var invokeGuardedCallback$2 = ReactErrorUtils.invokeGuardedCallback;
10299var hasCaughtError = ReactErrorUtils.hasCaughtError;
10300var clearCaughtError = ReactErrorUtils.clearCaughtError;
10301
10302
10303var didWarnAboutStateTransition = void 0;
10304var didWarnSetStateChildContext = void 0;
10305var warnAboutUpdateOnUnmounted = void 0;
10306var warnAboutInvalidUpdates = void 0;
10307
10308{
10309 didWarnAboutStateTransition = false;
10310 didWarnSetStateChildContext = false;
10311 var didWarnStateUpdateForUnmountedComponent = {};
10312
10313 warnAboutUpdateOnUnmounted = function (fiber) {
10314 var componentName = getComponentName(fiber) || 'ReactClass';
10315 if (didWarnStateUpdateForUnmountedComponent[componentName]) {
10316 return;
10317 }
10318 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);
10319 didWarnStateUpdateForUnmountedComponent[componentName] = true;
10320 };
10321
10322 warnAboutInvalidUpdates = function (instance) {
10323 switch (ReactDebugCurrentFiber.phase) {
10324 case 'getChildContext':
10325 if (didWarnSetStateChildContext) {
10326 return;
10327 }
10328 warning_1(false, 'setState(...): Cannot call setState() inside getChildContext()');
10329 didWarnSetStateChildContext = true;
10330 break;
10331 case 'render':
10332 if (didWarnAboutStateTransition) {
10333 return;
10334 }
10335 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`.');
10336 didWarnAboutStateTransition = true;
10337 break;
10338 }
10339 };
10340}
10341
10342var ReactFiberScheduler = function (config) {
10343 var hostContext = ReactFiberHostContext(config);
10344 var hydrationContext = ReactFiberHydrationContext(config);
10345 var popHostContainer = hostContext.popHostContainer,
10346 popHostContext = hostContext.popHostContext,
10347 resetHostContainer = hostContext.resetHostContainer;
10348
10349 var _ReactFiberBeginWork = ReactFiberBeginWork(config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber),
10350 beginWork = _ReactFiberBeginWork.beginWork,
10351 beginFailedWork = _ReactFiberBeginWork.beginFailedWork;
10352
10353 var _ReactFiberCompleteWo = ReactFiberCompleteWork(config, hostContext, hydrationContext),
10354 completeWork = _ReactFiberCompleteWo.completeWork;
10355
10356 var _ReactFiberCommitWork = ReactFiberCommitWork(config, captureError),
10357 commitResetTextContent = _ReactFiberCommitWork.commitResetTextContent,
10358 commitPlacement = _ReactFiberCommitWork.commitPlacement,
10359 commitDeletion = _ReactFiberCommitWork.commitDeletion,
10360 commitWork = _ReactFiberCommitWork.commitWork,
10361 commitLifeCycles = _ReactFiberCommitWork.commitLifeCycles,
10362 commitAttachRef = _ReactFiberCommitWork.commitAttachRef,
10363 commitDetachRef = _ReactFiberCommitWork.commitDetachRef;
10364
10365 var now = config.now,
10366 scheduleDeferredCallback = config.scheduleDeferredCallback,
10367 cancelDeferredCallback = config.cancelDeferredCallback,
10368 useSyncScheduling = config.useSyncScheduling,
10369 prepareForCommit = config.prepareForCommit,
10370 resetAfterCommit = config.resetAfterCommit;
10371
10372 // Represents the current time in ms.
10373
10374 var startTime = now();
10375 var mostRecentCurrentTime = msToExpirationTime(0);
10376
10377 // Used to ensure computeUniqueAsyncExpiration is monotonically increases.
10378 var lastUniqueAsyncExpiration = 0;
10379
10380 // Represents the expiration time that incoming updates should use. (If this
10381 // is NoWork, use the default strategy: async updates in async mode, sync
10382 // updates in sync mode.)
10383 var expirationContext = NoWork;
10384
10385 var isWorking = false;
10386
10387 // The next work in progress fiber that we're currently working on.
10388 var nextUnitOfWork = null;
10389 var nextRoot = null;
10390 // The time at which we're currently rendering work.
10391 var nextRenderExpirationTime = NoWork;
10392
10393 // The next fiber with an effect that we're currently committing.
10394 var nextEffect = null;
10395
10396 // Keep track of which fibers have captured an error that need to be handled.
10397 // Work is removed from this collection after componentDidCatch is called.
10398 var capturedErrors = null;
10399 // Keep track of which fibers have failed during the current batch of work.
10400 // This is a different set than capturedErrors, because it is not reset until
10401 // the end of the batch. This is needed to propagate errors correctly if a
10402 // subtree fails more than once.
10403 var failedBoundaries = null;
10404 // Error boundaries that captured an error during the current commit.
10405 var commitPhaseBoundaries = null;
10406 var firstUncaughtError = null;
10407 var didFatal = false;
10408
10409 var isCommitting = false;
10410 var isUnmounting = false;
10411
10412 // Used for performance tracking.
10413 var interruptedBy = null;
10414
10415 function resetContextStack() {
10416 // Reset the stack
10417 reset$1();
10418 // Reset the cursors
10419 resetContext();
10420 resetHostContainer();
10421 }
10422
10423 function commitAllHostEffects() {
10424 while (nextEffect !== null) {
10425 {
10426 ReactDebugCurrentFiber.setCurrentFiber(nextEffect);
10427 }
10428 recordEffect();
10429
10430 var effectTag = nextEffect.effectTag;
10431 if (effectTag & ContentReset) {
10432 commitResetTextContent(nextEffect);
10433 }
10434
10435 if (effectTag & Ref) {
10436 var current = nextEffect.alternate;
10437 if (current !== null) {
10438 commitDetachRef(current);
10439 }
10440 }
10441
10442 // The following switch statement is only concerned about placement,
10443 // updates, and deletions. To avoid needing to add a case for every
10444 // possible bitmap value, we remove the secondary effects from the
10445 // effect tag and switch on that value.
10446 var primaryEffectTag = effectTag & ~(Callback | Err | ContentReset | Ref | PerformedWork);
10447 switch (primaryEffectTag) {
10448 case Placement:
10449 {
10450 commitPlacement(nextEffect);
10451 // Clear the "placement" from effect tag so that we know that this is inserted, before
10452 // any life-cycles like componentDidMount gets called.
10453 // TODO: findDOMNode doesn't rely on this any more but isMounted
10454 // does and isMounted is deprecated anyway so we should be able
10455 // to kill this.
10456 nextEffect.effectTag &= ~Placement;
10457 break;
10458 }
10459 case PlacementAndUpdate:
10460 {
10461 // Placement
10462 commitPlacement(nextEffect);
10463 // Clear the "placement" from effect tag so that we know that this is inserted, before
10464 // any life-cycles like componentDidMount gets called.
10465 nextEffect.effectTag &= ~Placement;
10466
10467 // Update
10468 var _current = nextEffect.alternate;
10469 commitWork(_current, nextEffect);
10470 break;
10471 }
10472 case Update:
10473 {
10474 var _current2 = nextEffect.alternate;
10475 commitWork(_current2, nextEffect);
10476 break;
10477 }
10478 case Deletion:
10479 {
10480 isUnmounting = true;
10481 commitDeletion(nextEffect);
10482 isUnmounting = false;
10483 break;
10484 }
10485 }
10486 nextEffect = nextEffect.nextEffect;
10487 }
10488
10489 {
10490 ReactDebugCurrentFiber.resetCurrentFiber();
10491 }
10492 }
10493
10494 function commitAllLifeCycles() {
10495 while (nextEffect !== null) {
10496 var effectTag = nextEffect.effectTag;
10497
10498 if (effectTag & (Update | Callback)) {
10499 recordEffect();
10500 var current = nextEffect.alternate;
10501 commitLifeCycles(current, nextEffect);
10502 }
10503
10504 if (effectTag & Ref) {
10505 recordEffect();
10506 commitAttachRef(nextEffect);
10507 }
10508
10509 if (effectTag & Err) {
10510 recordEffect();
10511 commitErrorHandling(nextEffect);
10512 }
10513
10514 var next = nextEffect.nextEffect;
10515 // Ensure that we clean these up so that we don't accidentally keep them.
10516 // I'm not actually sure this matters because we can't reset firstEffect
10517 // and lastEffect since they're on every node, not just the effectful
10518 // ones. So we have to clean everything as we reuse nodes anyway.
10519 nextEffect.nextEffect = null;
10520 // Ensure that we reset the effectTag here so that we can rely on effect
10521 // tags to reason about the current life-cycle.
10522 nextEffect = next;
10523 }
10524 }
10525
10526 function commitRoot(finishedWork) {
10527 // We keep track of this so that captureError can collect any boundaries
10528 // that capture an error during the commit phase. The reason these aren't
10529 // local to this function is because errors that occur during cWU are
10530 // captured elsewhere, to prevent the unmount from being interrupted.
10531 isWorking = true;
10532 isCommitting = true;
10533 startCommitTimer();
10534
10535 var root = finishedWork.stateNode;
10536 !(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;
10537 root.isReadyForCommit = false;
10538
10539 // Reset this to null before calling lifecycles
10540 ReactCurrentOwner.current = null;
10541
10542 var firstEffect = void 0;
10543 if (finishedWork.effectTag > PerformedWork) {
10544 // A fiber's effect list consists only of its children, not itself. So if
10545 // the root has an effect, we need to add it to the end of the list. The
10546 // resulting list is the set that would belong to the root's parent, if
10547 // it had one; that is, all the effects in the tree including the root.
10548 if (finishedWork.lastEffect !== null) {
10549 finishedWork.lastEffect.nextEffect = finishedWork;
10550 firstEffect = finishedWork.firstEffect;
10551 } else {
10552 firstEffect = finishedWork;
10553 }
10554 } else {
10555 // There is no effect on the root.
10556 firstEffect = finishedWork.firstEffect;
10557 }
10558
10559 prepareForCommit();
10560
10561 // Commit all the side-effects within a tree. We'll do this in two passes.
10562 // The first pass performs all the host insertions, updates, deletions and
10563 // ref unmounts.
10564 nextEffect = firstEffect;
10565 startCommitHostEffectsTimer();
10566 while (nextEffect !== null) {
10567 var didError = false;
10568 var _error = void 0;
10569 {
10570 invokeGuardedCallback$2(null, commitAllHostEffects, null);
10571 if (hasCaughtError()) {
10572 didError = true;
10573 _error = clearCaughtError();
10574 }
10575 }
10576 if (didError) {
10577 !(nextEffect !== null) ? invariant_1(false, 'Should have next effect. This error is likely caused by a bug in React. Please file an issue.') : void 0;
10578 captureError(nextEffect, _error);
10579 // Clean-up
10580 if (nextEffect !== null) {
10581 nextEffect = nextEffect.nextEffect;
10582 }
10583 }
10584 }
10585 stopCommitHostEffectsTimer();
10586
10587 resetAfterCommit();
10588
10589 // The work-in-progress tree is now the current tree. This must come after
10590 // the first pass of the commit phase, so that the previous tree is still
10591 // current during componentWillUnmount, but before the second pass, so that
10592 // the finished work is current during componentDidMount/Update.
10593 root.current = finishedWork;
10594
10595 // In the second pass we'll perform all life-cycles and ref callbacks.
10596 // Life-cycles happen as a separate pass so that all placements, updates,
10597 // and deletions in the entire tree have already been invoked.
10598 // This pass also triggers any renderer-specific initial effects.
10599 nextEffect = firstEffect;
10600 startCommitLifeCyclesTimer();
10601 while (nextEffect !== null) {
10602 var _didError = false;
10603 var _error2 = void 0;
10604 {
10605 invokeGuardedCallback$2(null, commitAllLifeCycles, null);
10606 if (hasCaughtError()) {
10607 _didError = true;
10608 _error2 = clearCaughtError();
10609 }
10610 }
10611 if (_didError) {
10612 !(nextEffect !== null) ? invariant_1(false, 'Should have next effect. This error is likely caused by a bug in React. Please file an issue.') : void 0;
10613 captureError(nextEffect, _error2);
10614 if (nextEffect !== null) {
10615 nextEffect = nextEffect.nextEffect;
10616 }
10617 }
10618 }
10619
10620 isCommitting = false;
10621 isWorking = false;
10622 stopCommitLifeCyclesTimer();
10623 stopCommitTimer();
10624 if (typeof onCommitRoot === 'function') {
10625 onCommitRoot(finishedWork.stateNode);
10626 }
10627 if (true && ReactFiberInstrumentation_1.debugTool) {
10628 ReactFiberInstrumentation_1.debugTool.onCommitWork(finishedWork);
10629 }
10630
10631 // If we caught any errors during this commit, schedule their boundaries
10632 // to update.
10633 if (commitPhaseBoundaries) {
10634 commitPhaseBoundaries.forEach(scheduleErrorRecovery);
10635 commitPhaseBoundaries = null;
10636 }
10637
10638 if (firstUncaughtError !== null) {
10639 var _error3 = firstUncaughtError;
10640 firstUncaughtError = null;
10641 onUncaughtError(_error3);
10642 }
10643
10644 var remainingTime = root.current.expirationTime;
10645
10646 if (remainingTime === NoWork) {
10647 capturedErrors = null;
10648 failedBoundaries = null;
10649 }
10650
10651 return remainingTime;
10652 }
10653
10654 function resetExpirationTime(workInProgress, renderTime) {
10655 if (renderTime !== Never && workInProgress.expirationTime === Never) {
10656 // The children of this component are hidden. Don't bubble their
10657 // expiration times.
10658 return;
10659 }
10660
10661 // Check for pending updates.
10662 var newExpirationTime = getUpdateExpirationTime(workInProgress);
10663
10664 // TODO: Calls need to visit stateNode
10665
10666 // Bubble up the earliest expiration time.
10667 var child = workInProgress.child;
10668 while (child !== null) {
10669 if (child.expirationTime !== NoWork && (newExpirationTime === NoWork || newExpirationTime > child.expirationTime)) {
10670 newExpirationTime = child.expirationTime;
10671 }
10672 child = child.sibling;
10673 }
10674 workInProgress.expirationTime = newExpirationTime;
10675 }
10676
10677 function completeUnitOfWork(workInProgress) {
10678 while (true) {
10679 // The current, flushed, state of this fiber is the alternate.
10680 // Ideally nothing should rely on this, but relying on it here
10681 // means that we don't need an additional field on the work in
10682 // progress.
10683 var current = workInProgress.alternate;
10684 {
10685 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10686 }
10687 var next = completeWork(current, workInProgress, nextRenderExpirationTime);
10688 {
10689 ReactDebugCurrentFiber.resetCurrentFiber();
10690 }
10691
10692 var returnFiber = workInProgress['return'];
10693 var siblingFiber = workInProgress.sibling;
10694
10695 resetExpirationTime(workInProgress, nextRenderExpirationTime);
10696
10697 if (next !== null) {
10698 stopWorkTimer(workInProgress);
10699 if (true && ReactFiberInstrumentation_1.debugTool) {
10700 ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress);
10701 }
10702 // If completing this work spawned new work, do that next. We'll come
10703 // back here again.
10704 return next;
10705 }
10706
10707 if (returnFiber !== null) {
10708 // Append all the effects of the subtree and this fiber onto the effect
10709 // list of the parent. The completion order of the children affects the
10710 // side-effect order.
10711 if (returnFiber.firstEffect === null) {
10712 returnFiber.firstEffect = workInProgress.firstEffect;
10713 }
10714 if (workInProgress.lastEffect !== null) {
10715 if (returnFiber.lastEffect !== null) {
10716 returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;
10717 }
10718 returnFiber.lastEffect = workInProgress.lastEffect;
10719 }
10720
10721 // If this fiber had side-effects, we append it AFTER the children's
10722 // side-effects. We can perform certain side-effects earlier if
10723 // needed, by doing multiple passes over the effect list. We don't want
10724 // to schedule our own side-effect on our own list because if end up
10725 // reusing children we'll schedule this effect onto itself since we're
10726 // at the end.
10727 var effectTag = workInProgress.effectTag;
10728 // Skip both NoWork and PerformedWork tags when creating the effect list.
10729 // PerformedWork effect is read by React DevTools but shouldn't be committed.
10730 if (effectTag > PerformedWork) {
10731 if (returnFiber.lastEffect !== null) {
10732 returnFiber.lastEffect.nextEffect = workInProgress;
10733 } else {
10734 returnFiber.firstEffect = workInProgress;
10735 }
10736 returnFiber.lastEffect = workInProgress;
10737 }
10738 }
10739
10740 stopWorkTimer(workInProgress);
10741 if (true && ReactFiberInstrumentation_1.debugTool) {
10742 ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress);
10743 }
10744
10745 if (siblingFiber !== null) {
10746 // If there is more work to do in this returnFiber, do that next.
10747 return siblingFiber;
10748 } else if (returnFiber !== null) {
10749 // If there's no more work in this returnFiber. Complete the returnFiber.
10750 workInProgress = returnFiber;
10751 continue;
10752 } else {
10753 // We've reached the root.
10754 var root = workInProgress.stateNode;
10755 root.isReadyForCommit = true;
10756 return null;
10757 }
10758 }
10759
10760 // Without this explicit null return Flow complains of invalid return type
10761 // TODO Remove the above while(true) loop
10762 // eslint-disable-next-line no-unreachable
10763 return null;
10764 }
10765
10766 function performUnitOfWork(workInProgress) {
10767 // The current, flushed, state of this fiber is the alternate.
10768 // Ideally nothing should rely on this, but relying on it here
10769 // means that we don't need an additional field on the work in
10770 // progress.
10771 var current = workInProgress.alternate;
10772
10773 // See if beginning this work spawns more work.
10774 startWorkTimer(workInProgress);
10775 {
10776 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10777 }
10778
10779 var next = beginWork(current, workInProgress, nextRenderExpirationTime);
10780 {
10781 ReactDebugCurrentFiber.resetCurrentFiber();
10782 }
10783 if (true && ReactFiberInstrumentation_1.debugTool) {
10784 ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
10785 }
10786
10787 if (next === null) {
10788 // If this doesn't spawn new work, complete the current work.
10789 next = completeUnitOfWork(workInProgress);
10790 }
10791
10792 ReactCurrentOwner.current = null;
10793
10794 return next;
10795 }
10796
10797 function performFailedUnitOfWork(workInProgress) {
10798 // The current, flushed, state of this fiber is the alternate.
10799 // Ideally nothing should rely on this, but relying on it here
10800 // means that we don't need an additional field on the work in
10801 // progress.
10802 var current = workInProgress.alternate;
10803
10804 // See if beginning this work spawns more work.
10805 startWorkTimer(workInProgress);
10806 {
10807 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10808 }
10809 var next = beginFailedWork(current, workInProgress, nextRenderExpirationTime);
10810 {
10811 ReactDebugCurrentFiber.resetCurrentFiber();
10812 }
10813 if (true && ReactFiberInstrumentation_1.debugTool) {
10814 ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
10815 }
10816
10817 if (next === null) {
10818 // If this doesn't spawn new work, complete the current work.
10819 next = completeUnitOfWork(workInProgress);
10820 }
10821
10822 ReactCurrentOwner.current = null;
10823
10824 return next;
10825 }
10826
10827 function workLoop(expirationTime) {
10828 if (capturedErrors !== null) {
10829 // If there are unhandled errors, switch to the slow work loop.
10830 // TODO: How to avoid this check in the fast path? Maybe the renderer
10831 // could keep track of which roots have unhandled errors and call a
10832 // forked version of renderRoot.
10833 slowWorkLoopThatChecksForFailedWork(expirationTime);
10834 return;
10835 }
10836 if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
10837 return;
10838 }
10839
10840 if (nextRenderExpirationTime <= mostRecentCurrentTime) {
10841 // Flush all expired work.
10842 while (nextUnitOfWork !== null) {
10843 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10844 }
10845 } else {
10846 // Flush asynchronous work until the deadline runs out of time.
10847 while (nextUnitOfWork !== null && !shouldYield()) {
10848 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10849 }
10850 }
10851 }
10852
10853 function slowWorkLoopThatChecksForFailedWork(expirationTime) {
10854 if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
10855 return;
10856 }
10857
10858 if (nextRenderExpirationTime <= mostRecentCurrentTime) {
10859 // Flush all expired work.
10860 while (nextUnitOfWork !== null) {
10861 if (hasCapturedError(nextUnitOfWork)) {
10862 // Use a forked version of performUnitOfWork
10863 nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork);
10864 } else {
10865 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10866 }
10867 }
10868 } else {
10869 // Flush asynchronous work until the deadline runs out of time.
10870 while (nextUnitOfWork !== null && !shouldYield()) {
10871 if (hasCapturedError(nextUnitOfWork)) {
10872 // Use a forked version of performUnitOfWork
10873 nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork);
10874 } else {
10875 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10876 }
10877 }
10878 }
10879 }
10880
10881 function renderRootCatchBlock(root, failedWork, boundary, expirationTime) {
10882 // We're going to restart the error boundary that captured the error.
10883 // Conceptually, we're unwinding the stack. We need to unwind the
10884 // context stack, too.
10885 unwindContexts(failedWork, boundary);
10886
10887 // Restart the error boundary using a forked version of
10888 // performUnitOfWork that deletes the boundary's children. The entire
10889 // failed subree will be unmounted. During the commit phase, a special
10890 // lifecycle method is called on the error boundary, which triggers
10891 // a re-render.
10892 nextUnitOfWork = performFailedUnitOfWork(boundary);
10893
10894 // Continue working.
10895 workLoop(expirationTime);
10896 }
10897
10898 function renderRoot(root, expirationTime) {
10899 !!isWorking ? invariant_1(false, 'renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
10900 isWorking = true;
10901
10902 // We're about to mutate the work-in-progress tree. If the root was pending
10903 // commit, it no longer is: we'll need to complete it again.
10904 root.isReadyForCommit = false;
10905
10906 // Check if we're starting from a fresh stack, or if we're resuming from
10907 // previously yielded work.
10908 if (root !== nextRoot || expirationTime !== nextRenderExpirationTime || nextUnitOfWork === null) {
10909 // Reset the stack and start working from the root.
10910 resetContextStack();
10911 nextRoot = root;
10912 nextRenderExpirationTime = expirationTime;
10913 nextUnitOfWork = createWorkInProgress(nextRoot.current, null, expirationTime);
10914 }
10915
10916 startWorkLoopTimer(nextUnitOfWork);
10917
10918 var didError = false;
10919 var error = null;
10920 {
10921 invokeGuardedCallback$2(null, workLoop, null, expirationTime);
10922 if (hasCaughtError()) {
10923 didError = true;
10924 error = clearCaughtError();
10925 }
10926 }
10927
10928 // An error was thrown during the render phase.
10929 while (didError) {
10930 if (didFatal) {
10931 // This was a fatal error. Don't attempt to recover from it.
10932 firstUncaughtError = error;
10933 break;
10934 }
10935
10936 var failedWork = nextUnitOfWork;
10937 if (failedWork === null) {
10938 // An error was thrown but there's no current unit of work. This can
10939 // happen during the commit phase if there's a bug in the renderer.
10940 didFatal = true;
10941 continue;
10942 }
10943
10944 // "Capture" the error by finding the nearest boundary. If there is no
10945 // error boundary, we use the root.
10946 var boundary = captureError(failedWork, error);
10947 !(boundary !== null) ? invariant_1(false, 'Should have found an error boundary. This error is likely caused by a bug in React. Please file an issue.') : void 0;
10948
10949 if (didFatal) {
10950 // The error we just captured was a fatal error. This happens
10951 // when the error propagates to the root more than once.
10952 continue;
10953 }
10954
10955 didError = false;
10956 error = null;
10957 {
10958 invokeGuardedCallback$2(null, renderRootCatchBlock, null, root, failedWork, boundary, expirationTime);
10959 if (hasCaughtError()) {
10960 didError = true;
10961 error = clearCaughtError();
10962 continue;
10963 }
10964 }
10965 // We're finished working. Exit the error loop.
10966 break;
10967 }
10968
10969 var uncaughtError = firstUncaughtError;
10970
10971 // We're done performing work. Time to clean up.
10972 stopWorkLoopTimer(interruptedBy);
10973 interruptedBy = null;
10974 isWorking = false;
10975 didFatal = false;
10976 firstUncaughtError = null;
10977
10978 if (uncaughtError !== null) {
10979 onUncaughtError(uncaughtError);
10980 }
10981
10982 return root.isReadyForCommit ? root.current.alternate : null;
10983 }
10984
10985 // Returns the boundary that captured the error, or null if the error is ignored
10986 function captureError(failedWork, error) {
10987 // It is no longer valid because we exited the user code.
10988 ReactCurrentOwner.current = null;
10989 {
10990 ReactDebugCurrentFiber.resetCurrentFiber();
10991 }
10992
10993 // Search for the nearest error boundary.
10994 var boundary = null;
10995
10996 // Passed to logCapturedError()
10997 var errorBoundaryFound = false;
10998 var willRetry = false;
10999 var errorBoundaryName = null;
11000
11001 // Host containers are a special case. If the failed work itself is a host
11002 // container, then it acts as its own boundary. In all other cases, we
11003 // ignore the work itself and only search through the parents.
11004 if (failedWork.tag === HostRoot) {
11005 boundary = failedWork;
11006
11007 if (isFailedBoundary(failedWork)) {
11008 // If this root already failed, there must have been an error when
11009 // attempting to unmount it. This is a worst-case scenario and
11010 // should only be possible if there's a bug in the renderer.
11011 didFatal = true;
11012 }
11013 } else {
11014 var node = failedWork['return'];
11015 while (node !== null && boundary === null) {
11016 if (node.tag === ClassComponent) {
11017 var instance = node.stateNode;
11018 if (typeof instance.componentDidCatch === 'function') {
11019 errorBoundaryFound = true;
11020 errorBoundaryName = getComponentName(node);
11021
11022 // Found an error boundary!
11023 boundary = node;
11024 willRetry = true;
11025 }
11026 } else if (node.tag === HostRoot) {
11027 // Treat the root like a no-op error boundary
11028 boundary = node;
11029 }
11030
11031 if (isFailedBoundary(node)) {
11032 // This boundary is already in a failed state.
11033
11034 // If we're currently unmounting, that means this error was
11035 // thrown while unmounting a failed subtree. We should ignore
11036 // the error.
11037 if (isUnmounting) {
11038 return null;
11039 }
11040
11041 // If we're in the commit phase, we should check to see if
11042 // this boundary already captured an error during this commit.
11043 // This case exists because multiple errors can be thrown during
11044 // a single commit without interruption.
11045 if (commitPhaseBoundaries !== null && (commitPhaseBoundaries.has(node) || node.alternate !== null && commitPhaseBoundaries.has(node.alternate))) {
11046 // If so, we should ignore this error.
11047 return null;
11048 }
11049
11050 // The error should propagate to the next boundary -? we keep looking.
11051 boundary = null;
11052 willRetry = false;
11053 }
11054
11055 node = node['return'];
11056 }
11057 }
11058
11059 if (boundary !== null) {
11060 // Add to the collection of failed boundaries. This lets us know that
11061 // subsequent errors in this subtree should propagate to the next boundary.
11062 if (failedBoundaries === null) {
11063 failedBoundaries = new Set();
11064 }
11065 failedBoundaries.add(boundary);
11066
11067 // This method is unsafe outside of the begin and complete phases.
11068 // We might be in the commit phase when an error is captured.
11069 // The risk is that the return path from this Fiber may not be accurate.
11070 // That risk is acceptable given the benefit of providing users more context.
11071 var _componentStack = getStackAddendumByWorkInProgressFiber(failedWork);
11072 var _componentName = getComponentName(failedWork);
11073
11074 // Add to the collection of captured errors. This is stored as a global
11075 // map of errors and their component stack location keyed by the boundaries
11076 // that capture them. We mostly use this Map as a Set; it's a Map only to
11077 // avoid adding a field to Fiber to store the error.
11078 if (capturedErrors === null) {
11079 capturedErrors = new Map();
11080 }
11081
11082 var capturedError = {
11083 componentName: _componentName,
11084 componentStack: _componentStack,
11085 error: error,
11086 errorBoundary: errorBoundaryFound ? boundary.stateNode : null,
11087 errorBoundaryFound: errorBoundaryFound,
11088 errorBoundaryName: errorBoundaryName,
11089 willRetry: willRetry
11090 };
11091
11092 capturedErrors.set(boundary, capturedError);
11093
11094 try {
11095 logCapturedError(capturedError);
11096 } catch (e) {
11097 // Prevent cycle if logCapturedError() throws.
11098 // A cycle may still occur if logCapturedError renders a component that throws.
11099 var suppressLogging = e && e.suppressReactErrorLogging;
11100 if (!suppressLogging) {
11101 console.error(e);
11102 }
11103 }
11104
11105 // If we're in the commit phase, defer scheduling an update on the
11106 // boundary until after the commit is complete
11107 if (isCommitting) {
11108 if (commitPhaseBoundaries === null) {
11109 commitPhaseBoundaries = new Set();
11110 }
11111 commitPhaseBoundaries.add(boundary);
11112 } else {
11113 // Otherwise, schedule an update now.
11114 // TODO: Is this actually necessary during the render phase? Is it
11115 // possible to unwind and continue rendering at the same priority,
11116 // without corrupting internal state?
11117 scheduleErrorRecovery(boundary);
11118 }
11119 return boundary;
11120 } else if (firstUncaughtError === null) {
11121 // If no boundary is found, we'll need to throw the error
11122 firstUncaughtError = error;
11123 }
11124 return null;
11125 }
11126
11127 function hasCapturedError(fiber) {
11128 // TODO: capturedErrors should store the boundary instance, to avoid needing
11129 // to check the alternate.
11130 return capturedErrors !== null && (capturedErrors.has(fiber) || fiber.alternate !== null && capturedErrors.has(fiber.alternate));
11131 }
11132
11133 function isFailedBoundary(fiber) {
11134 // TODO: failedBoundaries should store the boundary instance, to avoid
11135 // needing to check the alternate.
11136 return failedBoundaries !== null && (failedBoundaries.has(fiber) || fiber.alternate !== null && failedBoundaries.has(fiber.alternate));
11137 }
11138
11139 function commitErrorHandling(effectfulFiber) {
11140 var capturedError = void 0;
11141 if (capturedErrors !== null) {
11142 capturedError = capturedErrors.get(effectfulFiber);
11143 capturedErrors['delete'](effectfulFiber);
11144 if (capturedError == null) {
11145 if (effectfulFiber.alternate !== null) {
11146 effectfulFiber = effectfulFiber.alternate;
11147 capturedError = capturedErrors.get(effectfulFiber);
11148 capturedErrors['delete'](effectfulFiber);
11149 }
11150 }
11151 }
11152
11153 !(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;
11154
11155 switch (effectfulFiber.tag) {
11156 case ClassComponent:
11157 var instance = effectfulFiber.stateNode;
11158
11159 var info = {
11160 componentStack: capturedError.componentStack
11161 };
11162
11163 // Allow the boundary to handle the error, usually by scheduling
11164 // an update to itself
11165 instance.componentDidCatch(capturedError.error, info);
11166 return;
11167 case HostRoot:
11168 if (firstUncaughtError === null) {
11169 firstUncaughtError = capturedError.error;
11170 }
11171 return;
11172 default:
11173 invariant_1(false, 'Invalid type of work. This error is likely caused by a bug in React. Please file an issue.');
11174 }
11175 }
11176
11177 function unwindContexts(from, to) {
11178 var node = from;
11179 while (node !== null) {
11180 switch (node.tag) {
11181 case ClassComponent:
11182 popContextProvider(node);
11183 break;
11184 case HostComponent:
11185 popHostContext(node);
11186 break;
11187 case HostRoot:
11188 popHostContainer(node);
11189 break;
11190 case HostPortal:
11191 popHostContainer(node);
11192 break;
11193 }
11194 if (node === to || node.alternate === to) {
11195 stopFailedWorkTimer(node);
11196 break;
11197 } else {
11198 stopWorkTimer(node);
11199 }
11200 node = node['return'];
11201 }
11202 }
11203
11204 function computeAsyncExpiration() {
11205 // Given the current clock time, returns an expiration time. We use rounding
11206 // to batch like updates together.
11207 // Should complete within ~1000ms. 1200ms max.
11208 var currentTime = recalculateCurrentTime();
11209 var expirationMs = 1000;
11210 var bucketSizeMs = 200;
11211 return computeExpirationBucket(currentTime, expirationMs, bucketSizeMs);
11212 }
11213
11214 // Creates a unique async expiration time.
11215 function computeUniqueAsyncExpiration() {
11216 var result = computeAsyncExpiration();
11217 if (result <= lastUniqueAsyncExpiration) {
11218 // Since we assume the current time monotonically increases, we only hit
11219 // this branch when computeUniqueAsyncExpiration is fired multiple times
11220 // within a 200ms window (or whatever the async bucket size is).
11221 result = lastUniqueAsyncExpiration + 1;
11222 }
11223 lastUniqueAsyncExpiration = result;
11224 return lastUniqueAsyncExpiration;
11225 }
11226
11227 function computeExpirationForFiber(fiber) {
11228 var expirationTime = void 0;
11229 if (expirationContext !== NoWork) {
11230 // An explicit expiration context was set;
11231 expirationTime = expirationContext;
11232 } else if (isWorking) {
11233 if (isCommitting) {
11234 // Updates that occur during the commit phase should have sync priority
11235 // by default.
11236 expirationTime = Sync;
11237 } else {
11238 // Updates during the render phase should expire at the same time as
11239 // the work that is being rendered.
11240 expirationTime = nextRenderExpirationTime;
11241 }
11242 } else {
11243 // No explicit expiration context was set, and we're not currently
11244 // performing work. Calculate a new expiration time.
11245 if (useSyncScheduling && !(fiber.internalContextTag & AsyncUpdates)) {
11246 // This is a sync update
11247 expirationTime = Sync;
11248 } else {
11249 // This is an async update
11250 expirationTime = computeAsyncExpiration();
11251 }
11252 }
11253 return expirationTime;
11254 }
11255
11256 function scheduleWork(fiber, expirationTime) {
11257 return scheduleWorkImpl(fiber, expirationTime, false);
11258 }
11259
11260 function checkRootNeedsClearing(root, fiber, expirationTime) {
11261 if (!isWorking && root === nextRoot && expirationTime < nextRenderExpirationTime) {
11262 // Restart the root from the top.
11263 if (nextUnitOfWork !== null) {
11264 // This is an interruption. (Used for performance tracking.)
11265 interruptedBy = fiber;
11266 }
11267 nextRoot = null;
11268 nextUnitOfWork = null;
11269 nextRenderExpirationTime = NoWork;
11270 }
11271 }
11272
11273 function scheduleWorkImpl(fiber, expirationTime, isErrorRecovery) {
11274 recordScheduleUpdate();
11275
11276 {
11277 if (!isErrorRecovery && fiber.tag === ClassComponent) {
11278 var instance = fiber.stateNode;
11279 warnAboutInvalidUpdates(instance);
11280 }
11281 }
11282
11283 var node = fiber;
11284 while (node !== null) {
11285 // Walk the parent path to the root and update each node's
11286 // expiration time.
11287 if (node.expirationTime === NoWork || node.expirationTime > expirationTime) {
11288 node.expirationTime = expirationTime;
11289 }
11290 if (node.alternate !== null) {
11291 if (node.alternate.expirationTime === NoWork || node.alternate.expirationTime > expirationTime) {
11292 node.alternate.expirationTime = expirationTime;
11293 }
11294 }
11295 if (node['return'] === null) {
11296 if (node.tag === HostRoot) {
11297 var root = node.stateNode;
11298
11299 checkRootNeedsClearing(root, fiber, expirationTime);
11300 requestWork(root, expirationTime);
11301 checkRootNeedsClearing(root, fiber, expirationTime);
11302 } else {
11303 {
11304 if (!isErrorRecovery && fiber.tag === ClassComponent) {
11305 warnAboutUpdateOnUnmounted(fiber);
11306 }
11307 }
11308 return;
11309 }
11310 }
11311 node = node['return'];
11312 }
11313 }
11314
11315 function scheduleErrorRecovery(fiber) {
11316 scheduleWorkImpl(fiber, Sync, true);
11317 }
11318
11319 function recalculateCurrentTime() {
11320 // Subtract initial time so it fits inside 32bits
11321 var ms = now() - startTime;
11322 mostRecentCurrentTime = msToExpirationTime(ms);
11323 return mostRecentCurrentTime;
11324 }
11325
11326 function deferredUpdates(fn) {
11327 var previousExpirationContext = expirationContext;
11328 expirationContext = computeAsyncExpiration();
11329 try {
11330 return fn();
11331 } finally {
11332 expirationContext = previousExpirationContext;
11333 }
11334 }
11335
11336 function syncUpdates(fn) {
11337 var previousExpirationContext = expirationContext;
11338 expirationContext = Sync;
11339 try {
11340 return fn();
11341 } finally {
11342 expirationContext = previousExpirationContext;
11343 }
11344 }
11345
11346 // TODO: Everything below this is written as if it has been lifted to the
11347 // renderers. I'll do this in a follow-up.
11348
11349 // Linked-list of roots
11350 var firstScheduledRoot = null;
11351 var lastScheduledRoot = null;
11352
11353 var callbackExpirationTime = NoWork;
11354 var callbackID = -1;
11355 var isRendering = false;
11356 var nextFlushedRoot = null;
11357 var nextFlushedExpirationTime = NoWork;
11358 var deadlineDidExpire = false;
11359 var hasUnhandledError = false;
11360 var unhandledError = null;
11361 var deadline = null;
11362
11363 var isBatchingUpdates = false;
11364 var isUnbatchingUpdates = false;
11365
11366 var completedBatches = null;
11367
11368 // Use these to prevent an infinite loop of nested updates
11369 var NESTED_UPDATE_LIMIT = 1000;
11370 var nestedUpdateCount = 0;
11371
11372 var timeHeuristicForUnitOfWork = 1;
11373
11374 function scheduleCallbackWithExpiration(expirationTime) {
11375 if (callbackExpirationTime !== NoWork) {
11376 // A callback is already scheduled. Check its expiration time (timeout).
11377 if (expirationTime > callbackExpirationTime) {
11378 // Existing callback has sufficient timeout. Exit.
11379 return;
11380 } else {
11381 // Existing callback has insufficient timeout. Cancel and schedule a
11382 // new one.
11383 cancelDeferredCallback(callbackID);
11384 }
11385 // The request callback timer is already running. Don't start a new one.
11386 } else {
11387 startRequestCallbackTimer();
11388 }
11389
11390 // Compute a timeout for the given expiration time.
11391 var currentMs = now() - startTime;
11392 var expirationMs = expirationTimeToMs(expirationTime);
11393 var timeout = expirationMs - currentMs;
11394
11395 callbackExpirationTime = expirationTime;
11396 callbackID = scheduleDeferredCallback(performAsyncWork, { timeout: timeout });
11397 }
11398
11399 // requestWork is called by the scheduler whenever a root receives an update.
11400 // It's up to the renderer to call renderRoot at some point in the future.
11401 function requestWork(root, expirationTime) {
11402 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
11403 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.');
11404 }
11405
11406 // Add the root to the schedule.
11407 // Check if this root is already part of the schedule.
11408 if (root.nextScheduledRoot === null) {
11409 // This root is not already scheduled. Add it.
11410 root.remainingExpirationTime = expirationTime;
11411 if (lastScheduledRoot === null) {
11412 firstScheduledRoot = lastScheduledRoot = root;
11413 root.nextScheduledRoot = root;
11414 } else {
11415 lastScheduledRoot.nextScheduledRoot = root;
11416 lastScheduledRoot = root;
11417 lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
11418 }
11419 } else {
11420 // This root is already scheduled, but its priority may have increased.
11421 var remainingExpirationTime = root.remainingExpirationTime;
11422 if (remainingExpirationTime === NoWork || expirationTime < remainingExpirationTime) {
11423 // Update the priority.
11424 root.remainingExpirationTime = expirationTime;
11425 }
11426 }
11427
11428 if (isRendering) {
11429 // Prevent reentrancy. Remaining work will be scheduled at the end of
11430 // the currently rendering batch.
11431 return;
11432 }
11433
11434 if (isBatchingUpdates) {
11435 // Flush work at the end of the batch.
11436 if (isUnbatchingUpdates) {
11437 // ...unless we're inside unbatchedUpdates, in which case we should
11438 // flush it now.
11439 nextFlushedRoot = root;
11440 nextFlushedExpirationTime = Sync;
11441 performWorkOnRoot(root, Sync, recalculateCurrentTime());
11442 }
11443 return;
11444 }
11445
11446 // TODO: Get rid of Sync and use current time?
11447 if (expirationTime === Sync) {
11448 performWork(Sync, null);
11449 } else {
11450 scheduleCallbackWithExpiration(expirationTime);
11451 }
11452 }
11453
11454 function findHighestPriorityRoot() {
11455 var highestPriorityWork = NoWork;
11456 var highestPriorityRoot = null;
11457
11458 if (lastScheduledRoot !== null) {
11459 var previousScheduledRoot = lastScheduledRoot;
11460 var root = firstScheduledRoot;
11461 while (root !== null) {
11462 var remainingExpirationTime = root.remainingExpirationTime;
11463 if (remainingExpirationTime === NoWork) {
11464 // This root no longer has work. Remove it from the scheduler.
11465
11466 // TODO: This check is redudant, but Flow is confused by the branch
11467 // below where we set lastScheduledRoot to null, even though we break
11468 // from the loop right after.
11469 !(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;
11470 if (root === root.nextScheduledRoot) {
11471 // This is the only root in the list.
11472 root.nextScheduledRoot = null;
11473 firstScheduledRoot = lastScheduledRoot = null;
11474 break;
11475 } else if (root === firstScheduledRoot) {
11476 // This is the first root in the list.
11477 var next = root.nextScheduledRoot;
11478 firstScheduledRoot = next;
11479 lastScheduledRoot.nextScheduledRoot = next;
11480 root.nextScheduledRoot = null;
11481 } else if (root === lastScheduledRoot) {
11482 // This is the last root in the list.
11483 lastScheduledRoot = previousScheduledRoot;
11484 lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
11485 root.nextScheduledRoot = null;
11486 break;
11487 } else {
11488 previousScheduledRoot.nextScheduledRoot = root.nextScheduledRoot;
11489 root.nextScheduledRoot = null;
11490 }
11491 root = previousScheduledRoot.nextScheduledRoot;
11492 } else {
11493 if (highestPriorityWork === NoWork || remainingExpirationTime < highestPriorityWork) {
11494 // Update the priority, if it's higher
11495 highestPriorityWork = remainingExpirationTime;
11496 highestPriorityRoot = root;
11497 }
11498 if (root === lastScheduledRoot) {
11499 break;
11500 }
11501 previousScheduledRoot = root;
11502 root = root.nextScheduledRoot;
11503 }
11504 }
11505 }
11506
11507 // If the next root is the same as the previous root, this is a nested
11508 // update. To prevent an infinite loop, increment the nested update count.
11509 var previousFlushedRoot = nextFlushedRoot;
11510 if (previousFlushedRoot !== null && previousFlushedRoot === highestPriorityRoot) {
11511 nestedUpdateCount++;
11512 } else {
11513 // Reset whenever we switch roots.
11514 nestedUpdateCount = 0;
11515 }
11516 nextFlushedRoot = highestPriorityRoot;
11517 nextFlushedExpirationTime = highestPriorityWork;
11518 }
11519
11520 function performAsyncWork(dl) {
11521 performWork(NoWork, dl);
11522 }
11523
11524 function performWork(minExpirationTime, dl) {
11525 deadline = dl;
11526
11527 // Keep working on roots until there's no more work, or until the we reach
11528 // the deadline.
11529 findHighestPriorityRoot();
11530
11531 if (enableUserTimingAPI && deadline !== null) {
11532 var didExpire = nextFlushedExpirationTime < recalculateCurrentTime();
11533 stopRequestCallbackTimer(didExpire);
11534 }
11535
11536 while (nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && (minExpirationTime === NoWork || nextFlushedExpirationTime <= minExpirationTime) && !deadlineDidExpire) {
11537 performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, recalculateCurrentTime());
11538 // Find the next highest priority work.
11539 findHighestPriorityRoot();
11540 }
11541
11542 // We're done flushing work. Either we ran out of time in this callback,
11543 // or there's no more work left with sufficient priority.
11544
11545 // If we're inside a callback, set this to false since we just completed it.
11546 if (deadline !== null) {
11547 callbackExpirationTime = NoWork;
11548 callbackID = -1;
11549 }
11550 // If there's work left over, schedule a new callback.
11551 if (nextFlushedExpirationTime !== NoWork) {
11552 scheduleCallbackWithExpiration(nextFlushedExpirationTime);
11553 }
11554
11555 // Clean-up.
11556 deadline = null;
11557 deadlineDidExpire = false;
11558 nestedUpdateCount = 0;
11559
11560 finishRendering();
11561 }
11562
11563 function flushRoot(root, expirationTime) {
11564 !!isRendering ? invariant_1(false, 'work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method.') : void 0;
11565 // Perform work on root as if the given expiration time is the current time.
11566 // This has the effect of synchronously flushing all work up to and
11567 // including the given time.
11568 performWorkOnRoot(root, expirationTime, expirationTime);
11569 finishRendering();
11570 }
11571
11572 function finishRendering() {
11573 if (completedBatches !== null) {
11574 var batches = completedBatches;
11575 completedBatches = null;
11576 for (var i = 0; i < batches.length; i++) {
11577 var batch = batches[i];
11578 try {
11579 batch._onComplete();
11580 } catch (error) {
11581 if (!hasUnhandledError) {
11582 hasUnhandledError = true;
11583 unhandledError = error;
11584 }
11585 }
11586 }
11587 }
11588
11589 if (hasUnhandledError) {
11590 var _error4 = unhandledError;
11591 unhandledError = null;
11592 hasUnhandledError = false;
11593 throw _error4;
11594 }
11595 }
11596
11597 function performWorkOnRoot(root, expirationTime, currentTime) {
11598 !!isRendering ? invariant_1(false, 'performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
11599
11600 isRendering = true;
11601
11602 // Check if this is async work or sync/expired work.
11603 if (expirationTime <= currentTime) {
11604 // Flush sync work.
11605 var finishedWork = root.finishedWork;
11606 if (finishedWork !== null) {
11607 // This root is already complete. We can commit it.
11608 completeRoot(root, finishedWork, expirationTime);
11609 } else {
11610 root.finishedWork = null;
11611 finishedWork = renderRoot(root, expirationTime);
11612 if (finishedWork !== null) {
11613 // We've completed the root. Commit it.
11614 completeRoot(root, finishedWork, expirationTime);
11615 }
11616 }
11617 } else {
11618 // Flush async work.
11619 var _finishedWork = root.finishedWork;
11620 if (_finishedWork !== null) {
11621 // This root is already complete. We can commit it.
11622 completeRoot(root, _finishedWork, expirationTime);
11623 } else {
11624 root.finishedWork = null;
11625 _finishedWork = renderRoot(root, expirationTime);
11626 if (_finishedWork !== null) {
11627 // We've completed the root. Check the deadline one more time
11628 // before committing.
11629 if (!shouldYield()) {
11630 // Still time left. Commit the root.
11631 completeRoot(root, _finishedWork, expirationTime);
11632 } else {
11633 // There's no time left. Mark this root as complete. We'll come
11634 // back and commit it later.
11635 root.finishedWork = _finishedWork;
11636 }
11637 }
11638 }
11639 }
11640
11641 isRendering = false;
11642 }
11643
11644 function completeRoot(root, finishedWork, expirationTime) {
11645 // Check if there's a batch that matches this expiration time.
11646 var firstBatch = root.firstBatch;
11647 if (firstBatch !== null && firstBatch._expirationTime <= expirationTime) {
11648 if (completedBatches === null) {
11649 completedBatches = [firstBatch];
11650 } else {
11651 completedBatches.push(firstBatch);
11652 }
11653 if (firstBatch._defer) {
11654 // This root is blocked from committing by a batch. Unschedule it until
11655 // we receive another update.
11656 root.finishedWork = finishedWork;
11657 root.remainingExpirationTime = NoWork;
11658 return;
11659 }
11660 }
11661
11662 // Commit the root.
11663 root.finishedWork = null;
11664 root.remainingExpirationTime = commitRoot(finishedWork);
11665 }
11666
11667 // When working on async work, the reconciler asks the renderer if it should
11668 // yield execution. For DOM, we implement this with requestIdleCallback.
11669 function shouldYield() {
11670 if (deadline === null) {
11671 return false;
11672 }
11673 if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
11674 // Disregard deadline.didTimeout. Only expired work should be flushed
11675 // during a timeout. This path is only hit for non-expired work.
11676 return false;
11677 }
11678 deadlineDidExpire = true;
11679 return true;
11680 }
11681
11682 // TODO: Not happy about this hook. Conceptually, renderRoot should return a
11683 // tuple of (isReadyForCommit, didError, error)
11684 function onUncaughtError(error) {
11685 !(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;
11686 // Unschedule this root so we don't work on it again until there's
11687 // another update.
11688 nextFlushedRoot.remainingExpirationTime = NoWork;
11689 if (!hasUnhandledError) {
11690 hasUnhandledError = true;
11691 unhandledError = error;
11692 }
11693 }
11694
11695 // TODO: Batching should be implemented at the renderer level, not inside
11696 // the reconciler.
11697 function batchedUpdates(fn, a) {
11698 var previousIsBatchingUpdates = isBatchingUpdates;
11699 isBatchingUpdates = true;
11700 try {
11701 return fn(a);
11702 } finally {
11703 isBatchingUpdates = previousIsBatchingUpdates;
11704 if (!isBatchingUpdates && !isRendering) {
11705 performWork(Sync, null);
11706 }
11707 }
11708 }
11709
11710 // TODO: Batching should be implemented at the renderer level, not inside
11711 // the reconciler.
11712 function unbatchedUpdates(fn) {
11713 if (isBatchingUpdates && !isUnbatchingUpdates) {
11714 isUnbatchingUpdates = true;
11715 try {
11716 return fn();
11717 } finally {
11718 isUnbatchingUpdates = false;
11719 }
11720 }
11721 return fn();
11722 }
11723
11724 // TODO: Batching should be implemented at the renderer level, not within
11725 // the reconciler.
11726 function flushSync(fn) {
11727 var previousIsBatchingUpdates = isBatchingUpdates;
11728 isBatchingUpdates = true;
11729 try {
11730 return syncUpdates(fn);
11731 } finally {
11732 isBatchingUpdates = previousIsBatchingUpdates;
11733 !!isRendering ? invariant_1(false, 'flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.') : void 0;
11734 performWork(Sync, null);
11735 }
11736 }
11737
11738 return {
11739 computeExpirationForFiber: computeExpirationForFiber,
11740 scheduleWork: scheduleWork,
11741 requestWork: requestWork,
11742 flushRoot: flushRoot,
11743 batchedUpdates: batchedUpdates,
11744 unbatchedUpdates: unbatchedUpdates,
11745 flushSync: flushSync,
11746 deferredUpdates: deferredUpdates,
11747 computeUniqueAsyncExpiration: computeUniqueAsyncExpiration
11748 };
11749};
11750
11751var didWarnAboutNestedUpdates = void 0;
11752
11753{
11754 didWarnAboutNestedUpdates = false;
11755}
11756
11757// 0 is PROD, 1 is DEV.
11758// Might add PROFILE later.
11759
11760
11761function getContextForSubtree(parentComponent) {
11762 if (!parentComponent) {
11763 return emptyObject_1;
11764 }
11765
11766 var fiber = get(parentComponent);
11767 var parentContext = findCurrentUnmaskedContext(fiber);
11768 return isContextProvider(fiber) ? processChildContext(fiber, parentContext) : parentContext;
11769}
11770
11771var ReactFiberReconciler$1 = function (config) {
11772 var getPublicInstance = config.getPublicInstance;
11773
11774 var _ReactFiberScheduler = ReactFiberScheduler(config),
11775 computeUniqueAsyncExpiration = _ReactFiberScheduler.computeUniqueAsyncExpiration,
11776 computeExpirationForFiber = _ReactFiberScheduler.computeExpirationForFiber,
11777 scheduleWork = _ReactFiberScheduler.scheduleWork,
11778 requestWork = _ReactFiberScheduler.requestWork,
11779 flushRoot = _ReactFiberScheduler.flushRoot,
11780 batchedUpdates = _ReactFiberScheduler.batchedUpdates,
11781 unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates,
11782 flushSync = _ReactFiberScheduler.flushSync,
11783 deferredUpdates = _ReactFiberScheduler.deferredUpdates;
11784
11785 function scheduleRootUpdate(current, element, expirationTime, callback) {
11786 {
11787 if (ReactDebugCurrentFiber.phase === 'render' && ReactDebugCurrentFiber.current !== null && !didWarnAboutNestedUpdates) {
11788 didWarnAboutNestedUpdates = true;
11789 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');
11790 }
11791 }
11792
11793 callback = callback === undefined ? null : callback;
11794 {
11795 warning_1(callback === null || typeof callback === 'function', 'render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback);
11796 }
11797
11798 var update = {
11799 expirationTime: expirationTime,
11800 partialState: { element: element },
11801 callback: callback,
11802 isReplace: false,
11803 isForced: false,
11804 next: null
11805 };
11806 insertUpdateIntoFiber(current, update);
11807 scheduleWork(current, expirationTime);
11808
11809 return expirationTime;
11810 }
11811
11812 function updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback) {
11813 // TODO: If this is a nested container, this won't be the root.
11814 var current = container.current;
11815
11816 {
11817 if (ReactFiberInstrumentation_1.debugTool) {
11818 if (current.alternate === null) {
11819 ReactFiberInstrumentation_1.debugTool.onMountContainer(container);
11820 } else if (element === null) {
11821 ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container);
11822 } else {
11823 ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container);
11824 }
11825 }
11826 }
11827
11828 var context = getContextForSubtree(parentComponent);
11829 if (container.context === null) {
11830 container.context = context;
11831 } else {
11832 container.pendingContext = context;
11833 }
11834
11835 return scheduleRootUpdate(current, element, expirationTime, callback);
11836 }
11837
11838 function findHostInstance(fiber) {
11839 var hostFiber = findCurrentHostFiber(fiber);
11840 if (hostFiber === null) {
11841 return null;
11842 }
11843 return hostFiber.stateNode;
11844 }
11845
11846 return {
11847 createContainer: function (containerInfo, isAsync, hydrate) {
11848 return createFiberRoot(containerInfo, isAsync, hydrate);
11849 },
11850 updateContainer: function (element, container, parentComponent, callback) {
11851 var current = container.current;
11852 var expirationTime = computeExpirationForFiber(current);
11853 return updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback);
11854 },
11855
11856
11857 updateContainerAtExpirationTime: updateContainerAtExpirationTime,
11858
11859 flushRoot: flushRoot,
11860
11861 requestWork: requestWork,
11862
11863 computeUniqueAsyncExpiration: computeUniqueAsyncExpiration,
11864
11865 batchedUpdates: batchedUpdates,
11866
11867 unbatchedUpdates: unbatchedUpdates,
11868
11869 deferredUpdates: deferredUpdates,
11870
11871 flushSync: flushSync,
11872
11873 getPublicRootInstance: function (container) {
11874 var containerFiber = container.current;
11875 if (!containerFiber.child) {
11876 return null;
11877 }
11878 switch (containerFiber.child.tag) {
11879 case HostComponent:
11880 return getPublicInstance(containerFiber.child.stateNode);
11881 default:
11882 return containerFiber.child.stateNode;
11883 }
11884 },
11885
11886
11887 findHostInstance: findHostInstance,
11888
11889 findHostInstanceWithNoPortals: function (fiber) {
11890 var hostFiber = findCurrentHostFiberWithNoPortals(fiber);
11891 if (hostFiber === null) {
11892 return null;
11893 }
11894 return hostFiber.stateNode;
11895 },
11896 injectIntoDevTools: function (devToolsConfig) {
11897 var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance;
11898
11899 return injectInternals(_assign({}, devToolsConfig, {
11900 findHostInstanceByFiber: function (fiber) {
11901 return findHostInstance(fiber);
11902 },
11903 findFiberByHostInstance: function (instance) {
11904 if (!findFiberByHostInstance) {
11905 // Might not be implemented by the renderer.
11906 return null;
11907 }
11908 return findFiberByHostInstance(instance);
11909 }
11910 }));
11911 }
11912 };
11913};
11914
11915var ReactFiberReconciler$2 = Object.freeze({
11916 default: ReactFiberReconciler$1
11917});
11918
11919var ReactFiberReconciler$3 = ( ReactFiberReconciler$2 && ReactFiberReconciler$1 ) || ReactFiberReconciler$2;
11920
11921// TODO: bundle Flow types with the package.
11922
11923
11924
11925// TODO: decide on the top-level export form.
11926// This is hacky but makes it work with both Rollup and Jest.
11927var reactReconciler = ReactFiberReconciler$3['default'] ? ReactFiberReconciler$3['default'] : ReactFiberReconciler$3;
11928
11929function createPortal$1(children, containerInfo,
11930// TODO: figure out the API for cross-renderer implementation.
11931implementation) {
11932 var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
11933
11934 return {
11935 // This tag allow us to uniquely identify this as a React Portal
11936 $$typeof: REACT_PORTAL_TYPE,
11937 key: key == null ? null : '' + key,
11938 children: children,
11939 containerInfo: containerInfo,
11940 implementation: implementation
11941 };
11942}
11943
11944// TODO: this is special because it gets imported during build.
11945
11946var ReactVersion = '16.2.0';
11947
11948// a requestAnimationFrame, storing the time for the start of the frame, then
11949// scheduling a postMessage which gets scheduled after paint. Within the
11950// postMessage handler do as much work as possible until time + frame rate.
11951// By separating the idle call into a separate event tick we ensure that
11952// layout, paint and other browser work is counted against the available time.
11953// The frame rate is dynamically adjusted.
11954
11955{
11956 if (ExecutionEnvironment_1.canUseDOM && typeof requestAnimationFrame !== 'function') {
11957 warning_1(false, 'React depends on requestAnimationFrame. Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills');
11958 }
11959}
11960
11961var hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function';
11962
11963var now = void 0;
11964if (hasNativePerformanceNow) {
11965 now = function () {
11966 return performance.now();
11967 };
11968} else {
11969 now = function () {
11970 return Date.now();
11971 };
11972}
11973
11974// TODO: There's no way to cancel, because Fiber doesn't atm.
11975var rIC = void 0;
11976var cIC = void 0;
11977
11978if (!ExecutionEnvironment_1.canUseDOM) {
11979 rIC = function (frameCallback) {
11980 return setTimeout(function () {
11981 frameCallback({
11982 timeRemaining: function () {
11983 return Infinity;
11984 }
11985 });
11986 });
11987 };
11988 cIC = function (timeoutID) {
11989 clearTimeout(timeoutID);
11990 };
11991} else if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') {
11992 // Polyfill requestIdleCallback and cancelIdleCallback
11993
11994 var scheduledRICCallback = null;
11995 var isIdleScheduled = false;
11996 var timeoutTime = -1;
11997
11998 var isAnimationFrameScheduled = false;
11999
12000 var frameDeadline = 0;
12001 // We start out assuming that we run at 30fps but then the heuristic tracking
12002 // will adjust this value to a faster fps if we get more frequent animation
12003 // frames.
12004 var previousFrameTime = 33;
12005 var activeFrameTime = 33;
12006
12007 var frameDeadlineObject = void 0;
12008 if (hasNativePerformanceNow) {
12009 frameDeadlineObject = {
12010 didTimeout: false,
12011 timeRemaining: function () {
12012 // We assume that if we have a performance timer that the rAF callback
12013 // gets a performance timer value. Not sure if this is always true.
12014 var remaining = frameDeadline - performance.now();
12015 return remaining > 0 ? remaining : 0;
12016 }
12017 };
12018 } else {
12019 frameDeadlineObject = {
12020 didTimeout: false,
12021 timeRemaining: function () {
12022 // Fallback to Date.now()
12023 var remaining = frameDeadline - Date.now();
12024 return remaining > 0 ? remaining : 0;
12025 }
12026 };
12027 }
12028
12029 // We use the postMessage trick to defer idle work until after the repaint.
12030 var messageKey = '__reactIdleCallback$' + Math.random().toString(36).slice(2);
12031 var idleTick = function (event) {
12032 if (event.source !== window || event.data !== messageKey) {
12033 return;
12034 }
12035
12036 isIdleScheduled = false;
12037
12038 var currentTime = now();
12039 if (frameDeadline - currentTime <= 0) {
12040 // There's no time left in this idle period. Check if the callback has
12041 // a timeout and whether it's been exceeded.
12042 if (timeoutTime !== -1 && timeoutTime <= currentTime) {
12043 // Exceeded the timeout. Invoke the callback even though there's no
12044 // time left.
12045 frameDeadlineObject.didTimeout = true;
12046 } else {
12047 // No timeout.
12048 if (!isAnimationFrameScheduled) {
12049 // Schedule another animation callback so we retry later.
12050 isAnimationFrameScheduled = true;
12051 requestAnimationFrame(animationTick);
12052 }
12053 // Exit without invoking the callback.
12054 return;
12055 }
12056 } else {
12057 // There's still time left in this idle period.
12058 frameDeadlineObject.didTimeout = false;
12059 }
12060
12061 timeoutTime = -1;
12062 var callback = scheduledRICCallback;
12063 scheduledRICCallback = null;
12064 if (callback !== null) {
12065 callback(frameDeadlineObject);
12066 }
12067 };
12068 // Assumes that we have addEventListener in this environment. Might need
12069 // something better for old IE.
12070 window.addEventListener('message', idleTick, false);
12071
12072 var animationTick = function (rafTime) {
12073 isAnimationFrameScheduled = false;
12074 var nextFrameTime = rafTime - frameDeadline + activeFrameTime;
12075 if (nextFrameTime < activeFrameTime && previousFrameTime < activeFrameTime) {
12076 if (nextFrameTime < 8) {
12077 // Defensive coding. We don't support higher frame rates than 120hz.
12078 // If we get lower than that, it is probably a bug.
12079 nextFrameTime = 8;
12080 }
12081 // If one frame goes long, then the next one can be short to catch up.
12082 // If two frames are short in a row, then that's an indication that we
12083 // actually have a higher frame rate than what we're currently optimizing.
12084 // We adjust our heuristic dynamically accordingly. For example, if we're
12085 // running on 120hz display or 90hz VR display.
12086 // Take the max of the two in case one of them was an anomaly due to
12087 // missed frame deadlines.
12088 activeFrameTime = nextFrameTime < previousFrameTime ? previousFrameTime : nextFrameTime;
12089 } else {
12090 previousFrameTime = nextFrameTime;
12091 }
12092 frameDeadline = rafTime + activeFrameTime;
12093 if (!isIdleScheduled) {
12094 isIdleScheduled = true;
12095 window.postMessage(messageKey, '*');
12096 }
12097 };
12098
12099 rIC = function (callback, options) {
12100 // This assumes that we only schedule one callback at a time because that's
12101 // how Fiber uses it.
12102 scheduledRICCallback = callback;
12103 if (options != null && typeof options.timeout === 'number') {
12104 timeoutTime = now() + options.timeout;
12105 }
12106 if (!isAnimationFrameScheduled) {
12107 // If rAF didn't already schedule one, we need to schedule a frame.
12108 // TODO: If this rAF doesn't materialize because the browser throttles, we
12109 // might want to still have setTimeout trigger rIC as a backup to ensure
12110 // that we keep performing work.
12111 isAnimationFrameScheduled = true;
12112 requestAnimationFrame(animationTick);
12113 }
12114 return 0;
12115 };
12116
12117 cIC = function () {
12118 scheduledRICCallback = null;
12119 isIdleScheduled = false;
12120 timeoutTime = -1;
12121 };
12122} else {
12123 rIC = window.requestIdleCallback;
12124 cIC = window.cancelIdleCallback;
12125}
12126
12127var didWarnSelectedSetOnOption = false;
12128
12129function flattenChildren(children) {
12130 var content = '';
12131
12132 // Flatten children and warn if they aren't strings or numbers;
12133 // invalid types are ignored.
12134 // We can silently skip them because invalid DOM nesting warning
12135 // catches these cases in Fiber.
12136 React.Children.forEach(children, function (child) {
12137 if (child == null) {
12138 return;
12139 }
12140 if (typeof child === 'string' || typeof child === 'number') {
12141 content += child;
12142 }
12143 });
12144
12145 return content;
12146}
12147
12148/**
12149 * Implements an <option> host component that warns when `selected` is set.
12150 */
12151
12152function validateProps(element, props) {
12153 // TODO (yungsters): Remove support for `selected` in <option>.
12154 {
12155 if (props.selected != null && !didWarnSelectedSetOnOption) {
12156 warning_1(false, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.');
12157 didWarnSelectedSetOnOption = true;
12158 }
12159 }
12160}
12161
12162function postMountWrapper$1(element, props) {
12163 // value="" should make a value attribute (#6219)
12164 if (props.value != null) {
12165 element.setAttribute('value', props.value);
12166 }
12167}
12168
12169function getHostProps$1(element, props) {
12170 var hostProps = _assign({ children: undefined }, props);
12171 var content = flattenChildren(props.children);
12172
12173 if (content) {
12174 hostProps.children = content;
12175 }
12176
12177 return hostProps;
12178}
12179
12180// TODO: direct imports like some-package/src/* are bad. Fix me.
12181var getCurrentFiberOwnerName$3 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
12182var getCurrentFiberStackAddendum$4 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
12183
12184
12185var didWarnValueDefaultValue$1 = void 0;
12186
12187{
12188 didWarnValueDefaultValue$1 = false;
12189}
12190
12191function getDeclarationErrorAddendum() {
12192 var ownerName = getCurrentFiberOwnerName$3();
12193 if (ownerName) {
12194 return '\n\nCheck the render method of `' + ownerName + '`.';
12195 }
12196 return '';
12197}
12198
12199var valuePropNames = ['value', 'defaultValue'];
12200
12201/**
12202 * Validation function for `value` and `defaultValue`.
12203 */
12204function checkSelectPropTypes(props) {
12205 ReactControlledValuePropTypes.checkPropTypes('select', props, getCurrentFiberStackAddendum$4);
12206
12207 for (var i = 0; i < valuePropNames.length; i++) {
12208 var propName = valuePropNames[i];
12209 if (props[propName] == null) {
12210 continue;
12211 }
12212 var isArray = Array.isArray(props[propName]);
12213 if (props.multiple && !isArray) {
12214 warning_1(false, 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum());
12215 } else if (!props.multiple && isArray) {
12216 warning_1(false, 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum());
12217 }
12218 }
12219}
12220
12221function updateOptions(node, multiple, propValue, setDefaultSelected) {
12222 var options = node.options;
12223
12224 if (multiple) {
12225 var selectedValues = propValue;
12226 var selectedValue = {};
12227 for (var i = 0; i < selectedValues.length; i++) {
12228 // Prefix to avoid chaos with special keys.
12229 selectedValue['$' + selectedValues[i]] = true;
12230 }
12231 for (var _i = 0; _i < options.length; _i++) {
12232 var selected = selectedValue.hasOwnProperty('$' + options[_i].value);
12233 if (options[_i].selected !== selected) {
12234 options[_i].selected = selected;
12235 }
12236 if (selected && setDefaultSelected) {
12237 options[_i].defaultSelected = true;
12238 }
12239 }
12240 } else {
12241 // Do not set `select.value` as exact behavior isn't consistent across all
12242 // browsers for all cases.
12243 var _selectedValue = '' + propValue;
12244 var defaultSelected = null;
12245 for (var _i2 = 0; _i2 < options.length; _i2++) {
12246 if (options[_i2].value === _selectedValue) {
12247 options[_i2].selected = true;
12248 if (setDefaultSelected) {
12249 options[_i2].defaultSelected = true;
12250 }
12251 return;
12252 }
12253 if (defaultSelected === null && !options[_i2].disabled) {
12254 defaultSelected = options[_i2];
12255 }
12256 }
12257 if (defaultSelected !== null) {
12258 defaultSelected.selected = true;
12259 }
12260 }
12261}
12262
12263/**
12264 * Implements a <select> host component that allows optionally setting the
12265 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
12266 * stringable. If `multiple` is true, the prop must be an array of stringables.
12267 *
12268 * If `value` is not supplied (or null/undefined), user actions that change the
12269 * selected option will trigger updates to the rendered options.
12270 *
12271 * If it is supplied (and not null/undefined), the rendered options will not
12272 * update in response to user actions. Instead, the `value` prop must change in
12273 * order for the rendered options to update.
12274 *
12275 * If `defaultValue` is provided, any options with the supplied values will be
12276 * selected.
12277 */
12278
12279function getHostProps$2(element, props) {
12280 return _assign({}, props, {
12281 value: undefined
12282 });
12283}
12284
12285function initWrapperState$1(element, props) {
12286 var node = element;
12287 {
12288 checkSelectPropTypes(props);
12289 }
12290
12291 var value = props.value;
12292 node._wrapperState = {
12293 initialValue: value != null ? value : props.defaultValue,
12294 wasMultiple: !!props.multiple
12295 };
12296
12297 {
12298 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) {
12299 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');
12300 didWarnValueDefaultValue$1 = true;
12301 }
12302 }
12303}
12304
12305function postMountWrapper$2(element, props) {
12306 var node = element;
12307 node.multiple = !!props.multiple;
12308 var value = props.value;
12309 if (value != null) {
12310 updateOptions(node, !!props.multiple, value, false);
12311 } else if (props.defaultValue != null) {
12312 updateOptions(node, !!props.multiple, props.defaultValue, true);
12313 }
12314}
12315
12316function postUpdateWrapper(element, props) {
12317 var node = element;
12318 // After the initial mount, we control selected-ness manually so don't pass
12319 // this value down
12320 node._wrapperState.initialValue = undefined;
12321
12322 var wasMultiple = node._wrapperState.wasMultiple;
12323 node._wrapperState.wasMultiple = !!props.multiple;
12324
12325 var value = props.value;
12326 if (value != null) {
12327 updateOptions(node, !!props.multiple, value, false);
12328 } else if (wasMultiple !== !!props.multiple) {
12329 // For simplicity, reapply `defaultValue` if `multiple` is toggled.
12330 if (props.defaultValue != null) {
12331 updateOptions(node, !!props.multiple, props.defaultValue, true);
12332 } else {
12333 // Revert the select back to its default unselected state.
12334 updateOptions(node, !!props.multiple, props.multiple ? [] : '', false);
12335 }
12336 }
12337}
12338
12339function restoreControlledState$2(element, props) {
12340 var node = element;
12341 var value = props.value;
12342
12343 if (value != null) {
12344 updateOptions(node, !!props.multiple, value, false);
12345 }
12346}
12347
12348// TODO: direct imports like some-package/src/* are bad. Fix me.
12349var getCurrentFiberStackAddendum$5 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
12350
12351var didWarnValDefaultVal = false;
12352
12353/**
12354 * Implements a <textarea> host component that allows setting `value`, and
12355 * `defaultValue`. This differs from the traditional DOM API because value is
12356 * usually set as PCDATA children.
12357 *
12358 * If `value` is not supplied (or null/undefined), user actions that affect the
12359 * value will trigger updates to the element.
12360 *
12361 * If `value` is supplied (and not null/undefined), the rendered element will
12362 * not trigger updates to the element. Instead, the `value` prop must change in
12363 * order for the rendered element to be updated.
12364 *
12365 * The rendered element will be initialized with an empty value, the prop
12366 * `defaultValue` if specified, or the children content (deprecated).
12367 */
12368
12369function getHostProps$3(element, props) {
12370 var node = element;
12371 !(props.dangerouslySetInnerHTML == null) ? invariant_1(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : void 0;
12372
12373 // Always set children to the same thing. In IE9, the selection range will
12374 // get reset if `textContent` is mutated. We could add a check in setTextContent
12375 // to only set the value if/when the value differs from the node value (which would
12376 // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this
12377 // solution. The value can be a boolean or object so that's why it's forced
12378 // to be a string.
12379 var hostProps = _assign({}, props, {
12380 value: undefined,
12381 defaultValue: undefined,
12382 children: '' + node._wrapperState.initialValue
12383 });
12384
12385 return hostProps;
12386}
12387
12388function initWrapperState$2(element, props) {
12389 var node = element;
12390 {
12391 ReactControlledValuePropTypes.checkPropTypes('textarea', props, getCurrentFiberStackAddendum$5);
12392 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
12393 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');
12394 didWarnValDefaultVal = true;
12395 }
12396 }
12397
12398 var initialValue = props.value;
12399
12400 // Only bother fetching default value if we're going to use it
12401 if (initialValue == null) {
12402 var defaultValue = props.defaultValue;
12403 // TODO (yungsters): Remove support for children content in <textarea>.
12404 var children = props.children;
12405 if (children != null) {
12406 {
12407 warning_1(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.');
12408 }
12409 !(defaultValue == null) ? invariant_1(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : void 0;
12410 if (Array.isArray(children)) {
12411 !(children.length <= 1) ? invariant_1(false, '<textarea> can only have at most one child.') : void 0;
12412 children = children[0];
12413 }
12414
12415 defaultValue = '' + children;
12416 }
12417 if (defaultValue == null) {
12418 defaultValue = '';
12419 }
12420 initialValue = defaultValue;
12421 }
12422
12423 node._wrapperState = {
12424 initialValue: '' + initialValue
12425 };
12426}
12427
12428function updateWrapper$1(element, props) {
12429 var node = element;
12430 var value = props.value;
12431 if (value != null) {
12432 // Cast `value` to a string to ensure the value is set correctly. While
12433 // browsers typically do this as necessary, jsdom doesn't.
12434 var newValue = '' + value;
12435
12436 // To avoid side effects (such as losing text selection), only set value if changed
12437 if (newValue !== node.value) {
12438 node.value = newValue;
12439 }
12440 if (props.defaultValue == null) {
12441 node.defaultValue = newValue;
12442 }
12443 }
12444 if (props.defaultValue != null) {
12445 node.defaultValue = props.defaultValue;
12446 }
12447}
12448
12449function postMountWrapper$3(element, props) {
12450 var node = element;
12451 // This is in postMount because we need access to the DOM node, which is not
12452 // available until after the component has mounted.
12453 var textContent = node.textContent;
12454
12455 // Only set node.value if textContent is equal to the expected
12456 // initial value. In IE10/IE11 there is a bug where the placeholder attribute
12457 // will populate textContent as well.
12458 // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
12459 if (textContent === node._wrapperState.initialValue) {
12460 node.value = textContent;
12461 }
12462}
12463
12464function restoreControlledState$3(element, props) {
12465 // DOM component is still mounted; update
12466 updateWrapper$1(element, props);
12467}
12468
12469var HTML_NAMESPACE$1 = 'http://www.w3.org/1999/xhtml';
12470var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
12471var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
12472
12473var Namespaces = {
12474 html: HTML_NAMESPACE$1,
12475 mathml: MATH_NAMESPACE,
12476 svg: SVG_NAMESPACE
12477};
12478
12479// Assumes there is no parent namespace.
12480function getIntrinsicNamespace(type) {
12481 switch (type) {
12482 case 'svg':
12483 return SVG_NAMESPACE;
12484 case 'math':
12485 return MATH_NAMESPACE;
12486 default:
12487 return HTML_NAMESPACE$1;
12488 }
12489}
12490
12491function getChildNamespace(parentNamespace, type) {
12492 if (parentNamespace == null || parentNamespace === HTML_NAMESPACE$1) {
12493 // No (or default) parent namespace: potential entry point.
12494 return getIntrinsicNamespace(type);
12495 }
12496 if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') {
12497 // We're leaving SVG.
12498 return HTML_NAMESPACE$1;
12499 }
12500 // By default, pass namespace below.
12501 return parentNamespace;
12502}
12503
12504/* globals MSApp */
12505
12506/**
12507 * Create a function which has 'unsafe' privileges (required by windows8 apps)
12508 */
12509var createMicrosoftUnsafeLocalFunction = function (func) {
12510 if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
12511 return function (arg0, arg1, arg2, arg3) {
12512 MSApp.execUnsafeLocalFunction(function () {
12513 return func(arg0, arg1, arg2, arg3);
12514 });
12515 };
12516 } else {
12517 return func;
12518 }
12519};
12520
12521// SVG temp container for IE lacking innerHTML
12522var reusableSVGContainer = void 0;
12523
12524/**
12525 * Set the innerHTML property of a node
12526 *
12527 * @param {DOMElement} node
12528 * @param {string} html
12529 * @internal
12530 */
12531var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
12532 // IE does not have innerHTML for SVG nodes, so instead we inject the
12533 // new markup in a temp node and then move the child nodes across into
12534 // the target node
12535
12536 if (node.namespaceURI === Namespaces.svg && !('innerHTML' in node)) {
12537 reusableSVGContainer = reusableSVGContainer || document.createElement('div');
12538 reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
12539 var svgNode = reusableSVGContainer.firstChild;
12540 while (node.firstChild) {
12541 node.removeChild(node.firstChild);
12542 }
12543 while (svgNode.firstChild) {
12544 node.appendChild(svgNode.firstChild);
12545 }
12546 } else {
12547 node.innerHTML = html;
12548 }
12549});
12550
12551/**
12552 * Set the textContent property of a node, ensuring that whitespace is preserved
12553 * even in IE8. innerText is a poor substitute for textContent and, among many
12554 * issues, inserts <br> instead of the literal newline chars. innerHTML behaves
12555 * as it should.
12556 *
12557 * @param {DOMElement} node
12558 * @param {string} text
12559 * @internal
12560 */
12561var setTextContent = function (node, text) {
12562 if (text) {
12563 var firstChild = node.firstChild;
12564
12565 if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) {
12566 firstChild.nodeValue = text;
12567 return;
12568 }
12569 }
12570 node.textContent = text;
12571};
12572
12573/**
12574 * CSS properties which accept numbers but are not in units of "px".
12575 */
12576var isUnitlessNumber = {
12577 animationIterationCount: true,
12578 borderImageOutset: true,
12579 borderImageSlice: true,
12580 borderImageWidth: true,
12581 boxFlex: true,
12582 boxFlexGroup: true,
12583 boxOrdinalGroup: true,
12584 columnCount: true,
12585 columns: true,
12586 flex: true,
12587 flexGrow: true,
12588 flexPositive: true,
12589 flexShrink: true,
12590 flexNegative: true,
12591 flexOrder: true,
12592 gridRow: true,
12593 gridRowEnd: true,
12594 gridRowSpan: true,
12595 gridRowStart: true,
12596 gridColumn: true,
12597 gridColumnEnd: true,
12598 gridColumnSpan: true,
12599 gridColumnStart: true,
12600 fontWeight: true,
12601 lineClamp: true,
12602 lineHeight: true,
12603 opacity: true,
12604 order: true,
12605 orphans: true,
12606 tabSize: true,
12607 widows: true,
12608 zIndex: true,
12609 zoom: true,
12610
12611 // SVG-related properties
12612 fillOpacity: true,
12613 floodOpacity: true,
12614 stopOpacity: true,
12615 strokeDasharray: true,
12616 strokeDashoffset: true,
12617 strokeMiterlimit: true,
12618 strokeOpacity: true,
12619 strokeWidth: true
12620};
12621
12622/**
12623 * @param {string} prefix vendor-specific prefix, eg: Webkit
12624 * @param {string} key style name, eg: transitionDuration
12625 * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
12626 * WebkitTransitionDuration
12627 */
12628function prefixKey(prefix, key) {
12629 return prefix + key.charAt(0).toUpperCase() + key.substring(1);
12630}
12631
12632/**
12633 * Support style names that may come passed in prefixed by adding permutations
12634 * of vendor prefixes.
12635 */
12636var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
12637
12638// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
12639// infinite loop, because it iterates over the newly added props too.
12640Object.keys(isUnitlessNumber).forEach(function (prop) {
12641 prefixes.forEach(function (prefix) {
12642 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
12643 });
12644});
12645
12646/**
12647 * Convert a value into the proper css writable value. The style name `name`
12648 * should be logical (no hyphens), as specified
12649 * in `CSSProperty.isUnitlessNumber`.
12650 *
12651 * @param {string} name CSS property name such as `topMargin`.
12652 * @param {*} value CSS property value such as `10px`.
12653 * @return {string} Normalized style value with dimensions applied.
12654 */
12655function dangerousStyleValue(name, value, isCustomProperty) {
12656 // Note that we've removed escapeTextForBrowser() calls here since the
12657 // whole string will be escaped when the attribute is injected into
12658 // the markup. If you provide unsafe user data here they can inject
12659 // arbitrary CSS which may be problematic (I couldn't repro this):
12660 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
12661 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
12662 // This is not an XSS hole but instead a potential CSS injection issue
12663 // which has lead to a greater discussion about how we're going to
12664 // trust URLs moving forward. See #2115901
12665
12666 var isEmpty = value == null || typeof value === 'boolean' || value === '';
12667 if (isEmpty) {
12668 return '';
12669 }
12670
12671 if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) {
12672 return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
12673 }
12674
12675 return ('' + value).trim();
12676}
12677
12678/**
12679 * Copyright (c) 2013-present, Facebook, Inc.
12680 *
12681 * This source code is licensed under the MIT license found in the
12682 * LICENSE file in the root directory of this source tree.
12683 *
12684 * @typechecks
12685 */
12686
12687var _uppercasePattern = /([A-Z])/g;
12688
12689/**
12690 * Hyphenates a camelcased string, for example:
12691 *
12692 * > hyphenate('backgroundColor')
12693 * < "background-color"
12694 *
12695 * For CSS style names, use `hyphenateStyleName` instead which works properly
12696 * with all vendor prefixes, including `ms`.
12697 *
12698 * @param {string} string
12699 * @return {string}
12700 */
12701function hyphenate(string) {
12702 return string.replace(_uppercasePattern, '-$1').toLowerCase();
12703}
12704
12705var hyphenate_1 = hyphenate;
12706
12707/**
12708 * Copyright (c) 2013-present, Facebook, Inc.
12709 *
12710 * This source code is licensed under the MIT license found in the
12711 * LICENSE file in the root directory of this source tree.
12712 *
12713 * @typechecks
12714 */
12715
12716
12717
12718
12719
12720var msPattern = /^ms-/;
12721
12722/**
12723 * Hyphenates a camelcased CSS property name, for example:
12724 *
12725 * > hyphenateStyleName('backgroundColor')
12726 * < "background-color"
12727 * > hyphenateStyleName('MozTransition')
12728 * < "-moz-transition"
12729 * > hyphenateStyleName('msTransition')
12730 * < "-ms-transition"
12731 *
12732 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
12733 * is converted to `-ms-`.
12734 *
12735 * @param {string} string
12736 * @return {string}
12737 */
12738function hyphenateStyleName(string) {
12739 return hyphenate_1(string).replace(msPattern, '-ms-');
12740}
12741
12742var hyphenateStyleName_1 = hyphenateStyleName;
12743
12744/**
12745 * Copyright (c) 2013-present, Facebook, Inc.
12746 *
12747 * This source code is licensed under the MIT license found in the
12748 * LICENSE file in the root directory of this source tree.
12749 *
12750 * @typechecks
12751 */
12752
12753var _hyphenPattern = /-(.)/g;
12754
12755/**
12756 * Camelcases a hyphenated string, for example:
12757 *
12758 * > camelize('background-color')
12759 * < "backgroundColor"
12760 *
12761 * @param {string} string
12762 * @return {string}
12763 */
12764function camelize(string) {
12765 return string.replace(_hyphenPattern, function (_, character) {
12766 return character.toUpperCase();
12767 });
12768}
12769
12770var camelize_1 = camelize;
12771
12772/**
12773 * Copyright (c) 2013-present, Facebook, Inc.
12774 *
12775 * This source code is licensed under the MIT license found in the
12776 * LICENSE file in the root directory of this source tree.
12777 *
12778 * @typechecks
12779 */
12780
12781
12782
12783
12784
12785var msPattern$1 = /^-ms-/;
12786
12787/**
12788 * Camelcases a hyphenated CSS property name, for example:
12789 *
12790 * > camelizeStyleName('background-color')
12791 * < "backgroundColor"
12792 * > camelizeStyleName('-moz-transition')
12793 * < "MozTransition"
12794 * > camelizeStyleName('-ms-transition')
12795 * < "msTransition"
12796 *
12797 * As Andi Smith suggests
12798 * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
12799 * is converted to lowercase `ms`.
12800 *
12801 * @param {string} string
12802 * @return {string}
12803 */
12804function camelizeStyleName(string) {
12805 return camelize_1(string.replace(msPattern$1, 'ms-'));
12806}
12807
12808var camelizeStyleName_1 = camelizeStyleName;
12809
12810var warnValidStyle = emptyFunction_1;
12811
12812{
12813 // 'msTransform' is correct, but the other prefixes should be capitalized
12814 var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
12815
12816 // style values shouldn't contain a semicolon
12817 var badStyleValueWithSemicolonPattern = /;\s*$/;
12818
12819 var warnedStyleNames = {};
12820 var warnedStyleValues = {};
12821 var warnedForNaNValue = false;
12822 var warnedForInfinityValue = false;
12823
12824 var warnHyphenatedStyleName = function (name, getStack) {
12825 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
12826 return;
12827 }
12828
12829 warnedStyleNames[name] = true;
12830 warning_1(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName_1(name), getStack());
12831 };
12832
12833 var warnBadVendoredStyleName = function (name, getStack) {
12834 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
12835 return;
12836 }
12837
12838 warnedStyleNames[name] = true;
12839 warning_1(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), getStack());
12840 };
12841
12842 var warnStyleValueWithSemicolon = function (name, value, getStack) {
12843 if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
12844 return;
12845 }
12846
12847 warnedStyleValues[value] = true;
12848 warning_1(false, "Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.%s', name, value.replace(badStyleValueWithSemicolonPattern, ''), getStack());
12849 };
12850
12851 var warnStyleValueIsNaN = function (name, value, getStack) {
12852 if (warnedForNaNValue) {
12853 return;
12854 }
12855
12856 warnedForNaNValue = true;
12857 warning_1(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, getStack());
12858 };
12859
12860 var warnStyleValueIsInfinity = function (name, value, getStack) {
12861 if (warnedForInfinityValue) {
12862 return;
12863 }
12864
12865 warnedForInfinityValue = true;
12866 warning_1(false, '`Infinity` is an invalid value for the `%s` css style property.%s', name, getStack());
12867 };
12868
12869 warnValidStyle = function (name, value, getStack) {
12870 if (name.indexOf('-') > -1) {
12871 warnHyphenatedStyleName(name, getStack);
12872 } else if (badVendoredStyleNamePattern.test(name)) {
12873 warnBadVendoredStyleName(name, getStack);
12874 } else if (badStyleValueWithSemicolonPattern.test(value)) {
12875 warnStyleValueWithSemicolon(name, value, getStack);
12876 }
12877
12878 if (typeof value === 'number') {
12879 if (isNaN(value)) {
12880 warnStyleValueIsNaN(name, value, getStack);
12881 } else if (!isFinite(value)) {
12882 warnStyleValueIsInfinity(name, value, getStack);
12883 }
12884 }
12885 };
12886}
12887
12888var warnValidStyle$1 = warnValidStyle;
12889
12890/**
12891 * Operations for dealing with CSS properties.
12892 */
12893
12894/**
12895 * This creates a string that is expected to be equivalent to the style
12896 * attribute generated by server-side rendering. It by-passes warnings and
12897 * security checks so it's not safe to use this value for anything other than
12898 * comparison. It is only used in DEV for SSR validation.
12899 */
12900function createDangerousStringForStyles(styles) {
12901 {
12902 var serialized = '';
12903 var delimiter = '';
12904 for (var styleName in styles) {
12905 if (!styles.hasOwnProperty(styleName)) {
12906 continue;
12907 }
12908 var styleValue = styles[styleName];
12909 if (styleValue != null) {
12910 var isCustomProperty = styleName.indexOf('--') === 0;
12911 serialized += delimiter + hyphenateStyleName_1(styleName) + ':';
12912 serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty);
12913
12914 delimiter = ';';
12915 }
12916 }
12917 return serialized || null;
12918 }
12919}
12920
12921/**
12922 * Sets the value for multiple styles on a node. If a value is specified as
12923 * '' (empty string), the corresponding style property will be unset.
12924 *
12925 * @param {DOMElement} node
12926 * @param {object} styles
12927 */
12928function setValueForStyles(node, styles, getStack) {
12929 var style = node.style;
12930 for (var styleName in styles) {
12931 if (!styles.hasOwnProperty(styleName)) {
12932 continue;
12933 }
12934 var isCustomProperty = styleName.indexOf('--') === 0;
12935 {
12936 if (!isCustomProperty) {
12937 warnValidStyle$1(styleName, styles[styleName], getStack);
12938 }
12939 }
12940 var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty);
12941 if (styleName === 'float') {
12942 styleName = 'cssFloat';
12943 }
12944 if (isCustomProperty) {
12945 style.setProperty(styleName, styleValue);
12946 } else {
12947 style[styleName] = styleValue;
12948 }
12949 }
12950}
12951
12952// For HTML, certain tags should omit their close tag. We keep a whitelist for
12953// those special-case tags.
12954
12955var omittedCloseTags = {
12956 area: true,
12957 base: true,
12958 br: true,
12959 col: true,
12960 embed: true,
12961 hr: true,
12962 img: true,
12963 input: true,
12964 keygen: true,
12965 link: true,
12966 meta: true,
12967 param: true,
12968 source: true,
12969 track: true,
12970 wbr: true
12971};
12972
12973// For HTML, certain tags cannot have children. This has the same purpose as
12974// `omittedCloseTags` except that `menuitem` should still have its closing tag.
12975
12976var voidElementTags = _assign({
12977 menuitem: true
12978}, omittedCloseTags);
12979
12980var HTML$1 = '__html';
12981
12982function assertValidProps(tag, props, getStack) {
12983 if (!props) {
12984 return;
12985 }
12986 // Note the use of `==` which checks for null or undefined.
12987 if (voidElementTags[tag]) {
12988 !(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;
12989 }
12990 if (props.dangerouslySetInnerHTML != null) {
12991 !(props.children == null) ? invariant_1(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : void 0;
12992 !(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;
12993 }
12994 {
12995 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());
12996 }
12997 !(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;
12998}
12999
13000function isCustomComponent(tagName, props) {
13001 if (tagName.indexOf('-') === -1) {
13002 return typeof props.is === 'string';
13003 }
13004 switch (tagName) {
13005 // These are reserved SVG and MathML elements.
13006 // We don't mind this whitelist too much because we expect it to never grow.
13007 // The alternative is to track the namespace in a few places which is convoluted.
13008 // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
13009 case 'annotation-xml':
13010 case 'color-profile':
13011 case 'font-face':
13012 case 'font-face-src':
13013 case 'font-face-uri':
13014 case 'font-face-format':
13015 case 'font-face-name':
13016 case 'missing-glyph':
13017 return false;
13018 default:
13019 return true;
13020 }
13021}
13022
13023// When adding attributes to the HTML or SVG whitelist, be sure to
13024// also add them to this module to ensure casing and incorrect name
13025// warnings.
13026var possibleStandardNames = {
13027 // HTML
13028 accept: 'accept',
13029 acceptcharset: 'acceptCharset',
13030 'accept-charset': 'acceptCharset',
13031 accesskey: 'accessKey',
13032 action: 'action',
13033 allowfullscreen: 'allowFullScreen',
13034 alt: 'alt',
13035 as: 'as',
13036 async: 'async',
13037 autocapitalize: 'autoCapitalize',
13038 autocomplete: 'autoComplete',
13039 autocorrect: 'autoCorrect',
13040 autofocus: 'autoFocus',
13041 autoplay: 'autoPlay',
13042 autosave: 'autoSave',
13043 capture: 'capture',
13044 cellpadding: 'cellPadding',
13045 cellspacing: 'cellSpacing',
13046 challenge: 'challenge',
13047 charset: 'charSet',
13048 checked: 'checked',
13049 children: 'children',
13050 cite: 'cite',
13051 'class': 'className',
13052 classid: 'classID',
13053 classname: 'className',
13054 cols: 'cols',
13055 colspan: 'colSpan',
13056 content: 'content',
13057 contenteditable: 'contentEditable',
13058 contextmenu: 'contextMenu',
13059 controls: 'controls',
13060 controlslist: 'controlsList',
13061 coords: 'coords',
13062 crossorigin: 'crossOrigin',
13063 dangerouslysetinnerhtml: 'dangerouslySetInnerHTML',
13064 data: 'data',
13065 datetime: 'dateTime',
13066 'default': 'default',
13067 defaultchecked: 'defaultChecked',
13068 defaultvalue: 'defaultValue',
13069 defer: 'defer',
13070 dir: 'dir',
13071 disabled: 'disabled',
13072 download: 'download',
13073 draggable: 'draggable',
13074 enctype: 'encType',
13075 'for': 'htmlFor',
13076 form: 'form',
13077 formmethod: 'formMethod',
13078 formaction: 'formAction',
13079 formenctype: 'formEncType',
13080 formnovalidate: 'formNoValidate',
13081 formtarget: 'formTarget',
13082 frameborder: 'frameBorder',
13083 headers: 'headers',
13084 height: 'height',
13085 hidden: 'hidden',
13086 high: 'high',
13087 href: 'href',
13088 hreflang: 'hrefLang',
13089 htmlfor: 'htmlFor',
13090 httpequiv: 'httpEquiv',
13091 'http-equiv': 'httpEquiv',
13092 icon: 'icon',
13093 id: 'id',
13094 innerhtml: 'innerHTML',
13095 inputmode: 'inputMode',
13096 integrity: 'integrity',
13097 is: 'is',
13098 itemid: 'itemID',
13099 itemprop: 'itemProp',
13100 itemref: 'itemRef',
13101 itemscope: 'itemScope',
13102 itemtype: 'itemType',
13103 keyparams: 'keyParams',
13104 keytype: 'keyType',
13105 kind: 'kind',
13106 label: 'label',
13107 lang: 'lang',
13108 list: 'list',
13109 loop: 'loop',
13110 low: 'low',
13111 manifest: 'manifest',
13112 marginwidth: 'marginWidth',
13113 marginheight: 'marginHeight',
13114 max: 'max',
13115 maxlength: 'maxLength',
13116 media: 'media',
13117 mediagroup: 'mediaGroup',
13118 method: 'method',
13119 min: 'min',
13120 minlength: 'minLength',
13121 multiple: 'multiple',
13122 muted: 'muted',
13123 name: 'name',
13124 nomodule: 'noModule',
13125 nonce: 'nonce',
13126 novalidate: 'noValidate',
13127 open: 'open',
13128 optimum: 'optimum',
13129 pattern: 'pattern',
13130 placeholder: 'placeholder',
13131 playsinline: 'playsInline',
13132 poster: 'poster',
13133 preload: 'preload',
13134 profile: 'profile',
13135 radiogroup: 'radioGroup',
13136 readonly: 'readOnly',
13137 referrerpolicy: 'referrerPolicy',
13138 rel: 'rel',
13139 required: 'required',
13140 reversed: 'reversed',
13141 role: 'role',
13142 rows: 'rows',
13143 rowspan: 'rowSpan',
13144 sandbox: 'sandbox',
13145 scope: 'scope',
13146 scoped: 'scoped',
13147 scrolling: 'scrolling',
13148 seamless: 'seamless',
13149 selected: 'selected',
13150 shape: 'shape',
13151 size: 'size',
13152 sizes: 'sizes',
13153 span: 'span',
13154 spellcheck: 'spellCheck',
13155 src: 'src',
13156 srcdoc: 'srcDoc',
13157 srclang: 'srcLang',
13158 srcset: 'srcSet',
13159 start: 'start',
13160 step: 'step',
13161 style: 'style',
13162 summary: 'summary',
13163 tabindex: 'tabIndex',
13164 target: 'target',
13165 title: 'title',
13166 type: 'type',
13167 usemap: 'useMap',
13168 value: 'value',
13169 width: 'width',
13170 wmode: 'wmode',
13171 wrap: 'wrap',
13172
13173 // SVG
13174 about: 'about',
13175 accentheight: 'accentHeight',
13176 'accent-height': 'accentHeight',
13177 accumulate: 'accumulate',
13178 additive: 'additive',
13179 alignmentbaseline: 'alignmentBaseline',
13180 'alignment-baseline': 'alignmentBaseline',
13181 allowreorder: 'allowReorder',
13182 alphabetic: 'alphabetic',
13183 amplitude: 'amplitude',
13184 arabicform: 'arabicForm',
13185 'arabic-form': 'arabicForm',
13186 ascent: 'ascent',
13187 attributename: 'attributeName',
13188 attributetype: 'attributeType',
13189 autoreverse: 'autoReverse',
13190 azimuth: 'azimuth',
13191 basefrequency: 'baseFrequency',
13192 baselineshift: 'baselineShift',
13193 'baseline-shift': 'baselineShift',
13194 baseprofile: 'baseProfile',
13195 bbox: 'bbox',
13196 begin: 'begin',
13197 bias: 'bias',
13198 by: 'by',
13199 calcmode: 'calcMode',
13200 capheight: 'capHeight',
13201 'cap-height': 'capHeight',
13202 clip: 'clip',
13203 clippath: 'clipPath',
13204 'clip-path': 'clipPath',
13205 clippathunits: 'clipPathUnits',
13206 cliprule: 'clipRule',
13207 'clip-rule': 'clipRule',
13208 color: 'color',
13209 colorinterpolation: 'colorInterpolation',
13210 'color-interpolation': 'colorInterpolation',
13211 colorinterpolationfilters: 'colorInterpolationFilters',
13212 'color-interpolation-filters': 'colorInterpolationFilters',
13213 colorprofile: 'colorProfile',
13214 'color-profile': 'colorProfile',
13215 colorrendering: 'colorRendering',
13216 'color-rendering': 'colorRendering',
13217 contentscripttype: 'contentScriptType',
13218 contentstyletype: 'contentStyleType',
13219 cursor: 'cursor',
13220 cx: 'cx',
13221 cy: 'cy',
13222 d: 'd',
13223 datatype: 'datatype',
13224 decelerate: 'decelerate',
13225 descent: 'descent',
13226 diffuseconstant: 'diffuseConstant',
13227 direction: 'direction',
13228 display: 'display',
13229 divisor: 'divisor',
13230 dominantbaseline: 'dominantBaseline',
13231 'dominant-baseline': 'dominantBaseline',
13232 dur: 'dur',
13233 dx: 'dx',
13234 dy: 'dy',
13235 edgemode: 'edgeMode',
13236 elevation: 'elevation',
13237 enablebackground: 'enableBackground',
13238 'enable-background': 'enableBackground',
13239 end: 'end',
13240 exponent: 'exponent',
13241 externalresourcesrequired: 'externalResourcesRequired',
13242 fill: 'fill',
13243 fillopacity: 'fillOpacity',
13244 'fill-opacity': 'fillOpacity',
13245 fillrule: 'fillRule',
13246 'fill-rule': 'fillRule',
13247 filter: 'filter',
13248 filterres: 'filterRes',
13249 filterunits: 'filterUnits',
13250 floodopacity: 'floodOpacity',
13251 'flood-opacity': 'floodOpacity',
13252 floodcolor: 'floodColor',
13253 'flood-color': 'floodColor',
13254 focusable: 'focusable',
13255 fontfamily: 'fontFamily',
13256 'font-family': 'fontFamily',
13257 fontsize: 'fontSize',
13258 'font-size': 'fontSize',
13259 fontsizeadjust: 'fontSizeAdjust',
13260 'font-size-adjust': 'fontSizeAdjust',
13261 fontstretch: 'fontStretch',
13262 'font-stretch': 'fontStretch',
13263 fontstyle: 'fontStyle',
13264 'font-style': 'fontStyle',
13265 fontvariant: 'fontVariant',
13266 'font-variant': 'fontVariant',
13267 fontweight: 'fontWeight',
13268 'font-weight': 'fontWeight',
13269 format: 'format',
13270 from: 'from',
13271 fx: 'fx',
13272 fy: 'fy',
13273 g1: 'g1',
13274 g2: 'g2',
13275 glyphname: 'glyphName',
13276 'glyph-name': 'glyphName',
13277 glyphorientationhorizontal: 'glyphOrientationHorizontal',
13278 'glyph-orientation-horizontal': 'glyphOrientationHorizontal',
13279 glyphorientationvertical: 'glyphOrientationVertical',
13280 'glyph-orientation-vertical': 'glyphOrientationVertical',
13281 glyphref: 'glyphRef',
13282 gradienttransform: 'gradientTransform',
13283 gradientunits: 'gradientUnits',
13284 hanging: 'hanging',
13285 horizadvx: 'horizAdvX',
13286 'horiz-adv-x': 'horizAdvX',
13287 horizoriginx: 'horizOriginX',
13288 'horiz-origin-x': 'horizOriginX',
13289 ideographic: 'ideographic',
13290 imagerendering: 'imageRendering',
13291 'image-rendering': 'imageRendering',
13292 in2: 'in2',
13293 'in': 'in',
13294 inlist: 'inlist',
13295 intercept: 'intercept',
13296 k1: 'k1',
13297 k2: 'k2',
13298 k3: 'k3',
13299 k4: 'k4',
13300 k: 'k',
13301 kernelmatrix: 'kernelMatrix',
13302 kernelunitlength: 'kernelUnitLength',
13303 kerning: 'kerning',
13304 keypoints: 'keyPoints',
13305 keysplines: 'keySplines',
13306 keytimes: 'keyTimes',
13307 lengthadjust: 'lengthAdjust',
13308 letterspacing: 'letterSpacing',
13309 'letter-spacing': 'letterSpacing',
13310 lightingcolor: 'lightingColor',
13311 'lighting-color': 'lightingColor',
13312 limitingconeangle: 'limitingConeAngle',
13313 local: 'local',
13314 markerend: 'markerEnd',
13315 'marker-end': 'markerEnd',
13316 markerheight: 'markerHeight',
13317 markermid: 'markerMid',
13318 'marker-mid': 'markerMid',
13319 markerstart: 'markerStart',
13320 'marker-start': 'markerStart',
13321 markerunits: 'markerUnits',
13322 markerwidth: 'markerWidth',
13323 mask: 'mask',
13324 maskcontentunits: 'maskContentUnits',
13325 maskunits: 'maskUnits',
13326 mathematical: 'mathematical',
13327 mode: 'mode',
13328 numoctaves: 'numOctaves',
13329 offset: 'offset',
13330 opacity: 'opacity',
13331 operator: 'operator',
13332 order: 'order',
13333 orient: 'orient',
13334 orientation: 'orientation',
13335 origin: 'origin',
13336 overflow: 'overflow',
13337 overlineposition: 'overlinePosition',
13338 'overline-position': 'overlinePosition',
13339 overlinethickness: 'overlineThickness',
13340 'overline-thickness': 'overlineThickness',
13341 paintorder: 'paintOrder',
13342 'paint-order': 'paintOrder',
13343 panose1: 'panose1',
13344 'panose-1': 'panose1',
13345 pathlength: 'pathLength',
13346 patterncontentunits: 'patternContentUnits',
13347 patterntransform: 'patternTransform',
13348 patternunits: 'patternUnits',
13349 pointerevents: 'pointerEvents',
13350 'pointer-events': 'pointerEvents',
13351 points: 'points',
13352 pointsatx: 'pointsAtX',
13353 pointsaty: 'pointsAtY',
13354 pointsatz: 'pointsAtZ',
13355 prefix: 'prefix',
13356 preservealpha: 'preserveAlpha',
13357 preserveaspectratio: 'preserveAspectRatio',
13358 primitiveunits: 'primitiveUnits',
13359 property: 'property',
13360 r: 'r',
13361 radius: 'radius',
13362 refx: 'refX',
13363 refy: 'refY',
13364 renderingintent: 'renderingIntent',
13365 'rendering-intent': 'renderingIntent',
13366 repeatcount: 'repeatCount',
13367 repeatdur: 'repeatDur',
13368 requiredextensions: 'requiredExtensions',
13369 requiredfeatures: 'requiredFeatures',
13370 resource: 'resource',
13371 restart: 'restart',
13372 result: 'result',
13373 results: 'results',
13374 rotate: 'rotate',
13375 rx: 'rx',
13376 ry: 'ry',
13377 scale: 'scale',
13378 security: 'security',
13379 seed: 'seed',
13380 shaperendering: 'shapeRendering',
13381 'shape-rendering': 'shapeRendering',
13382 slope: 'slope',
13383 spacing: 'spacing',
13384 specularconstant: 'specularConstant',
13385 specularexponent: 'specularExponent',
13386 speed: 'speed',
13387 spreadmethod: 'spreadMethod',
13388 startoffset: 'startOffset',
13389 stddeviation: 'stdDeviation',
13390 stemh: 'stemh',
13391 stemv: 'stemv',
13392 stitchtiles: 'stitchTiles',
13393 stopcolor: 'stopColor',
13394 'stop-color': 'stopColor',
13395 stopopacity: 'stopOpacity',
13396 'stop-opacity': 'stopOpacity',
13397 strikethroughposition: 'strikethroughPosition',
13398 'strikethrough-position': 'strikethroughPosition',
13399 strikethroughthickness: 'strikethroughThickness',
13400 'strikethrough-thickness': 'strikethroughThickness',
13401 string: 'string',
13402 stroke: 'stroke',
13403 strokedasharray: 'strokeDasharray',
13404 'stroke-dasharray': 'strokeDasharray',
13405 strokedashoffset: 'strokeDashoffset',
13406 'stroke-dashoffset': 'strokeDashoffset',
13407 strokelinecap: 'strokeLinecap',
13408 'stroke-linecap': 'strokeLinecap',
13409 strokelinejoin: 'strokeLinejoin',
13410 'stroke-linejoin': 'strokeLinejoin',
13411 strokemiterlimit: 'strokeMiterlimit',
13412 'stroke-miterlimit': 'strokeMiterlimit',
13413 strokewidth: 'strokeWidth',
13414 'stroke-width': 'strokeWidth',
13415 strokeopacity: 'strokeOpacity',
13416 'stroke-opacity': 'strokeOpacity',
13417 suppresscontenteditablewarning: 'suppressContentEditableWarning',
13418 suppresshydrationwarning: 'suppressHydrationWarning',
13419 surfacescale: 'surfaceScale',
13420 systemlanguage: 'systemLanguage',
13421 tablevalues: 'tableValues',
13422 targetx: 'targetX',
13423 targety: 'targetY',
13424 textanchor: 'textAnchor',
13425 'text-anchor': 'textAnchor',
13426 textdecoration: 'textDecoration',
13427 'text-decoration': 'textDecoration',
13428 textlength: 'textLength',
13429 textrendering: 'textRendering',
13430 'text-rendering': 'textRendering',
13431 to: 'to',
13432 transform: 'transform',
13433 'typeof': 'typeof',
13434 u1: 'u1',
13435 u2: 'u2',
13436 underlineposition: 'underlinePosition',
13437 'underline-position': 'underlinePosition',
13438 underlinethickness: 'underlineThickness',
13439 'underline-thickness': 'underlineThickness',
13440 unicode: 'unicode',
13441 unicodebidi: 'unicodeBidi',
13442 'unicode-bidi': 'unicodeBidi',
13443 unicoderange: 'unicodeRange',
13444 'unicode-range': 'unicodeRange',
13445 unitsperem: 'unitsPerEm',
13446 'units-per-em': 'unitsPerEm',
13447 unselectable: 'unselectable',
13448 valphabetic: 'vAlphabetic',
13449 'v-alphabetic': 'vAlphabetic',
13450 values: 'values',
13451 vectoreffect: 'vectorEffect',
13452 'vector-effect': 'vectorEffect',
13453 version: 'version',
13454 vertadvy: 'vertAdvY',
13455 'vert-adv-y': 'vertAdvY',
13456 vertoriginx: 'vertOriginX',
13457 'vert-origin-x': 'vertOriginX',
13458 vertoriginy: 'vertOriginY',
13459 'vert-origin-y': 'vertOriginY',
13460 vhanging: 'vHanging',
13461 'v-hanging': 'vHanging',
13462 videographic: 'vIdeographic',
13463 'v-ideographic': 'vIdeographic',
13464 viewbox: 'viewBox',
13465 viewtarget: 'viewTarget',
13466 visibility: 'visibility',
13467 vmathematical: 'vMathematical',
13468 'v-mathematical': 'vMathematical',
13469 vocab: 'vocab',
13470 widths: 'widths',
13471 wordspacing: 'wordSpacing',
13472 'word-spacing': 'wordSpacing',
13473 writingmode: 'writingMode',
13474 'writing-mode': 'writingMode',
13475 x1: 'x1',
13476 x2: 'x2',
13477 x: 'x',
13478 xchannelselector: 'xChannelSelector',
13479 xheight: 'xHeight',
13480 'x-height': 'xHeight',
13481 xlinkactuate: 'xlinkActuate',
13482 'xlink:actuate': 'xlinkActuate',
13483 xlinkarcrole: 'xlinkArcrole',
13484 'xlink:arcrole': 'xlinkArcrole',
13485 xlinkhref: 'xlinkHref',
13486 'xlink:href': 'xlinkHref',
13487 xlinkrole: 'xlinkRole',
13488 'xlink:role': 'xlinkRole',
13489 xlinkshow: 'xlinkShow',
13490 'xlink:show': 'xlinkShow',
13491 xlinktitle: 'xlinkTitle',
13492 'xlink:title': 'xlinkTitle',
13493 xlinktype: 'xlinkType',
13494 'xlink:type': 'xlinkType',
13495 xmlbase: 'xmlBase',
13496 'xml:base': 'xmlBase',
13497 xmllang: 'xmlLang',
13498 'xml:lang': 'xmlLang',
13499 xmlns: 'xmlns',
13500 'xml:space': 'xmlSpace',
13501 xmlnsxlink: 'xmlnsXlink',
13502 'xmlns:xlink': 'xmlnsXlink',
13503 xmlspace: 'xmlSpace',
13504 y1: 'y1',
13505 y2: 'y2',
13506 y: 'y',
13507 ychannelselector: 'yChannelSelector',
13508 z: 'z',
13509 zoomandpan: 'zoomAndPan'
13510};
13511
13512var ariaProperties = {
13513 'aria-current': 0, // state
13514 'aria-details': 0,
13515 'aria-disabled': 0, // state
13516 'aria-hidden': 0, // state
13517 'aria-invalid': 0, // state
13518 'aria-keyshortcuts': 0,
13519 'aria-label': 0,
13520 'aria-roledescription': 0,
13521 // Widget Attributes
13522 'aria-autocomplete': 0,
13523 'aria-checked': 0,
13524 'aria-expanded': 0,
13525 'aria-haspopup': 0,
13526 'aria-level': 0,
13527 'aria-modal': 0,
13528 'aria-multiline': 0,
13529 'aria-multiselectable': 0,
13530 'aria-orientation': 0,
13531 'aria-placeholder': 0,
13532 'aria-pressed': 0,
13533 'aria-readonly': 0,
13534 'aria-required': 0,
13535 'aria-selected': 0,
13536 'aria-sort': 0,
13537 'aria-valuemax': 0,
13538 'aria-valuemin': 0,
13539 'aria-valuenow': 0,
13540 'aria-valuetext': 0,
13541 // Live Region Attributes
13542 'aria-atomic': 0,
13543 'aria-busy': 0,
13544 'aria-live': 0,
13545 'aria-relevant': 0,
13546 // Drag-and-Drop Attributes
13547 'aria-dropeffect': 0,
13548 'aria-grabbed': 0,
13549 // Relationship Attributes
13550 'aria-activedescendant': 0,
13551 'aria-colcount': 0,
13552 'aria-colindex': 0,
13553 'aria-colspan': 0,
13554 'aria-controls': 0,
13555 'aria-describedby': 0,
13556 'aria-errormessage': 0,
13557 'aria-flowto': 0,
13558 'aria-labelledby': 0,
13559 'aria-owns': 0,
13560 'aria-posinset': 0,
13561 'aria-rowcount': 0,
13562 'aria-rowindex': 0,
13563 'aria-rowspan': 0,
13564 'aria-setsize': 0
13565};
13566
13567var warnedProperties = {};
13568var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
13569var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
13570
13571var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
13572
13573function getStackAddendum() {
13574 var stack = ReactDebugCurrentFrame.getStackAddendum();
13575 return stack != null ? stack : '';
13576}
13577
13578function validateProperty(tagName, name) {
13579 if (hasOwnProperty$1.call(warnedProperties, name) && warnedProperties[name]) {
13580 return true;
13581 }
13582
13583 if (rARIACamel.test(name)) {
13584 var ariaName = 'aria-' + name.slice(4).toLowerCase();
13585 var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null;
13586
13587 // If this is an aria-* attribute, but is not listed in the known DOM
13588 // DOM properties, then it is an invalid aria-* attribute.
13589 if (correctName == null) {
13590 warning_1(false, 'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.%s', name, getStackAddendum());
13591 warnedProperties[name] = true;
13592 return true;
13593 }
13594 // aria-* attributes should be lowercase; suggest the lowercase version.
13595 if (name !== correctName) {
13596 warning_1(false, 'Invalid ARIA attribute `%s`. Did you mean `%s`?%s', name, correctName, getStackAddendum());
13597 warnedProperties[name] = true;
13598 return true;
13599 }
13600 }
13601
13602 if (rARIA.test(name)) {
13603 var lowerCasedName = name.toLowerCase();
13604 var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null;
13605
13606 // If this is an aria-* attribute, but is not listed in the known DOM
13607 // DOM properties, then it is an invalid aria-* attribute.
13608 if (standardName == null) {
13609 warnedProperties[name] = true;
13610 return false;
13611 }
13612 // aria-* attributes should be lowercase; suggest the lowercase version.
13613 if (name !== standardName) {
13614 warning_1(false, 'Unknown ARIA attribute `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum());
13615 warnedProperties[name] = true;
13616 return true;
13617 }
13618 }
13619
13620 return true;
13621}
13622
13623function warnInvalidARIAProps(type, props) {
13624 var invalidProps = [];
13625
13626 for (var key in props) {
13627 var isValid = validateProperty(type, key);
13628 if (!isValid) {
13629 invalidProps.push(key);
13630 }
13631 }
13632
13633 var unknownPropString = invalidProps.map(function (prop) {
13634 return '`' + prop + '`';
13635 }).join(', ');
13636
13637 if (invalidProps.length === 1) {
13638 warning_1(false, 'Invalid aria prop %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum());
13639 } else if (invalidProps.length > 1) {
13640 warning_1(false, 'Invalid aria props %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum());
13641 }
13642}
13643
13644function validateProperties(type, props) {
13645 if (isCustomComponent(type, props)) {
13646 return;
13647 }
13648 warnInvalidARIAProps(type, props);
13649}
13650
13651var didWarnValueNull = false;
13652
13653function getStackAddendum$1() {
13654 var stack = ReactDebugCurrentFrame.getStackAddendum();
13655 return stack != null ? stack : '';
13656}
13657
13658function validateProperties$1(type, props) {
13659 if (type !== 'input' && type !== 'textarea' && type !== 'select') {
13660 return;
13661 }
13662
13663 if (props != null && props.value === null && !didWarnValueNull) {
13664 didWarnValueNull = true;
13665 if (type === 'select' && props.multiple) {
13666 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());
13667 } else {
13668 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());
13669 }
13670 }
13671}
13672
13673function getStackAddendum$2() {
13674 var stack = ReactDebugCurrentFrame.getStackAddendum();
13675 return stack != null ? stack : '';
13676}
13677
13678var validateProperty$1 = function () {};
13679
13680{
13681 var warnedProperties$1 = {};
13682 var _hasOwnProperty = Object.prototype.hasOwnProperty;
13683 var EVENT_NAME_REGEX = /^on./;
13684 var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;
13685 var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
13686 var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
13687
13688 validateProperty$1 = function (tagName, name, value, canUseEventSystem) {
13689 if (_hasOwnProperty.call(warnedProperties$1, name) && warnedProperties$1[name]) {
13690 return true;
13691 }
13692
13693 var lowerCasedName = name.toLowerCase();
13694 if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') {
13695 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.');
13696 warnedProperties$1[name] = true;
13697 return true;
13698 }
13699
13700 // We can't rely on the event system being injected on the server.
13701 if (canUseEventSystem) {
13702 if (registrationNameModules.hasOwnProperty(name)) {
13703 return true;
13704 }
13705 var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null;
13706 if (registrationName != null) {
13707 warning_1(false, 'Invalid event handler property `%s`. Did you mean `%s`?%s', name, registrationName, getStackAddendum$2());
13708 warnedProperties$1[name] = true;
13709 return true;
13710 }
13711 if (EVENT_NAME_REGEX.test(name)) {
13712 warning_1(false, 'Unknown event handler property `%s`. It will be ignored.%s', name, getStackAddendum$2());
13713 warnedProperties$1[name] = true;
13714 return true;
13715 }
13716 } else if (EVENT_NAME_REGEX.test(name)) {
13717 // If no event plugins have been injected, we are in a server environment.
13718 // So we can't tell if the event name is correct for sure, but we can filter
13719 // out known bad ones like `onclick`. We can't suggest a specific replacement though.
13720 if (INVALID_EVENT_NAME_REGEX.test(name)) {
13721 warning_1(false, 'Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.%s', name, getStackAddendum$2());
13722 }
13723 warnedProperties$1[name] = true;
13724 return true;
13725 }
13726
13727 // Let the ARIA attribute hook validate ARIA attributes
13728 if (rARIA$1.test(name) || rARIACamel$1.test(name)) {
13729 return true;
13730 }
13731
13732 if (lowerCasedName === 'innerhtml') {
13733 warning_1(false, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.');
13734 warnedProperties$1[name] = true;
13735 return true;
13736 }
13737
13738 if (lowerCasedName === 'aria') {
13739 warning_1(false, 'The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.');
13740 warnedProperties$1[name] = true;
13741 return true;
13742 }
13743
13744 if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') {
13745 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());
13746 warnedProperties$1[name] = true;
13747 return true;
13748 }
13749
13750 if (typeof value === 'number' && isNaN(value)) {
13751 warning_1(false, 'Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.%s', name, getStackAddendum$2());
13752 warnedProperties$1[name] = true;
13753 return true;
13754 }
13755
13756 var propertyInfo = getPropertyInfo(name);
13757 var isReserved = propertyInfo !== null && propertyInfo.type === RESERVED;
13758
13759 // Known attributes should match the casing specified in the property config.
13760 if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
13761 var standardName = possibleStandardNames[lowerCasedName];
13762 if (standardName !== name) {
13763 warning_1(false, 'Invalid DOM property `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum$2());
13764 warnedProperties$1[name] = true;
13765 return true;
13766 }
13767 } else if (!isReserved && name !== lowerCasedName) {
13768 // Unknown attributes should have lowercase casing since that's how they
13769 // will be cased anyway with server rendering.
13770 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());
13771 warnedProperties$1[name] = true;
13772 return true;
13773 }
13774
13775 if (typeof value === 'boolean' && shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) {
13776 if (value) {
13777 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());
13778 } else {
13779 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());
13780 }
13781 warnedProperties$1[name] = true;
13782 return true;
13783 }
13784
13785 // Now that we've validated casing, do not validate
13786 // data types for reserved props
13787 if (isReserved) {
13788 return true;
13789 }
13790
13791 // Warn when a known attribute is a bad type
13792 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) {
13793 warnedProperties$1[name] = true;
13794 return false;
13795 }
13796
13797 return true;
13798 };
13799}
13800
13801var warnUnknownProperties = function (type, props, canUseEventSystem) {
13802 var unknownProps = [];
13803 for (var key in props) {
13804 var isValid = validateProperty$1(type, key, props[key], canUseEventSystem);
13805 if (!isValid) {
13806 unknownProps.push(key);
13807 }
13808 }
13809
13810 var unknownPropString = unknownProps.map(function (prop) {
13811 return '`' + prop + '`';
13812 }).join(', ');
13813 if (unknownProps.length === 1) {
13814 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());
13815 } else if (unknownProps.length > 1) {
13816 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());
13817 }
13818};
13819
13820function validateProperties$2(type, props, canUseEventSystem) {
13821 if (isCustomComponent(type, props)) {
13822 return;
13823 }
13824 warnUnknownProperties(type, props, canUseEventSystem);
13825}
13826
13827// TODO: direct imports like some-package/src/* are bad. Fix me.
13828var getCurrentFiberOwnerName$2 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
13829var getCurrentFiberStackAddendum$3 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
13830
13831var didWarnInvalidHydration = false;
13832var didWarnShadyDOM = false;
13833
13834var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
13835var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
13836var SUPPRESS_HYDRATION_WARNING$1 = 'suppressHydrationWarning';
13837var AUTOFOCUS = 'autoFocus';
13838var CHILDREN = 'children';
13839var STYLE = 'style';
13840var HTML = '__html';
13841
13842var HTML_NAMESPACE = Namespaces.html;
13843
13844
13845var getStack = emptyFunction_1.thatReturns('');
13846
13847var warnedUnknownTags = void 0;
13848var suppressHydrationWarning = void 0;
13849
13850var validatePropertiesInDevelopment = void 0;
13851var warnForTextDifference = void 0;
13852var warnForPropDifference = void 0;
13853var warnForExtraAttributes = void 0;
13854var warnForInvalidEventListener = void 0;
13855
13856var normalizeMarkupForTextOrAttribute = void 0;
13857var normalizeHTML = void 0;
13858
13859{
13860 getStack = getCurrentFiberStackAddendum$3;
13861
13862 warnedUnknownTags = {
13863 // Chrome is the only major browser not shipping <time>. But as of July
13864 // 2017 it intends to ship it due to widespread usage. We intentionally
13865 // *don't* warn for <time> even if it's unrecognized by Chrome because
13866 // it soon will be, and many apps have been using it anyway.
13867 time: true,
13868 // There are working polyfills for <dialog>. Let people use it.
13869 dialog: true
13870 };
13871
13872 validatePropertiesInDevelopment = function (type, props) {
13873 validateProperties(type, props);
13874 validateProperties$1(type, props);
13875 validateProperties$2(type, props, /* canUseEventSystem */true);
13876 };
13877
13878 // HTML parsing normalizes CR and CRLF to LF.
13879 // It also can turn \u0000 into \uFFFD inside attributes.
13880 // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream
13881 // If we have a mismatch, it might be caused by that.
13882 // We will still patch up in this case but not fire the warning.
13883 var NORMALIZE_NEWLINES_REGEX = /\r\n?/g;
13884 var NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g;
13885
13886 normalizeMarkupForTextOrAttribute = function (markup) {
13887 var markupString = typeof markup === 'string' ? markup : '' + markup;
13888 return markupString.replace(NORMALIZE_NEWLINES_REGEX, '\n').replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, '');
13889 };
13890
13891 warnForTextDifference = function (serverText, clientText) {
13892 if (didWarnInvalidHydration) {
13893 return;
13894 }
13895 var normalizedClientText = normalizeMarkupForTextOrAttribute(clientText);
13896 var normalizedServerText = normalizeMarkupForTextOrAttribute(serverText);
13897 if (normalizedServerText === normalizedClientText) {
13898 return;
13899 }
13900 didWarnInvalidHydration = true;
13901 warning_1(false, 'Text content did not match. Server: "%s" Client: "%s"', normalizedServerText, normalizedClientText);
13902 };
13903
13904 warnForPropDifference = function (propName, serverValue, clientValue) {
13905 if (didWarnInvalidHydration) {
13906 return;
13907 }
13908 var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue);
13909 var normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);
13910 if (normalizedServerValue === normalizedClientValue) {
13911 return;
13912 }
13913 didWarnInvalidHydration = true;
13914 warning_1(false, 'Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue));
13915 };
13916
13917 warnForExtraAttributes = function (attributeNames) {
13918 if (didWarnInvalidHydration) {
13919 return;
13920 }
13921 didWarnInvalidHydration = true;
13922 var names = [];
13923 attributeNames.forEach(function (name) {
13924 names.push(name);
13925 });
13926 warning_1(false, 'Extra attributes from the server: %s', names);
13927 };
13928
13929 warnForInvalidEventListener = function (registrationName, listener) {
13930 if (listener === false) {
13931 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$3());
13932 } else {
13933 warning_1(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.%s', registrationName, typeof listener, getCurrentFiberStackAddendum$3());
13934 }
13935 };
13936
13937 // Parse the HTML and read it back to normalize the HTML string so that it
13938 // can be used for comparison.
13939 normalizeHTML = function (parent, html) {
13940 // We could have created a separate document here to avoid
13941 // re-initializing custom elements if they exist. But this breaks
13942 // how <noscript> is being handled. So we use the same document.
13943 // See the discussion in https://github.com/facebook/react/pull/11157.
13944 var testElement = parent.namespaceURI === HTML_NAMESPACE ? parent.ownerDocument.createElement(parent.tagName) : parent.ownerDocument.createElementNS(parent.namespaceURI, parent.tagName);
13945 testElement.innerHTML = html;
13946 return testElement.innerHTML;
13947 };
13948}
13949
13950function ensureListeningTo(rootContainerElement, registrationName) {
13951 var isDocumentOrFragment = rootContainerElement.nodeType === DOCUMENT_NODE || rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE;
13952 var doc = isDocumentOrFragment ? rootContainerElement : rootContainerElement.ownerDocument;
13953 listenTo(registrationName, doc);
13954}
13955
13956function getOwnerDocumentFromRootContainer(rootContainerElement) {
13957 return rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument;
13958}
13959
13960// There are so many media events, it makes sense to just
13961// maintain a list rather than create a `trapBubbledEvent` for each
13962var mediaEvents = {
13963 topAbort: 'abort',
13964 topCanPlay: 'canplay',
13965 topCanPlayThrough: 'canplaythrough',
13966 topDurationChange: 'durationchange',
13967 topEmptied: 'emptied',
13968 topEncrypted: 'encrypted',
13969 topEnded: 'ended',
13970 topError: 'error',
13971 topLoadedData: 'loadeddata',
13972 topLoadedMetadata: 'loadedmetadata',
13973 topLoadStart: 'loadstart',
13974 topPause: 'pause',
13975 topPlay: 'play',
13976 topPlaying: 'playing',
13977 topProgress: 'progress',
13978 topRateChange: 'ratechange',
13979 topSeeked: 'seeked',
13980 topSeeking: 'seeking',
13981 topStalled: 'stalled',
13982 topSuspend: 'suspend',
13983 topTimeUpdate: 'timeupdate',
13984 topVolumeChange: 'volumechange',
13985 topWaiting: 'waiting'
13986};
13987
13988function trapClickOnNonInteractiveElement(node) {
13989 // Mobile Safari does not fire properly bubble click events on
13990 // non-interactive elements, which means delegated click listeners do not
13991 // fire. The workaround for this bug involves attaching an empty click
13992 // listener on the target node.
13993 // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
13994 // Just set it using the onclick property so that we don't have to manage any
13995 // bookkeeping for it. Not sure if we need to clear it when the listener is
13996 // removed.
13997 // TODO: Only do this for the relevant Safaris maybe?
13998 node.onclick = emptyFunction_1;
13999}
14000
14001function setInitialDOMProperties(tag, domElement, rootContainerElement, nextProps, isCustomComponentTag) {
14002 for (var propKey in nextProps) {
14003 if (!nextProps.hasOwnProperty(propKey)) {
14004 continue;
14005 }
14006 var nextProp = nextProps[propKey];
14007 if (propKey === STYLE) {
14008 {
14009 if (nextProp) {
14010 // Freeze the next style object so that we can assume it won't be
14011 // mutated. We have already warned for this in the past.
14012 Object.freeze(nextProp);
14013 }
14014 }
14015 // Relies on `updateStylesByID` not mutating `styleUpdates`.
14016 setValueForStyles(domElement, nextProp, getStack);
14017 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14018 var nextHtml = nextProp ? nextProp[HTML] : undefined;
14019 if (nextHtml != null) {
14020 setInnerHTML(domElement, nextHtml);
14021 }
14022 } else if (propKey === CHILDREN) {
14023 if (typeof nextProp === 'string') {
14024 // Avoid setting initial textContent when the text is empty. In IE11 setting
14025 // textContent on a <textarea> will cause the placeholder to not
14026 // show within the <textarea> until it has been focused and blurred again.
14027 // https://github.com/facebook/react/issues/6731#issuecomment-254874553
14028 var canSetTextContent = tag !== 'textarea' || nextProp !== '';
14029 if (canSetTextContent) {
14030 setTextContent(domElement, nextProp);
14031 }
14032 } else if (typeof nextProp === 'number') {
14033 setTextContent(domElement, '' + nextProp);
14034 }
14035 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
14036 // Noop
14037 } else if (propKey === AUTOFOCUS) {
14038 // We polyfill it separately on the client during commit.
14039 // We blacklist it here rather than in the property list because we emit it in SSR.
14040 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14041 if (nextProp != null) {
14042 if (true && typeof nextProp !== 'function') {
14043 warnForInvalidEventListener(propKey, nextProp);
14044 }
14045 ensureListeningTo(rootContainerElement, propKey);
14046 }
14047 } else if (nextProp != null) {
14048 setValueForProperty(domElement, propKey, nextProp, isCustomComponentTag);
14049 }
14050 }
14051}
14052
14053function updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag) {
14054 // TODO: Handle wasCustomComponentTag
14055 for (var i = 0; i < updatePayload.length; i += 2) {
14056 var propKey = updatePayload[i];
14057 var propValue = updatePayload[i + 1];
14058 if (propKey === STYLE) {
14059 setValueForStyles(domElement, propValue, getStack);
14060 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14061 setInnerHTML(domElement, propValue);
14062 } else if (propKey === CHILDREN) {
14063 setTextContent(domElement, propValue);
14064 } else {
14065 setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);
14066 }
14067 }
14068}
14069
14070function createElement$1(type, props, rootContainerElement, parentNamespace) {
14071 var isCustomComponentTag = void 0;
14072
14073 // We create tags in the namespace of their parent container, except HTML
14074 // tags get no namespace.
14075 var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement);
14076 var domElement = void 0;
14077 var namespaceURI = parentNamespace;
14078 if (namespaceURI === HTML_NAMESPACE) {
14079 namespaceURI = getIntrinsicNamespace(type);
14080 }
14081 if (namespaceURI === HTML_NAMESPACE) {
14082 {
14083 isCustomComponentTag = isCustomComponent(type, props);
14084 // Should this check be gated by parent namespace? Not sure we want to
14085 // allow <SVG> or <mATH>.
14086 warning_1(isCustomComponentTag || type === type.toLowerCase(), '<%s /> is using uppercase HTML. Always use lowercase HTML tags ' + 'in React.', type);
14087 }
14088
14089 if (type === 'script') {
14090 // Create the script via .innerHTML so its "parser-inserted" flag is
14091 // set to true and it does not execute
14092 var div = ownerDocument.createElement('div');
14093 div.innerHTML = '<script><' + '/script>'; // eslint-disable-line
14094 // This is guaranteed to yield a script element.
14095 var firstChild = div.firstChild;
14096 domElement = div.removeChild(firstChild);
14097 } else if (typeof props.is === 'string') {
14098 // $FlowIssue `createElement` should be updated for Web Components
14099 domElement = ownerDocument.createElement(type, { is: props.is });
14100 } else {
14101 // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
14102 // See discussion in https://github.com/facebook/react/pull/6896
14103 // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
14104 domElement = ownerDocument.createElement(type);
14105 }
14106 } else {
14107 domElement = ownerDocument.createElementNS(namespaceURI, type);
14108 }
14109
14110 {
14111 if (namespaceURI === HTML_NAMESPACE) {
14112 if (!isCustomComponentTag && Object.prototype.toString.call(domElement) === '[object HTMLUnknownElement]' && !Object.prototype.hasOwnProperty.call(warnedUnknownTags, type)) {
14113 warnedUnknownTags[type] = true;
14114 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);
14115 }
14116 }
14117 }
14118
14119 return domElement;
14120}
14121
14122function createTextNode$1(text, rootContainerElement) {
14123 return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(text);
14124}
14125
14126function setInitialProperties$1(domElement, tag, rawProps, rootContainerElement) {
14127 var isCustomComponentTag = isCustomComponent(tag, rawProps);
14128 {
14129 validatePropertiesInDevelopment(tag, rawProps);
14130 if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
14131 warning_1(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName$2() || 'A component');
14132 didWarnShadyDOM = true;
14133 }
14134 }
14135
14136 // TODO: Make sure that we check isMounted before firing any of these events.
14137 var props = void 0;
14138 switch (tag) {
14139 case 'iframe':
14140 case 'object':
14141 trapBubbledEvent('topLoad', 'load', domElement);
14142 props = rawProps;
14143 break;
14144 case 'video':
14145 case 'audio':
14146 // Create listener for each media event
14147 for (var event in mediaEvents) {
14148 if (mediaEvents.hasOwnProperty(event)) {
14149 trapBubbledEvent(event, mediaEvents[event], domElement);
14150 }
14151 }
14152 props = rawProps;
14153 break;
14154 case 'source':
14155 trapBubbledEvent('topError', 'error', domElement);
14156 props = rawProps;
14157 break;
14158 case 'img':
14159 case 'image':
14160 trapBubbledEvent('topError', 'error', domElement);
14161 trapBubbledEvent('topLoad', 'load', domElement);
14162 props = rawProps;
14163 break;
14164 case 'form':
14165 trapBubbledEvent('topReset', 'reset', domElement);
14166 trapBubbledEvent('topSubmit', 'submit', domElement);
14167 props = rawProps;
14168 break;
14169 case 'details':
14170 trapBubbledEvent('topToggle', 'toggle', domElement);
14171 props = rawProps;
14172 break;
14173 case 'input':
14174 initWrapperState(domElement, rawProps);
14175 props = getHostProps(domElement, rawProps);
14176 trapBubbledEvent('topInvalid', 'invalid', domElement);
14177 // For controlled components we always need to ensure we're listening
14178 // to onChange. Even if there is no listener.
14179 ensureListeningTo(rootContainerElement, 'onChange');
14180 break;
14181 case 'option':
14182 validateProps(domElement, rawProps);
14183 props = getHostProps$1(domElement, rawProps);
14184 break;
14185 case 'select':
14186 initWrapperState$1(domElement, rawProps);
14187 props = getHostProps$2(domElement, rawProps);
14188 trapBubbledEvent('topInvalid', 'invalid', domElement);
14189 // For controlled components we always need to ensure we're listening
14190 // to onChange. Even if there is no listener.
14191 ensureListeningTo(rootContainerElement, 'onChange');
14192 break;
14193 case 'textarea':
14194 initWrapperState$2(domElement, rawProps);
14195 props = getHostProps$3(domElement, rawProps);
14196 trapBubbledEvent('topInvalid', 'invalid', domElement);
14197 // For controlled components we always need to ensure we're listening
14198 // to onChange. Even if there is no listener.
14199 ensureListeningTo(rootContainerElement, 'onChange');
14200 break;
14201 default:
14202 props = rawProps;
14203 }
14204
14205 assertValidProps(tag, props, getStack);
14206
14207 setInitialDOMProperties(tag, domElement, rootContainerElement, props, isCustomComponentTag);
14208
14209 switch (tag) {
14210 case 'input':
14211 // TODO: Make sure we check if this is still unmounted or do any clean
14212 // up necessary since we never stop tracking anymore.
14213 track(domElement);
14214 postMountWrapper(domElement, rawProps);
14215 break;
14216 case 'textarea':
14217 // TODO: Make sure we check if this is still unmounted or do any clean
14218 // up necessary since we never stop tracking anymore.
14219 track(domElement);
14220 postMountWrapper$3(domElement, rawProps);
14221 break;
14222 case 'option':
14223 postMountWrapper$1(domElement, rawProps);
14224 break;
14225 case 'select':
14226 postMountWrapper$2(domElement, rawProps);
14227 break;
14228 default:
14229 if (typeof props.onClick === 'function') {
14230 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14231 trapClickOnNonInteractiveElement(domElement);
14232 }
14233 break;
14234 }
14235}
14236
14237// Calculate the diff between the two objects.
14238function diffProperties$1(domElement, tag, lastRawProps, nextRawProps, rootContainerElement) {
14239 {
14240 validatePropertiesInDevelopment(tag, nextRawProps);
14241 }
14242
14243 var updatePayload = null;
14244
14245 var lastProps = void 0;
14246 var nextProps = void 0;
14247 switch (tag) {
14248 case 'input':
14249 lastProps = getHostProps(domElement, lastRawProps);
14250 nextProps = getHostProps(domElement, nextRawProps);
14251 updatePayload = [];
14252 break;
14253 case 'option':
14254 lastProps = getHostProps$1(domElement, lastRawProps);
14255 nextProps = getHostProps$1(domElement, nextRawProps);
14256 updatePayload = [];
14257 break;
14258 case 'select':
14259 lastProps = getHostProps$2(domElement, lastRawProps);
14260 nextProps = getHostProps$2(domElement, nextRawProps);
14261 updatePayload = [];
14262 break;
14263 case 'textarea':
14264 lastProps = getHostProps$3(domElement, lastRawProps);
14265 nextProps = getHostProps$3(domElement, nextRawProps);
14266 updatePayload = [];
14267 break;
14268 default:
14269 lastProps = lastRawProps;
14270 nextProps = nextRawProps;
14271 if (typeof lastProps.onClick !== 'function' && typeof nextProps.onClick === 'function') {
14272 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14273 trapClickOnNonInteractiveElement(domElement);
14274 }
14275 break;
14276 }
14277
14278 assertValidProps(tag, nextProps, getStack);
14279
14280 var propKey = void 0;
14281 var styleName = void 0;
14282 var styleUpdates = null;
14283 for (propKey in lastProps) {
14284 if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
14285 continue;
14286 }
14287 if (propKey === STYLE) {
14288 var lastStyle = lastProps[propKey];
14289 for (styleName in lastStyle) {
14290 if (lastStyle.hasOwnProperty(styleName)) {
14291 if (!styleUpdates) {
14292 styleUpdates = {};
14293 }
14294 styleUpdates[styleName] = '';
14295 }
14296 }
14297 } else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN) {
14298 // Noop. This is handled by the clear text mechanism.
14299 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
14300 // Noop
14301 } else if (propKey === AUTOFOCUS) {
14302 // Noop. It doesn't work on updates anyway.
14303 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14304 // This is a special case. If any listener updates we need to ensure
14305 // that the "current" fiber pointer gets updated so we need a commit
14306 // to update this element.
14307 if (!updatePayload) {
14308 updatePayload = [];
14309 }
14310 } else {
14311 // For all other deleted properties we add it to the queue. We use
14312 // the whitelist in the commit phase instead.
14313 (updatePayload = updatePayload || []).push(propKey, null);
14314 }
14315 }
14316 for (propKey in nextProps) {
14317 var nextProp = nextProps[propKey];
14318 var lastProp = lastProps != null ? lastProps[propKey] : undefined;
14319 if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
14320 continue;
14321 }
14322 if (propKey === STYLE) {
14323 {
14324 if (nextProp) {
14325 // Freeze the next style object so that we can assume it won't be
14326 // mutated. We have already warned for this in the past.
14327 Object.freeze(nextProp);
14328 }
14329 }
14330 if (lastProp) {
14331 // Unset styles on `lastProp` but not on `nextProp`.
14332 for (styleName in lastProp) {
14333 if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
14334 if (!styleUpdates) {
14335 styleUpdates = {};
14336 }
14337 styleUpdates[styleName] = '';
14338 }
14339 }
14340 // Update styles that changed since `lastProp`.
14341 for (styleName in nextProp) {
14342 if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
14343 if (!styleUpdates) {
14344 styleUpdates = {};
14345 }
14346 styleUpdates[styleName] = nextProp[styleName];
14347 }
14348 }
14349 } else {
14350 // Relies on `updateStylesByID` not mutating `styleUpdates`.
14351 if (!styleUpdates) {
14352 if (!updatePayload) {
14353 updatePayload = [];
14354 }
14355 updatePayload.push(propKey, styleUpdates);
14356 }
14357 styleUpdates = nextProp;
14358 }
14359 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14360 var nextHtml = nextProp ? nextProp[HTML] : undefined;
14361 var lastHtml = lastProp ? lastProp[HTML] : undefined;
14362 if (nextHtml != null) {
14363 if (lastHtml !== nextHtml) {
14364 (updatePayload = updatePayload || []).push(propKey, '' + nextHtml);
14365 }
14366 } else {
14367 // TODO: It might be too late to clear this if we have children
14368 // inserted already.
14369 }
14370 } else if (propKey === CHILDREN) {
14371 if (lastProp !== nextProp && (typeof nextProp === 'string' || typeof nextProp === 'number')) {
14372 (updatePayload = updatePayload || []).push(propKey, '' + nextProp);
14373 }
14374 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
14375 // Noop
14376 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14377 if (nextProp != null) {
14378 // We eagerly listen to this even though we haven't committed yet.
14379 if (true && typeof nextProp !== 'function') {
14380 warnForInvalidEventListener(propKey, nextProp);
14381 }
14382 ensureListeningTo(rootContainerElement, propKey);
14383 }
14384 if (!updatePayload && lastProp !== nextProp) {
14385 // This is a special case. If any listener updates we need to ensure
14386 // that the "current" props pointer gets updated so we need a commit
14387 // to update this element.
14388 updatePayload = [];
14389 }
14390 } else {
14391 // For any other property we always add it to the queue and then we
14392 // filter it out using the whitelist during the commit.
14393 (updatePayload = updatePayload || []).push(propKey, nextProp);
14394 }
14395 }
14396 if (styleUpdates) {
14397 (updatePayload = updatePayload || []).push(STYLE, styleUpdates);
14398 }
14399 return updatePayload;
14400}
14401
14402// Apply the diff.
14403function updateProperties$1(domElement, updatePayload, tag, lastRawProps, nextRawProps) {
14404 // Update checked *before* name.
14405 // In the middle of an update, it is possible to have multiple checked.
14406 // When a checked radio tries to change name, browser makes another radio's checked false.
14407 if (tag === 'input' && nextRawProps.type === 'radio' && nextRawProps.name != null) {
14408 updateChecked(domElement, nextRawProps);
14409 }
14410
14411 var wasCustomComponentTag = isCustomComponent(tag, lastRawProps);
14412 var isCustomComponentTag = isCustomComponent(tag, nextRawProps);
14413 // Apply the diff.
14414 updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag);
14415
14416 // TODO: Ensure that an update gets scheduled if any of the special props
14417 // changed.
14418 switch (tag) {
14419 case 'input':
14420 // Update the wrapper around inputs *after* updating props. This has to
14421 // happen after `updateDOMProperties`. Otherwise HTML5 input validations
14422 // raise warnings and prevent the new value from being assigned.
14423 updateWrapper(domElement, nextRawProps);
14424 break;
14425 case 'textarea':
14426 updateWrapper$1(domElement, nextRawProps);
14427 break;
14428 case 'select':
14429 // <select> value update needs to occur after <option> children
14430 // reconciliation
14431 postUpdateWrapper(domElement, nextRawProps);
14432 break;
14433 }
14434}
14435
14436function getPossibleStandardName(propName) {
14437 {
14438 var lowerCasedName = propName.toLowerCase();
14439 if (!possibleStandardNames.hasOwnProperty(lowerCasedName)) {
14440 return null;
14441 }
14442 return possibleStandardNames[lowerCasedName] || null;
14443 }
14444 return null;
14445}
14446
14447function diffHydratedProperties$1(domElement, tag, rawProps, parentNamespace, rootContainerElement) {
14448 var isCustomComponentTag = void 0;
14449 var extraAttributeNames = void 0;
14450
14451 {
14452 suppressHydrationWarning = rawProps[SUPPRESS_HYDRATION_WARNING$1] === true;
14453 isCustomComponentTag = isCustomComponent(tag, rawProps);
14454 validatePropertiesInDevelopment(tag, rawProps);
14455 if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
14456 warning_1(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName$2() || 'A component');
14457 didWarnShadyDOM = true;
14458 }
14459 }
14460
14461 // TODO: Make sure that we check isMounted before firing any of these events.
14462 switch (tag) {
14463 case 'iframe':
14464 case 'object':
14465 trapBubbledEvent('topLoad', 'load', domElement);
14466 break;
14467 case 'video':
14468 case 'audio':
14469 // Create listener for each media event
14470 for (var event in mediaEvents) {
14471 if (mediaEvents.hasOwnProperty(event)) {
14472 trapBubbledEvent(event, mediaEvents[event], domElement);
14473 }
14474 }
14475 break;
14476 case 'source':
14477 trapBubbledEvent('topError', 'error', domElement);
14478 break;
14479 case 'img':
14480 case 'image':
14481 trapBubbledEvent('topError', 'error', domElement);
14482 trapBubbledEvent('topLoad', 'load', domElement);
14483 break;
14484 case 'form':
14485 trapBubbledEvent('topReset', 'reset', domElement);
14486 trapBubbledEvent('topSubmit', 'submit', domElement);
14487 break;
14488 case 'details':
14489 trapBubbledEvent('topToggle', 'toggle', domElement);
14490 break;
14491 case 'input':
14492 initWrapperState(domElement, rawProps);
14493 trapBubbledEvent('topInvalid', 'invalid', domElement);
14494 // For controlled components we always need to ensure we're listening
14495 // to onChange. Even if there is no listener.
14496 ensureListeningTo(rootContainerElement, 'onChange');
14497 break;
14498 case 'option':
14499 validateProps(domElement, rawProps);
14500 break;
14501 case 'select':
14502 initWrapperState$1(domElement, rawProps);
14503 trapBubbledEvent('topInvalid', 'invalid', domElement);
14504 // For controlled components we always need to ensure we're listening
14505 // to onChange. Even if there is no listener.
14506 ensureListeningTo(rootContainerElement, 'onChange');
14507 break;
14508 case 'textarea':
14509 initWrapperState$2(domElement, rawProps);
14510 trapBubbledEvent('topInvalid', 'invalid', domElement);
14511 // For controlled components we always need to ensure we're listening
14512 // to onChange. Even if there is no listener.
14513 ensureListeningTo(rootContainerElement, 'onChange');
14514 break;
14515 }
14516
14517 assertValidProps(tag, rawProps, getStack);
14518
14519 {
14520 extraAttributeNames = new Set();
14521 var attributes = domElement.attributes;
14522 for (var i = 0; i < attributes.length; i++) {
14523 var name = attributes[i].name.toLowerCase();
14524 switch (name) {
14525 // Built-in SSR attribute is whitelisted
14526 case 'data-reactroot':
14527 break;
14528 // Controlled attributes are not validated
14529 // TODO: Only ignore them on controlled tags.
14530 case 'value':
14531 break;
14532 case 'checked':
14533 break;
14534 case 'selected':
14535 break;
14536 default:
14537 // Intentionally use the original name.
14538 // See discussion in https://github.com/facebook/react/pull/10676.
14539 extraAttributeNames.add(attributes[i].name);
14540 }
14541 }
14542 }
14543
14544 var updatePayload = null;
14545 for (var propKey in rawProps) {
14546 if (!rawProps.hasOwnProperty(propKey)) {
14547 continue;
14548 }
14549 var nextProp = rawProps[propKey];
14550 if (propKey === CHILDREN) {
14551 // For text content children we compare against textContent. This
14552 // might match additional HTML that is hidden when we read it using
14553 // textContent. E.g. "foo" will match "f<span>oo</span>" but that still
14554 // satisfies our requirement. Our requirement is not to produce perfect
14555 // HTML and attributes. Ideally we should preserve structure but it's
14556 // ok not to if the visible content is still enough to indicate what
14557 // even listeners these nodes might be wired up to.
14558 // TODO: Warn if there is more than a single textNode as a child.
14559 // TODO: Should we use domElement.firstChild.nodeValue to compare?
14560 if (typeof nextProp === 'string') {
14561 if (domElement.textContent !== nextProp) {
14562 if (true && !suppressHydrationWarning) {
14563 warnForTextDifference(domElement.textContent, nextProp);
14564 }
14565 updatePayload = [CHILDREN, nextProp];
14566 }
14567 } else if (typeof nextProp === 'number') {
14568 if (domElement.textContent !== '' + nextProp) {
14569 if (true && !suppressHydrationWarning) {
14570 warnForTextDifference(domElement.textContent, nextProp);
14571 }
14572 updatePayload = [CHILDREN, '' + nextProp];
14573 }
14574 }
14575 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14576 if (nextProp != null) {
14577 if (true && typeof nextProp !== 'function') {
14578 warnForInvalidEventListener(propKey, nextProp);
14579 }
14580 ensureListeningTo(rootContainerElement, propKey);
14581 }
14582 } else if (true &&
14583 // Convince Flow we've calculated it (it's DEV-only in this method.)
14584 typeof isCustomComponentTag === 'boolean') {
14585 // Validate that the properties correspond to their expected values.
14586 var serverValue = void 0;
14587 var propertyInfo = getPropertyInfo(propKey);
14588 if (suppressHydrationWarning) {
14589 // Don't bother comparing. We're ignoring all these warnings.
14590 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1 ||
14591 // Controlled attributes are not validated
14592 // TODO: Only ignore them on controlled tags.
14593 propKey === 'value' || propKey === 'checked' || propKey === 'selected') {
14594 // Noop
14595 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14596 var rawHtml = nextProp ? nextProp[HTML] || '' : '';
14597 var serverHTML = domElement.innerHTML;
14598 var expectedHTML = normalizeHTML(domElement, rawHtml);
14599 if (expectedHTML !== serverHTML) {
14600 warnForPropDifference(propKey, serverHTML, expectedHTML);
14601 }
14602 } else if (propKey === STYLE) {
14603 // $FlowFixMe - Should be inferred as not undefined.
14604 extraAttributeNames['delete'](propKey);
14605 var expectedStyle = createDangerousStringForStyles(nextProp);
14606 serverValue = domElement.getAttribute('style');
14607 if (expectedStyle !== serverValue) {
14608 warnForPropDifference(propKey, serverValue, expectedStyle);
14609 }
14610 } else if (isCustomComponentTag) {
14611 // $FlowFixMe - Should be inferred as not undefined.
14612 extraAttributeNames['delete'](propKey.toLowerCase());
14613 serverValue = getValueForAttribute(domElement, propKey, nextProp);
14614
14615 if (nextProp !== serverValue) {
14616 warnForPropDifference(propKey, serverValue, nextProp);
14617 }
14618 } else if (!shouldIgnoreAttribute(propKey, propertyInfo, isCustomComponentTag) && !shouldRemoveAttribute(propKey, nextProp, propertyInfo, isCustomComponentTag)) {
14619 var isMismatchDueToBadCasing = false;
14620 if (propertyInfo !== null) {
14621 // $FlowFixMe - Should be inferred as not undefined.
14622 extraAttributeNames['delete'](propertyInfo.attributeName);
14623 serverValue = getValueForProperty(domElement, propKey, nextProp, propertyInfo);
14624 } else {
14625 var ownNamespace = parentNamespace;
14626 if (ownNamespace === HTML_NAMESPACE) {
14627 ownNamespace = getIntrinsicNamespace(tag);
14628 }
14629 if (ownNamespace === HTML_NAMESPACE) {
14630 // $FlowFixMe - Should be inferred as not undefined.
14631 extraAttributeNames['delete'](propKey.toLowerCase());
14632 } else {
14633 var standardName = getPossibleStandardName(propKey);
14634 if (standardName !== null && standardName !== propKey) {
14635 // If an SVG prop is supplied with bad casing, it will
14636 // be successfully parsed from HTML, but will produce a mismatch
14637 // (and would be incorrectly rendered on the client).
14638 // However, we already warn about bad casing elsewhere.
14639 // So we'll skip the misleading extra mismatch warning in this case.
14640 isMismatchDueToBadCasing = true;
14641 // $FlowFixMe - Should be inferred as not undefined.
14642 extraAttributeNames['delete'](standardName);
14643 }
14644 // $FlowFixMe - Should be inferred as not undefined.
14645 extraAttributeNames['delete'](propKey);
14646 }
14647 serverValue = getValueForAttribute(domElement, propKey, nextProp);
14648 }
14649
14650 if (nextProp !== serverValue && !isMismatchDueToBadCasing) {
14651 warnForPropDifference(propKey, serverValue, nextProp);
14652 }
14653 }
14654 }
14655 }
14656
14657 {
14658 // $FlowFixMe - Should be inferred as not undefined.
14659 if (extraAttributeNames.size > 0 && !suppressHydrationWarning) {
14660 // $FlowFixMe - Should be inferred as not undefined.
14661 warnForExtraAttributes(extraAttributeNames);
14662 }
14663 }
14664
14665 switch (tag) {
14666 case 'input':
14667 // TODO: Make sure we check if this is still unmounted or do any clean
14668 // up necessary since we never stop tracking anymore.
14669 track(domElement);
14670 postMountWrapper(domElement, rawProps);
14671 break;
14672 case 'textarea':
14673 // TODO: Make sure we check if this is still unmounted or do any clean
14674 // up necessary since we never stop tracking anymore.
14675 track(domElement);
14676 postMountWrapper$3(domElement, rawProps);
14677 break;
14678 case 'select':
14679 case 'option':
14680 // For input and textarea we current always set the value property at
14681 // post mount to force it to diverge from attributes. However, for
14682 // option and select we don't quite do the same thing and select
14683 // is not resilient to the DOM state changing so we don't do that here.
14684 // TODO: Consider not doing this for input and textarea.
14685 break;
14686 default:
14687 if (typeof rawProps.onClick === 'function') {
14688 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14689 trapClickOnNonInteractiveElement(domElement);
14690 }
14691 break;
14692 }
14693
14694 return updatePayload;
14695}
14696
14697function diffHydratedText$1(textNode, text) {
14698 var isDifferent = textNode.nodeValue !== text;
14699 return isDifferent;
14700}
14701
14702function warnForUnmatchedText$1(textNode, text) {
14703 {
14704 warnForTextDifference(textNode.nodeValue, text);
14705 }
14706}
14707
14708function warnForDeletedHydratableElement$1(parentNode, child) {
14709 {
14710 if (didWarnInvalidHydration) {
14711 return;
14712 }
14713 didWarnInvalidHydration = true;
14714 warning_1(false, 'Did not expect server HTML to contain a <%s> in <%s>.', child.nodeName.toLowerCase(), parentNode.nodeName.toLowerCase());
14715 }
14716}
14717
14718function warnForDeletedHydratableText$1(parentNode, child) {
14719 {
14720 if (didWarnInvalidHydration) {
14721 return;
14722 }
14723 didWarnInvalidHydration = true;
14724 warning_1(false, 'Did not expect server HTML to contain the text node "%s" in <%s>.', child.nodeValue, parentNode.nodeName.toLowerCase());
14725 }
14726}
14727
14728function warnForInsertedHydratedElement$1(parentNode, tag, props) {
14729 {
14730 if (didWarnInvalidHydration) {
14731 return;
14732 }
14733 didWarnInvalidHydration = true;
14734 warning_1(false, 'Expected server HTML to contain a matching <%s> in <%s>.', tag, parentNode.nodeName.toLowerCase());
14735 }
14736}
14737
14738function warnForInsertedHydratedText$1(parentNode, text) {
14739 {
14740 if (text === '') {
14741 // We expect to insert empty text nodes since they're not represented in
14742 // the HTML.
14743 // TODO: Remove this special case if we can just avoid inserting empty
14744 // text nodes.
14745 return;
14746 }
14747 if (didWarnInvalidHydration) {
14748 return;
14749 }
14750 didWarnInvalidHydration = true;
14751 warning_1(false, 'Expected server HTML to contain a matching text node for "%s" in <%s>.', text, parentNode.nodeName.toLowerCase());
14752 }
14753}
14754
14755function restoreControlledState$1(domElement, tag, props) {
14756 switch (tag) {
14757 case 'input':
14758 restoreControlledState(domElement, props);
14759 return;
14760 case 'textarea':
14761 restoreControlledState$3(domElement, props);
14762 return;
14763 case 'select':
14764 restoreControlledState$2(domElement, props);
14765 return;
14766 }
14767}
14768
14769var ReactDOMFiberComponent = Object.freeze({
14770 createElement: createElement$1,
14771 createTextNode: createTextNode$1,
14772 setInitialProperties: setInitialProperties$1,
14773 diffProperties: diffProperties$1,
14774 updateProperties: updateProperties$1,
14775 diffHydratedProperties: diffHydratedProperties$1,
14776 diffHydratedText: diffHydratedText$1,
14777 warnForUnmatchedText: warnForUnmatchedText$1,
14778 warnForDeletedHydratableElement: warnForDeletedHydratableElement$1,
14779 warnForDeletedHydratableText: warnForDeletedHydratableText$1,
14780 warnForInsertedHydratedElement: warnForInsertedHydratedElement$1,
14781 warnForInsertedHydratedText: warnForInsertedHydratedText$1,
14782 restoreControlledState: restoreControlledState$1
14783});
14784
14785// TODO: direct imports like some-package/src/* are bad. Fix me.
14786var getCurrentFiberStackAddendum$6 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
14787
14788var validateDOMNesting = emptyFunction_1;
14789
14790{
14791 // This validation code was written based on the HTML5 parsing spec:
14792 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
14793 //
14794 // Note: this does not catch all invalid nesting, nor does it try to (as it's
14795 // not clear what practical benefit doing so provides); instead, we warn only
14796 // for cases where the parser will give a parse tree differing from what React
14797 // intended. For example, <b><div></div></b> is invalid but we don't warn
14798 // because it still parses correctly; we do warn for other cases like nested
14799 // <p> tags where the beginning of the second element implicitly closes the
14800 // first, causing a confusing mess.
14801
14802 // https://html.spec.whatwg.org/multipage/syntax.html#special
14803 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'];
14804
14805 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
14806 var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
14807
14808 // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
14809 // TODO: Distinguish by namespace here -- for <title>, including it here
14810 // errs on the side of fewer warnings
14811 'foreignObject', 'desc', 'title'];
14812
14813 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
14814 var buttonScopeTags = inScopeTags.concat(['button']);
14815
14816 // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
14817 var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
14818
14819 var emptyAncestorInfo = {
14820 current: null,
14821
14822 formTag: null,
14823 aTagInScope: null,
14824 buttonTagInScope: null,
14825 nobrTagInScope: null,
14826 pTagInButtonScope: null,
14827
14828 listItemTagAutoclosing: null,
14829 dlItemTagAutoclosing: null
14830 };
14831
14832 var updatedAncestorInfo$1 = function (oldInfo, tag, instance) {
14833 var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);
14834 var info = { tag: tag, instance: instance };
14835
14836 if (inScopeTags.indexOf(tag) !== -1) {
14837 ancestorInfo.aTagInScope = null;
14838 ancestorInfo.buttonTagInScope = null;
14839 ancestorInfo.nobrTagInScope = null;
14840 }
14841 if (buttonScopeTags.indexOf(tag) !== -1) {
14842 ancestorInfo.pTagInButtonScope = null;
14843 }
14844
14845 // See rules for 'li', 'dd', 'dt' start tags in
14846 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
14847 if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
14848 ancestorInfo.listItemTagAutoclosing = null;
14849 ancestorInfo.dlItemTagAutoclosing = null;
14850 }
14851
14852 ancestorInfo.current = info;
14853
14854 if (tag === 'form') {
14855 ancestorInfo.formTag = info;
14856 }
14857 if (tag === 'a') {
14858 ancestorInfo.aTagInScope = info;
14859 }
14860 if (tag === 'button') {
14861 ancestorInfo.buttonTagInScope = info;
14862 }
14863 if (tag === 'nobr') {
14864 ancestorInfo.nobrTagInScope = info;
14865 }
14866 if (tag === 'p') {
14867 ancestorInfo.pTagInButtonScope = info;
14868 }
14869 if (tag === 'li') {
14870 ancestorInfo.listItemTagAutoclosing = info;
14871 }
14872 if (tag === 'dd' || tag === 'dt') {
14873 ancestorInfo.dlItemTagAutoclosing = info;
14874 }
14875
14876 return ancestorInfo;
14877 };
14878
14879 /**
14880 * Returns whether
14881 */
14882 var isTagValidWithParent = function (tag, parentTag) {
14883 // First, let's check if we're in an unusual parsing mode...
14884 switch (parentTag) {
14885 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
14886 case 'select':
14887 return tag === 'option' || tag === 'optgroup' || tag === '#text';
14888 case 'optgroup':
14889 return tag === 'option' || tag === '#text';
14890 // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
14891 // but
14892 case 'option':
14893 return tag === '#text';
14894 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
14895 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
14896 // No special behavior since these rules fall back to "in body" mode for
14897 // all except special table nodes which cause bad parsing behavior anyway.
14898
14899 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
14900 case 'tr':
14901 return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
14902 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
14903 case 'tbody':
14904 case 'thead':
14905 case 'tfoot':
14906 return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
14907 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
14908 case 'colgroup':
14909 return tag === 'col' || tag === 'template';
14910 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
14911 case 'table':
14912 return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
14913 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
14914 case 'head':
14915 return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
14916 // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
14917 case 'html':
14918 return tag === 'head' || tag === 'body';
14919 case '#document':
14920 return tag === 'html';
14921 }
14922
14923 // Probably in the "in body" parsing mode, so we outlaw only tag combos
14924 // where the parsing rules cause implicit opens or closes to be added.
14925 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
14926 switch (tag) {
14927 case 'h1':
14928 case 'h2':
14929 case 'h3':
14930 case 'h4':
14931 case 'h5':
14932 case 'h6':
14933 return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
14934
14935 case 'rp':
14936 case 'rt':
14937 return impliedEndTags.indexOf(parentTag) === -1;
14938
14939 case 'body':
14940 case 'caption':
14941 case 'col':
14942 case 'colgroup':
14943 case 'frame':
14944 case 'head':
14945 case 'html':
14946 case 'tbody':
14947 case 'td':
14948 case 'tfoot':
14949 case 'th':
14950 case 'thead':
14951 case 'tr':
14952 // These tags are only valid with a few parents that have special child
14953 // parsing rules -- if we're down here, then none of those matched and
14954 // so we allow it only if we don't know what the parent is, as all other
14955 // cases are invalid.
14956 return parentTag == null;
14957 }
14958
14959 return true;
14960 };
14961
14962 /**
14963 * Returns whether
14964 */
14965 var findInvalidAncestorForTag = function (tag, ancestorInfo) {
14966 switch (tag) {
14967 case 'address':
14968 case 'article':
14969 case 'aside':
14970 case 'blockquote':
14971 case 'center':
14972 case 'details':
14973 case 'dialog':
14974 case 'dir':
14975 case 'div':
14976 case 'dl':
14977 case 'fieldset':
14978 case 'figcaption':
14979 case 'figure':
14980 case 'footer':
14981 case 'header':
14982 case 'hgroup':
14983 case 'main':
14984 case 'menu':
14985 case 'nav':
14986 case 'ol':
14987 case 'p':
14988 case 'section':
14989 case 'summary':
14990 case 'ul':
14991 case 'pre':
14992 case 'listing':
14993 case 'table':
14994 case 'hr':
14995 case 'xmp':
14996 case 'h1':
14997 case 'h2':
14998 case 'h3':
14999 case 'h4':
15000 case 'h5':
15001 case 'h6':
15002 return ancestorInfo.pTagInButtonScope;
15003
15004 case 'form':
15005 return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
15006
15007 case 'li':
15008 return ancestorInfo.listItemTagAutoclosing;
15009
15010 case 'dd':
15011 case 'dt':
15012 return ancestorInfo.dlItemTagAutoclosing;
15013
15014 case 'button':
15015 return ancestorInfo.buttonTagInScope;
15016
15017 case 'a':
15018 // Spec says something about storing a list of markers, but it sounds
15019 // equivalent to this check.
15020 return ancestorInfo.aTagInScope;
15021
15022 case 'nobr':
15023 return ancestorInfo.nobrTagInScope;
15024 }
15025
15026 return null;
15027 };
15028
15029 var didWarn = {};
15030
15031 validateDOMNesting = function (childTag, childText, ancestorInfo) {
15032 ancestorInfo = ancestorInfo || emptyAncestorInfo;
15033 var parentInfo = ancestorInfo.current;
15034 var parentTag = parentInfo && parentInfo.tag;
15035
15036 if (childText != null) {
15037 warning_1(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null');
15038 childTag = '#text';
15039 }
15040
15041 var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
15042 var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
15043 var invalidParentOrAncestor = invalidParent || invalidAncestor;
15044 if (!invalidParentOrAncestor) {
15045 return;
15046 }
15047
15048 var ancestorTag = invalidParentOrAncestor.tag;
15049 var addendum = getCurrentFiberStackAddendum$6();
15050
15051 var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + addendum;
15052 if (didWarn[warnKey]) {
15053 return;
15054 }
15055 didWarn[warnKey] = true;
15056
15057 var tagDisplayName = childTag;
15058 var whitespaceInfo = '';
15059 if (childTag === '#text') {
15060 if (/\S/.test(childText)) {
15061 tagDisplayName = 'Text nodes';
15062 } else {
15063 tagDisplayName = 'Whitespace text nodes';
15064 whitespaceInfo = " Make sure you don't have any extra whitespace between tags on " + 'each line of your source code.';
15065 }
15066 } else {
15067 tagDisplayName = '<' + childTag + '>';
15068 }
15069
15070 if (invalidParent) {
15071 var info = '';
15072 if (ancestorTag === 'table' && childTag === 'tr') {
15073 info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
15074 }
15075 warning_1(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>.%s%s%s', tagDisplayName, ancestorTag, whitespaceInfo, info, addendum);
15076 } else {
15077 warning_1(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>.%s', tagDisplayName, ancestorTag, addendum);
15078 }
15079 };
15080
15081 // TODO: turn this into a named export
15082 validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo$1;
15083}
15084
15085var validateDOMNesting$1 = validateDOMNesting;
15086
15087// TODO: This type is shared between the reconciler and ReactDOM, but will
15088// eventually be lifted out to the renderer.
15089
15090// TODO: direct imports like some-package/src/* are bad. Fix me.
15091var createElement = createElement$1;
15092var createTextNode = createTextNode$1;
15093var setInitialProperties = setInitialProperties$1;
15094var diffProperties = diffProperties$1;
15095var updateProperties = updateProperties$1;
15096var diffHydratedProperties = diffHydratedProperties$1;
15097var diffHydratedText = diffHydratedText$1;
15098var warnForUnmatchedText = warnForUnmatchedText$1;
15099var warnForDeletedHydratableElement = warnForDeletedHydratableElement$1;
15100var warnForDeletedHydratableText = warnForDeletedHydratableText$1;
15101var warnForInsertedHydratedElement = warnForInsertedHydratedElement$1;
15102var warnForInsertedHydratedText = warnForInsertedHydratedText$1;
15103var updatedAncestorInfo = validateDOMNesting$1.updatedAncestorInfo;
15104var precacheFiberNode = precacheFiberNode$1;
15105var updateFiberProps = updateFiberProps$1;
15106
15107
15108var SUPPRESS_HYDRATION_WARNING = void 0;
15109var topLevelUpdateWarnings = void 0;
15110var warnOnInvalidCallback = void 0;
15111var didWarnAboutUnstableCreatePortal = false;
15112
15113{
15114 SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
15115 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') {
15116 warning_1(false, 'React depends on Map and Set built-in types. Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills');
15117 }
15118
15119 topLevelUpdateWarnings = function (container) {
15120 {
15121 if (container._reactRootContainer && container.nodeType !== COMMENT_NODE) {
15122 var hostInstance = DOMRenderer.findHostInstanceWithNoPortals(container._reactRootContainer._internalRoot.current);
15123 if (hostInstance) {
15124 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.');
15125 }
15126 }
15127
15128 var isRootRenderedBySomeReact = !!container._reactRootContainer;
15129 var rootEl = getReactRootElementInContainer(container);
15130 var hasNonRootReactChild = !!(rootEl && getInstanceFromNode$1(rootEl));
15131
15132 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.');
15133
15134 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.');
15135 }
15136 };
15137
15138 warnOnInvalidCallback = function (callback, callerName) {
15139 warning_1(callback === null || typeof callback === 'function', '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
15140 };
15141}
15142
15143injection$2.injectFiberControlledHostComponent(ReactDOMFiberComponent);
15144
15145var eventsEnabled = null;
15146var selectionInformation = null;
15147
15148function ReactBatch(root) {
15149 var expirationTime = DOMRenderer.computeUniqueAsyncExpiration();
15150 this._expirationTime = expirationTime;
15151 this._root = root;
15152 this._next = null;
15153 this._callbacks = null;
15154 this._didComplete = false;
15155 this._hasChildren = false;
15156 this._children = null;
15157 this._defer = true;
15158}
15159ReactBatch.prototype.render = function (children) {
15160 !this._defer ? invariant_1(false, 'batch.render: Cannot render a batch that already committed.') : void 0;
15161 this._hasChildren = true;
15162 this._children = children;
15163 var internalRoot = this._root._internalRoot;
15164 var expirationTime = this._expirationTime;
15165 var work = new ReactWork();
15166 DOMRenderer.updateContainerAtExpirationTime(children, internalRoot, null, expirationTime, work._onCommit);
15167 return work;
15168};
15169ReactBatch.prototype.then = function (onComplete) {
15170 if (this._didComplete) {
15171 onComplete();
15172 return;
15173 }
15174 var callbacks = this._callbacks;
15175 if (callbacks === null) {
15176 callbacks = this._callbacks = [];
15177 }
15178 callbacks.push(onComplete);
15179};
15180ReactBatch.prototype.commit = function () {
15181 var internalRoot = this._root._internalRoot;
15182 var firstBatch = internalRoot.firstBatch;
15183 !(this._defer && firstBatch !== null) ? invariant_1(false, 'batch.commit: Cannot commit a batch multiple times.') : void 0;
15184
15185 if (!this._hasChildren) {
15186 // This batch is empty. Return.
15187 this._next = null;
15188 this._defer = false;
15189 return;
15190 }
15191
15192 var expirationTime = this._expirationTime;
15193
15194 // Ensure this is the first batch in the list.
15195 if (firstBatch !== this) {
15196 // This batch is not the earliest batch. We need to move it to the front.
15197 // Update its expiration time to be the expiration time of the earliest
15198 // batch, so that we can flush it without flushing the other batches.
15199 if (this._hasChildren) {
15200 expirationTime = this._expirationTime = firstBatch._expirationTime;
15201 // Rendering this batch again ensures its children will be the final state
15202 // when we flush (updates are processed in insertion order: last
15203 // update wins).
15204 // TODO: This forces a restart. Should we print a warning?
15205 this.render(this._children);
15206 }
15207
15208 // Remove the batch from the list.
15209 var previous = null;
15210 var batch = firstBatch;
15211 while (batch !== this) {
15212 previous = batch;
15213 batch = batch._next;
15214 }
15215 !(previous !== null) ? invariant_1(false, 'batch.commit: Cannot commit a batch multiple times.') : void 0;
15216 previous._next = batch._next;
15217
15218 // Add it to the front.
15219 this._next = firstBatch;
15220 firstBatch = internalRoot.firstBatch = this;
15221 }
15222
15223 // Synchronously flush all the work up to this batch's expiration time.
15224 this._defer = false;
15225 DOMRenderer.flushRoot(internalRoot, expirationTime);
15226
15227 // Pop the batch from the list.
15228 var next = this._next;
15229 this._next = null;
15230 firstBatch = internalRoot.firstBatch = next;
15231
15232 // Append the next earliest batch's children to the update queue.
15233 if (firstBatch !== null && firstBatch._hasChildren) {
15234 firstBatch.render(firstBatch._children);
15235 }
15236};
15237ReactBatch.prototype._onComplete = function () {
15238 if (this._didComplete) {
15239 return;
15240 }
15241 this._didComplete = true;
15242 var callbacks = this._callbacks;
15243 if (callbacks === null) {
15244 return;
15245 }
15246 // TODO: Error handling.
15247 for (var i = 0; i < callbacks.length; i++) {
15248 var _callback = callbacks[i];
15249 _callback();
15250 }
15251};
15252
15253function ReactWork() {
15254 this._callbacks = null;
15255 this._didCommit = false;
15256 // TODO: Avoid need to bind by replacing callbacks in the update queue with
15257 // list of Work objects.
15258 this._onCommit = this._onCommit.bind(this);
15259}
15260ReactWork.prototype.then = function (onCommit) {
15261 if (this._didCommit) {
15262 onCommit();
15263 return;
15264 }
15265 var callbacks = this._callbacks;
15266 if (callbacks === null) {
15267 callbacks = this._callbacks = [];
15268 }
15269 callbacks.push(onCommit);
15270};
15271ReactWork.prototype._onCommit = function () {
15272 if (this._didCommit) {
15273 return;
15274 }
15275 this._didCommit = true;
15276 var callbacks = this._callbacks;
15277 if (callbacks === null) {
15278 return;
15279 }
15280 // TODO: Error handling.
15281 for (var i = 0; i < callbacks.length; i++) {
15282 var _callback2 = callbacks[i];
15283 !(typeof _callback2 === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback2) : void 0;
15284 _callback2();
15285 }
15286};
15287
15288function ReactRoot(container, isAsync, hydrate) {
15289 var root = DOMRenderer.createContainer(container, isAsync, hydrate);
15290 this._internalRoot = root;
15291}
15292ReactRoot.prototype.render = function (children, callback) {
15293 var root = this._internalRoot;
15294 var work = new ReactWork();
15295 callback = callback === undefined ? null : callback;
15296 {
15297 warnOnInvalidCallback(callback, 'render');
15298 }
15299 if (callback !== null) {
15300 work.then(callback);
15301 }
15302 DOMRenderer.updateContainer(children, root, null, work._onCommit);
15303 return work;
15304};
15305ReactRoot.prototype.unmount = function (callback) {
15306 var root = this._internalRoot;
15307 var work = new ReactWork();
15308 callback = callback === undefined ? null : callback;
15309 {
15310 warnOnInvalidCallback(callback, 'render');
15311 }
15312 if (callback !== null) {
15313 work.then(callback);
15314 }
15315 DOMRenderer.updateContainer(null, root, null, work._onCommit);
15316 return work;
15317};
15318ReactRoot.prototype.legacy_renderSubtreeIntoContainer = function (parentComponent, children, callback) {
15319 var root = this._internalRoot;
15320 var work = new ReactWork();
15321 callback = callback === undefined ? null : callback;
15322 {
15323 warnOnInvalidCallback(callback, 'render');
15324 }
15325 if (callback !== null) {
15326 work.then(callback);
15327 }
15328 DOMRenderer.updateContainer(children, root, parentComponent, work._onCommit);
15329 return work;
15330};
15331ReactRoot.prototype.createBatch = function () {
15332 var batch = new ReactBatch(this);
15333 var expirationTime = batch._expirationTime;
15334
15335 var internalRoot = this._internalRoot;
15336 var firstBatch = internalRoot.firstBatch;
15337 if (firstBatch === null) {
15338 internalRoot.firstBatch = batch;
15339 batch._next = null;
15340 } else {
15341 // Insert sorted by expiration time then insertion order
15342 var insertAfter = null;
15343 var insertBefore = firstBatch;
15344 while (insertBefore !== null && insertBefore._expirationTime <= expirationTime) {
15345 insertAfter = insertBefore;
15346 insertBefore = insertBefore._next;
15347 }
15348 batch._next = insertBefore;
15349 if (insertAfter !== null) {
15350 insertAfter._next = batch;
15351 }
15352 }
15353
15354 return batch;
15355};
15356
15357/**
15358 * True if the supplied DOM node is a valid node element.
15359 *
15360 * @param {?DOMElement} node The candidate DOM node.
15361 * @return {boolean} True if the DOM is a valid DOM node.
15362 * @internal
15363 */
15364function isValidContainer(node) {
15365 return !!(node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || node.nodeType === COMMENT_NODE && node.nodeValue === ' react-mount-point-unstable '));
15366}
15367
15368function getReactRootElementInContainer(container) {
15369 if (!container) {
15370 return null;
15371 }
15372
15373 if (container.nodeType === DOCUMENT_NODE) {
15374 return container.documentElement;
15375 } else {
15376 return container.firstChild;
15377 }
15378}
15379
15380function shouldHydrateDueToLegacyHeuristic(container) {
15381 var rootElement = getReactRootElementInContainer(container);
15382 return !!(rootElement && rootElement.nodeType === ELEMENT_NODE && rootElement.hasAttribute(ROOT_ATTRIBUTE_NAME));
15383}
15384
15385function shouldAutoFocusHostComponent(type, props) {
15386 switch (type) {
15387 case 'button':
15388 case 'input':
15389 case 'select':
15390 case 'textarea':
15391 return !!props.autoFocus;
15392 }
15393 return false;
15394}
15395
15396var DOMRenderer = reactReconciler({
15397 getRootHostContext: function (rootContainerInstance) {
15398 var type = void 0;
15399 var namespace = void 0;
15400 var nodeType = rootContainerInstance.nodeType;
15401 switch (nodeType) {
15402 case DOCUMENT_NODE:
15403 case DOCUMENT_FRAGMENT_NODE:
15404 {
15405 type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment';
15406 var root = rootContainerInstance.documentElement;
15407 namespace = root ? root.namespaceURI : getChildNamespace(null, '');
15408 break;
15409 }
15410 default:
15411 {
15412 var container = nodeType === COMMENT_NODE ? rootContainerInstance.parentNode : rootContainerInstance;
15413 var ownNamespace = container.namespaceURI || null;
15414 type = container.tagName;
15415 namespace = getChildNamespace(ownNamespace, type);
15416 break;
15417 }
15418 }
15419 {
15420 var validatedTag = type.toLowerCase();
15421 var _ancestorInfo = updatedAncestorInfo(null, validatedTag, null);
15422 return { namespace: namespace, ancestorInfo: _ancestorInfo };
15423 }
15424 return namespace;
15425 },
15426 getChildHostContext: function (parentHostContext, type) {
15427 {
15428 var parentHostContextDev = parentHostContext;
15429 var _namespace = getChildNamespace(parentHostContextDev.namespace, type);
15430 var _ancestorInfo2 = updatedAncestorInfo(parentHostContextDev.ancestorInfo, type, null);
15431 return { namespace: _namespace, ancestorInfo: _ancestorInfo2 };
15432 }
15433 var parentNamespace = parentHostContext;
15434 return getChildNamespace(parentNamespace, type);
15435 },
15436 getPublicInstance: function (instance) {
15437 return instance;
15438 },
15439 prepareForCommit: function () {
15440 eventsEnabled = isEnabled();
15441 selectionInformation = getSelectionInformation();
15442 setEnabled(false);
15443 },
15444 resetAfterCommit: function () {
15445 restoreSelection(selectionInformation);
15446 selectionInformation = null;
15447 setEnabled(eventsEnabled);
15448 eventsEnabled = null;
15449 },
15450 createInstance: function (type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
15451 var parentNamespace = void 0;
15452 {
15453 // TODO: take namespace into account when validating.
15454 var hostContextDev = hostContext;
15455 validateDOMNesting$1(type, null, hostContextDev.ancestorInfo);
15456 if (typeof props.children === 'string' || typeof props.children === 'number') {
15457 var string = '' + props.children;
15458 var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type, null);
15459 validateDOMNesting$1(null, string, ownAncestorInfo);
15460 }
15461 parentNamespace = hostContextDev.namespace;
15462 }
15463 var domElement = createElement(type, props, rootContainerInstance, parentNamespace);
15464 precacheFiberNode(internalInstanceHandle, domElement);
15465 updateFiberProps(domElement, props);
15466 return domElement;
15467 },
15468 appendInitialChild: function (parentInstance, child) {
15469 parentInstance.appendChild(child);
15470 },
15471 finalizeInitialChildren: function (domElement, type, props, rootContainerInstance) {
15472 setInitialProperties(domElement, type, props, rootContainerInstance);
15473 return shouldAutoFocusHostComponent(type, props);
15474 },
15475 prepareUpdate: function (domElement, type, oldProps, newProps, rootContainerInstance, hostContext) {
15476 {
15477 var hostContextDev = hostContext;
15478 if (typeof newProps.children !== typeof oldProps.children && (typeof newProps.children === 'string' || typeof newProps.children === 'number')) {
15479 var string = '' + newProps.children;
15480 var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type, null);
15481 validateDOMNesting$1(null, string, ownAncestorInfo);
15482 }
15483 }
15484 return diffProperties(domElement, type, oldProps, newProps, rootContainerInstance);
15485 },
15486 shouldSetTextContent: function (type, props) {
15487 return type === 'textarea' || typeof props.children === 'string' || typeof props.children === 'number' || typeof props.dangerouslySetInnerHTML === 'object' && props.dangerouslySetInnerHTML !== null && typeof props.dangerouslySetInnerHTML.__html === 'string';
15488 },
15489 shouldDeprioritizeSubtree: function (type, props) {
15490 return !!props.hidden;
15491 },
15492 createTextInstance: function (text, rootContainerInstance, hostContext, internalInstanceHandle) {
15493 {
15494 var hostContextDev = hostContext;
15495 validateDOMNesting$1(null, text, hostContextDev.ancestorInfo);
15496 }
15497 var textNode = createTextNode(text, rootContainerInstance);
15498 precacheFiberNode(internalInstanceHandle, textNode);
15499 return textNode;
15500 },
15501
15502
15503 now: now,
15504
15505 mutation: {
15506 commitMount: function (domElement, type, newProps, internalInstanceHandle) {
15507 // Despite the naming that might imply otherwise, this method only
15508 // fires if there is an `Update` effect scheduled during mounting.
15509 // This happens if `finalizeInitialChildren` returns `true` (which it
15510 // does to implement the `autoFocus` attribute on the client). But
15511 // there are also other cases when this might happen (such as patching
15512 // up text content during hydration mismatch). So we'll check this again.
15513 if (shouldAutoFocusHostComponent(type, newProps)) {
15514 domElement.focus();
15515 }
15516 },
15517 commitUpdate: function (domElement, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
15518 // Update the props handle so that we know which props are the ones with
15519 // with current event handlers.
15520 updateFiberProps(domElement, newProps);
15521 // Apply the diff to the DOM node.
15522 updateProperties(domElement, updatePayload, type, oldProps, newProps);
15523 },
15524 resetTextContent: function (domElement) {
15525 domElement.textContent = '';
15526 },
15527 commitTextUpdate: function (textInstance, oldText, newText) {
15528 textInstance.nodeValue = newText;
15529 },
15530 appendChild: function (parentInstance, child) {
15531 parentInstance.appendChild(child);
15532 },
15533 appendChildToContainer: function (container, child) {
15534 if (container.nodeType === COMMENT_NODE) {
15535 container.parentNode.insertBefore(child, container);
15536 } else {
15537 container.appendChild(child);
15538 }
15539 },
15540 insertBefore: function (parentInstance, child, beforeChild) {
15541 parentInstance.insertBefore(child, beforeChild);
15542 },
15543 insertInContainerBefore: function (container, child, beforeChild) {
15544 if (container.nodeType === COMMENT_NODE) {
15545 container.parentNode.insertBefore(child, beforeChild);
15546 } else {
15547 container.insertBefore(child, beforeChild);
15548 }
15549 },
15550 removeChild: function (parentInstance, child) {
15551 parentInstance.removeChild(child);
15552 },
15553 removeChildFromContainer: function (container, child) {
15554 if (container.nodeType === COMMENT_NODE) {
15555 container.parentNode.removeChild(child);
15556 } else {
15557 container.removeChild(child);
15558 }
15559 }
15560 },
15561
15562 hydration: {
15563 canHydrateInstance: function (instance, type, props) {
15564 if (instance.nodeType !== ELEMENT_NODE || type.toLowerCase() !== instance.nodeName.toLowerCase()) {
15565 return null;
15566 }
15567 // This has now been refined to an element node.
15568 return instance;
15569 },
15570 canHydrateTextInstance: function (instance, text) {
15571 if (text === '' || instance.nodeType !== TEXT_NODE) {
15572 // Empty strings are not parsed by HTML so there won't be a correct match here.
15573 return null;
15574 }
15575 // This has now been refined to a text node.
15576 return instance;
15577 },
15578 getNextHydratableSibling: function (instance) {
15579 var node = instance.nextSibling;
15580 // Skip non-hydratable nodes.
15581 while (node && node.nodeType !== ELEMENT_NODE && node.nodeType !== TEXT_NODE) {
15582 node = node.nextSibling;
15583 }
15584 return node;
15585 },
15586 getFirstHydratableChild: function (parentInstance) {
15587 var next = parentInstance.firstChild;
15588 // Skip non-hydratable nodes.
15589 while (next && next.nodeType !== ELEMENT_NODE && next.nodeType !== TEXT_NODE) {
15590 next = next.nextSibling;
15591 }
15592 return next;
15593 },
15594 hydrateInstance: function (instance, type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
15595 precacheFiberNode(internalInstanceHandle, instance);
15596 // TODO: Possibly defer this until the commit phase where all the events
15597 // get attached.
15598 updateFiberProps(instance, props);
15599 var parentNamespace = void 0;
15600 {
15601 var hostContextDev = hostContext;
15602 parentNamespace = hostContextDev.namespace;
15603 }
15604 return diffHydratedProperties(instance, type, props, parentNamespace, rootContainerInstance);
15605 },
15606 hydrateTextInstance: function (textInstance, text, internalInstanceHandle) {
15607 precacheFiberNode(internalInstanceHandle, textInstance);
15608 return diffHydratedText(textInstance, text);
15609 },
15610 didNotMatchHydratedContainerTextInstance: function (parentContainer, textInstance, text) {
15611 {
15612 warnForUnmatchedText(textInstance, text);
15613 }
15614 },
15615 didNotMatchHydratedTextInstance: function (parentType, parentProps, parentInstance, textInstance, text) {
15616 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15617 warnForUnmatchedText(textInstance, text);
15618 }
15619 },
15620 didNotHydrateContainerInstance: function (parentContainer, instance) {
15621 {
15622 if (instance.nodeType === 1) {
15623 warnForDeletedHydratableElement(parentContainer, instance);
15624 } else {
15625 warnForDeletedHydratableText(parentContainer, instance);
15626 }
15627 }
15628 },
15629 didNotHydrateInstance: function (parentType, parentProps, parentInstance, instance) {
15630 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15631 if (instance.nodeType === 1) {
15632 warnForDeletedHydratableElement(parentInstance, instance);
15633 } else {
15634 warnForDeletedHydratableText(parentInstance, instance);
15635 }
15636 }
15637 },
15638 didNotFindHydratableContainerInstance: function (parentContainer, type, props) {
15639 {
15640 warnForInsertedHydratedElement(parentContainer, type, props);
15641 }
15642 },
15643 didNotFindHydratableContainerTextInstance: function (parentContainer, text) {
15644 {
15645 warnForInsertedHydratedText(parentContainer, text);
15646 }
15647 },
15648 didNotFindHydratableInstance: function (parentType, parentProps, parentInstance, type, props) {
15649 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15650 warnForInsertedHydratedElement(parentInstance, type, props);
15651 }
15652 },
15653 didNotFindHydratableTextInstance: function (parentType, parentProps, parentInstance, text) {
15654 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15655 warnForInsertedHydratedText(parentInstance, text);
15656 }
15657 }
15658 },
15659
15660 scheduleDeferredCallback: rIC,
15661 cancelDeferredCallback: cIC,
15662
15663 useSyncScheduling: !enableAsyncSchedulingByDefaultInReactDOM
15664});
15665
15666injection$3.injectFiberBatchedUpdates(DOMRenderer.batchedUpdates);
15667
15668var warnedAboutHydrateAPI = false;
15669
15670function legacyCreateRootFromDOMContainer(container, forceHydrate) {
15671 var shouldHydrate = forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
15672 // First clear any existing content.
15673 if (!shouldHydrate) {
15674 var warned = false;
15675 var rootSibling = void 0;
15676 while (rootSibling = container.lastChild) {
15677 {
15678 if (!warned && rootSibling.nodeType === ELEMENT_NODE && rootSibling.hasAttribute(ROOT_ATTRIBUTE_NAME)) {
15679 warned = true;
15680 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.');
15681 }
15682 }
15683 container.removeChild(rootSibling);
15684 }
15685 }
15686 {
15687 if (shouldHydrate && !forceHydrate && !warnedAboutHydrateAPI) {
15688 warnedAboutHydrateAPI = true;
15689 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.');
15690 }
15691 }
15692 // Legacy roots are not async by default.
15693 var isAsync = false;
15694 return new ReactRoot(container, isAsync, shouldHydrate);
15695}
15696
15697function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {
15698 // TODO: Ensure all entry points contain this check
15699 !isValidContainer(container) ? invariant_1(false, 'Target container is not a DOM element.') : void 0;
15700
15701 {
15702 topLevelUpdateWarnings(container);
15703 }
15704
15705 // TODO: Without `any` type, Flow says "Property cannot be accessed on any
15706 // member of intersection type." Whyyyyyy.
15707 var root = container._reactRootContainer;
15708 if (!root) {
15709 // Initial mount
15710 root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate);
15711 if (typeof callback === 'function') {
15712 var originalCallback = callback;
15713 callback = function () {
15714 var instance = DOMRenderer.getPublicRootInstance(root._internalRoot);
15715 originalCallback.call(instance);
15716 };
15717 }
15718 // Initial mount should not be batched.
15719 DOMRenderer.unbatchedUpdates(function () {
15720 if (parentComponent != null) {
15721 root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
15722 } else {
15723 root.render(children, callback);
15724 }
15725 });
15726 } else {
15727 if (typeof callback === 'function') {
15728 var _originalCallback = callback;
15729 callback = function () {
15730 var instance = DOMRenderer.getPublicRootInstance(root._internalRoot);
15731 _originalCallback.call(instance);
15732 };
15733 }
15734 // Update
15735 if (parentComponent != null) {
15736 root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
15737 } else {
15738 root.render(children, callback);
15739 }
15740 }
15741 return DOMRenderer.getPublicRootInstance(root._internalRoot);
15742}
15743
15744function createPortal(children, container) {
15745 var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
15746
15747 !isValidContainer(container) ? invariant_1(false, 'Target container is not a DOM element.') : void 0;
15748 // TODO: pass ReactDOM portal implementation as third argument
15749 return createPortal$1(children, container, null, key);
15750}
15751
15752var ReactDOM = {
15753 createPortal: createPortal,
15754
15755 findDOMNode: function (componentOrElement) {
15756 {
15757 var owner = ReactCurrentOwner.current;
15758 if (owner !== null) {
15759 var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender;
15760 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');
15761 owner.stateNode._warnedAboutRefsInRender = true;
15762 }
15763 }
15764 if (componentOrElement == null) {
15765 return null;
15766 }
15767 if (componentOrElement.nodeType === ELEMENT_NODE) {
15768 return componentOrElement;
15769 }
15770
15771 var inst = get(componentOrElement);
15772 if (inst) {
15773 return DOMRenderer.findHostInstance(inst);
15774 }
15775
15776 if (typeof componentOrElement.render === 'function') {
15777 invariant_1(false, 'Unable to find node on an unmounted component.');
15778 } else {
15779 invariant_1(false, 'Element appears to be neither ReactComponent nor DOMNode. Keys: %s', Object.keys(componentOrElement));
15780 }
15781 },
15782 hydrate: function (element, container, callback) {
15783 // TODO: throw or warn if we couldn't hydrate?
15784 return legacyRenderSubtreeIntoContainer(null, element, container, true, callback);
15785 },
15786 render: function (element, container, callback) {
15787 return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
15788 },
15789 unstable_renderSubtreeIntoContainer: function (parentComponent, element, containerNode, callback) {
15790 !(parentComponent != null && has(parentComponent)) ? invariant_1(false, 'parentComponent must be a valid React Component') : void 0;
15791 return legacyRenderSubtreeIntoContainer(parentComponent, element, containerNode, false, callback);
15792 },
15793 unmountComponentAtNode: function (container) {
15794 !isValidContainer(container) ? invariant_1(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : void 0;
15795
15796 if (container._reactRootContainer) {
15797 {
15798 var rootEl = getReactRootElementInContainer(container);
15799 var renderedByDifferentReact = rootEl && !getInstanceFromNode$1(rootEl);
15800 warning_1(!renderedByDifferentReact, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.');
15801 }
15802
15803 // Unmount should not be batched.
15804 DOMRenderer.unbatchedUpdates(function () {
15805 legacyRenderSubtreeIntoContainer(null, null, container, false, function () {
15806 container._reactRootContainer = null;
15807 });
15808 });
15809 // If you call unmountComponentAtNode twice in quick succession, you'll
15810 // get `true` twice. That's probably fine?
15811 return true;
15812 } else {
15813 {
15814 var _rootEl = getReactRootElementInContainer(container);
15815 var hasNonRootReactChild = !!(_rootEl && getInstanceFromNode$1(_rootEl));
15816
15817 // Check if the container itself is a React root node.
15818 var isContainerReactRoot = container.nodeType === 1 && isValidContainer(container.parentNode) && !!container.parentNode._reactRootContainer;
15819
15820 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.');
15821 }
15822
15823 return false;
15824 }
15825 },
15826
15827
15828 // Temporary alias since we already shipped React 16 RC with it.
15829 // TODO: remove in React 17.
15830 unstable_createPortal: function () {
15831 if (!didWarnAboutUnstableCreatePortal) {
15832 didWarnAboutUnstableCreatePortal = true;
15833 lowPriorityWarning$1(false, 'The ReactDOM.unstable_createPortal() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactDOM.createPortal() instead. It has the exact same API, ' + 'but without the "unstable_" prefix.');
15834 }
15835 return createPortal.apply(undefined, arguments);
15836 },
15837
15838
15839 unstable_batchedUpdates: batchedUpdates,
15840
15841 unstable_deferredUpdates: DOMRenderer.deferredUpdates,
15842
15843 flushSync: DOMRenderer.flushSync,
15844
15845 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
15846 // For TapEventPlugin which is popular in open source
15847 EventPluginHub: EventPluginHub,
15848 // Used by test-utils
15849 EventPluginRegistry: EventPluginRegistry,
15850 EventPropagators: EventPropagators,
15851 ReactControlledComponent: ReactControlledComponent,
15852 ReactDOMComponentTree: ReactDOMComponentTree,
15853 ReactDOMEventListener: ReactDOMEventListener
15854 }
15855};
15856
15857{
15858 // Show deprecation warnings as we don't want to support injection forever.
15859 // We do it now to let the internal injection happen without warnings.
15860 // https://github.com/facebook/react/issues/11689
15861 enableWarningOnInjection();
15862}
15863
15864if (enableCreateRoot) {
15865 ReactDOM.createRoot = function createRoot(container, options) {
15866 var hydrate = options != null && options.hydrate === true;
15867 return new ReactRoot(container, true, hydrate);
15868 };
15869}
15870
15871var foundDevTools = DOMRenderer.injectIntoDevTools({
15872 findFiberByHostInstance: getClosestInstanceFromNode,
15873 bundleType: 1,
15874 version: ReactVersion,
15875 rendererPackageName: 'react-dom'
15876});
15877
15878{
15879 if (!foundDevTools && ExecutionEnvironment_1.canUseDOM && window.top === window.self) {
15880 // If we're in Chrome or Firefox, provide a download link if not installed.
15881 if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
15882 var protocol = window.location.protocol;
15883 // Don't warn in exotic cases like chrome-extension://.
15884 if (/^(https?|file):$/.test(protocol)) {
15885 console.info('%cDownload the React DevTools ' + 'for a better development experience: ' + 'https://fb.me/react-devtools' + (protocol === 'file:' ? '\nYou might need to use a local HTTP server (instead of file://): ' + 'https://fb.me/react-devtools-faq' : ''), 'font-weight:bold');
15886 }
15887 }
15888 }
15889}
15890
15891
15892
15893var ReactDOM$2 = Object.freeze({
15894 default: ReactDOM
15895});
15896
15897var ReactDOM$3 = ( ReactDOM$2 && ReactDOM ) || ReactDOM$2;
15898
15899// TODO: decide on the top-level export form.
15900// This is hacky but makes it work with both Rollup and Jest.
15901var reactDom = ReactDOM$3['default'] ? ReactDOM$3['default'] : ReactDOM$3;
15902
15903return reactDom;
15904
15905})));