· 8 years ago · Jan 08, 2018, 12:04 PM
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 = null;
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
920function runEventsInBatch(events, simulated) {
921 if (events !== null) {
922 eventQueue = accumulateInto(eventQueue, events);
923 }
924
925 // Set `eventQueue` to null before processing it so that we can tell if more
926 // events get enqueued while processing.
927 var processingEventQueue = eventQueue;
928 eventQueue = null;
929
930 if (!processingEventQueue) {
931 return;
932 }
933
934 if (simulated) {
935 forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);
936 } else {
937 forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);
938 }
939 !!eventQueue ? invariant_1(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : void 0;
940 // This would be a good time to rethrow if any of the event handlers threw.
941 ReactErrorUtils.rethrowCaughtError();
942}
943
944function runExtractedEventsInBatch(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
945 var events = extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
946 runEventsInBatch(events, false);
947}
948
949var EventPluginHub = Object.freeze({
950 injection: injection,
951 getListener: getListener,
952 runEventsInBatch: runEventsInBatch,
953 runExtractedEventsInBatch: runExtractedEventsInBatch
954});
955
956var IndeterminateComponent = 0; // Before we know whether it is functional or class
957var FunctionalComponent = 1;
958var ClassComponent = 2;
959var HostRoot = 3; // Root of a host tree. Could be nested inside another node.
960var HostPortal = 4; // A subtree. Could be an entry point to a different renderer.
961var HostComponent = 5;
962var HostText = 6;
963var CallComponent = 7;
964var CallHandlerPhase = 8;
965var ReturnComponent = 9;
966var Fragment = 10;
967
968var randomKey = Math.random().toString(36).slice(2);
969var internalInstanceKey = '__reactInternalInstance$' + randomKey;
970var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
971
972function precacheFiberNode$1(hostInst, node) {
973 node[internalInstanceKey] = hostInst;
974}
975
976/**
977 * Given a DOM node, return the closest ReactDOMComponent or
978 * ReactDOMTextComponent instance ancestor.
979 */
980function getClosestInstanceFromNode(node) {
981 if (node[internalInstanceKey]) {
982 return node[internalInstanceKey];
983 }
984
985 while (!node[internalInstanceKey]) {
986 if (node.parentNode) {
987 node = node.parentNode;
988 } else {
989 // Top of the tree. This node must not be part of a React tree (or is
990 // unmounted, potentially).
991 return null;
992 }
993 }
994
995 var inst = node[internalInstanceKey];
996 if (inst.tag === HostComponent || inst.tag === HostText) {
997 // In Fiber, this will always be the deepest root.
998 return inst;
999 }
1000
1001 return null;
1002}
1003
1004/**
1005 * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
1006 * instance, or null if the node was not rendered by this React.
1007 */
1008function getInstanceFromNode$1(node) {
1009 var inst = node[internalInstanceKey];
1010 if (inst) {
1011 if (inst.tag === HostComponent || inst.tag === HostText) {
1012 return inst;
1013 } else {
1014 return null;
1015 }
1016 }
1017 return null;
1018}
1019
1020/**
1021 * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
1022 * DOM node.
1023 */
1024function getNodeFromInstance$1(inst) {
1025 if (inst.tag === HostComponent || inst.tag === HostText) {
1026 // In Fiber this, is just the state node right now. We assume it will be
1027 // a host component or host text.
1028 return inst.stateNode;
1029 }
1030
1031 // Without this first invariant, passing a non-DOM-component triggers the next
1032 // invariant for a missing parent, which is super confusing.
1033 invariant_1(false, 'getNodeFromInstance: Invalid argument.');
1034}
1035
1036function getFiberCurrentPropsFromNode$1(node) {
1037 return node[internalEventHandlersKey] || null;
1038}
1039
1040function updateFiberProps$1(node, props) {
1041 node[internalEventHandlersKey] = props;
1042}
1043
1044var ReactDOMComponentTree = Object.freeze({
1045 precacheFiberNode: precacheFiberNode$1,
1046 getClosestInstanceFromNode: getClosestInstanceFromNode,
1047 getInstanceFromNode: getInstanceFromNode$1,
1048 getNodeFromInstance: getNodeFromInstance$1,
1049 getFiberCurrentPropsFromNode: getFiberCurrentPropsFromNode$1,
1050 updateFiberProps: updateFiberProps$1
1051});
1052
1053function getParent(inst) {
1054 do {
1055 inst = inst['return'];
1056 // TODO: If this is a HostRoot we might want to bail out.
1057 // That is depending on if we want nested subtrees (layers) to bubble
1058 // events to their parent. We could also go through parentNode on the
1059 // host node but that wouldn't work for React Native and doesn't let us
1060 // do the portal feature.
1061 } while (inst && inst.tag !== HostComponent);
1062 if (inst) {
1063 return inst;
1064 }
1065 return null;
1066}
1067
1068/**
1069 * Return the lowest common ancestor of A and B, or null if they are in
1070 * different trees.
1071 */
1072function getLowestCommonAncestor(instA, instB) {
1073 var depthA = 0;
1074 for (var tempA = instA; tempA; tempA = getParent(tempA)) {
1075 depthA++;
1076 }
1077 var depthB = 0;
1078 for (var tempB = instB; tempB; tempB = getParent(tempB)) {
1079 depthB++;
1080 }
1081
1082 // If A is deeper, crawl up.
1083 while (depthA - depthB > 0) {
1084 instA = getParent(instA);
1085 depthA--;
1086 }
1087
1088 // If B is deeper, crawl up.
1089 while (depthB - depthA > 0) {
1090 instB = getParent(instB);
1091 depthB--;
1092 }
1093
1094 // Walk in lockstep until we find a match.
1095 var depth = depthA;
1096 while (depth--) {
1097 if (instA === instB || instA === instB.alternate) {
1098 return instA;
1099 }
1100 instA = getParent(instA);
1101 instB = getParent(instB);
1102 }
1103 return null;
1104}
1105
1106/**
1107 * Return if A is an ancestor of B.
1108 */
1109
1110
1111/**
1112 * Return the parent instance of the passed-in instance.
1113 */
1114function getParentInstance(inst) {
1115 return getParent(inst);
1116}
1117
1118/**
1119 * Simulates the traversal of a two-phase, capture/bubble event dispatch.
1120 */
1121function traverseTwoPhase(inst, fn, arg) {
1122 var path = [];
1123 while (inst) {
1124 path.push(inst);
1125 inst = getParent(inst);
1126 }
1127 var i = void 0;
1128 for (i = path.length; i-- > 0;) {
1129 fn(path[i], 'captured', arg);
1130 }
1131 for (i = 0; i < path.length; i++) {
1132 fn(path[i], 'bubbled', arg);
1133 }
1134}
1135
1136/**
1137 * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
1138 * should would receive a `mouseEnter` or `mouseLeave` event.
1139 *
1140 * Does not invoke the callback on the nearest common ancestor because nothing
1141 * "entered" or "left" that element.
1142 */
1143function traverseEnterLeave(from, to, fn, argFrom, argTo) {
1144 var common = from && to ? getLowestCommonAncestor(from, to) : null;
1145 var pathFrom = [];
1146 while (true) {
1147 if (!from) {
1148 break;
1149 }
1150 if (from === common) {
1151 break;
1152 }
1153 var alternate = from.alternate;
1154 if (alternate !== null && alternate === common) {
1155 break;
1156 }
1157 pathFrom.push(from);
1158 from = getParent(from);
1159 }
1160 var pathTo = [];
1161 while (true) {
1162 if (!to) {
1163 break;
1164 }
1165 if (to === common) {
1166 break;
1167 }
1168 var _alternate = to.alternate;
1169 if (_alternate !== null && _alternate === common) {
1170 break;
1171 }
1172 pathTo.push(to);
1173 to = getParent(to);
1174 }
1175 for (var i = 0; i < pathFrom.length; i++) {
1176 fn(pathFrom[i], 'bubbled', argFrom);
1177 }
1178 for (var _i = pathTo.length; _i-- > 0;) {
1179 fn(pathTo[_i], 'captured', argTo);
1180 }
1181}
1182
1183/**
1184 * Some event types have a notion of different registration names for different
1185 * "phases" of propagation. This finds listeners by a given phase.
1186 */
1187function listenerAtPhase(inst, event, propagationPhase) {
1188 var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
1189 return getListener(inst, registrationName);
1190}
1191
1192/**
1193 * A small set of propagation patterns, each of which will accept a small amount
1194 * of information, and generate a set of "dispatch ready event objects" - which
1195 * are sets of events that have already been annotated with a set of dispatched
1196 * listener functions/ids. The API is designed this way to discourage these
1197 * propagation strategies from actually executing the dispatches, since we
1198 * always want to collect the entire set of dispatches before executing even a
1199 * single one.
1200 */
1201
1202/**
1203 * Tags a `SyntheticEvent` with dispatched listeners. Creating this function
1204 * here, allows us to not have to bind or create functions for each event.
1205 * Mutating the event's members allows us to not have to create a wrapping
1206 * "dispatch" object that pairs the event with the listener.
1207 */
1208function accumulateDirectionalDispatches(inst, phase, event) {
1209 {
1210 warning_1(inst, 'Dispatching inst must not be null');
1211 }
1212 var listener = listenerAtPhase(inst, event, phase);
1213 if (listener) {
1214 event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
1215 event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
1216 }
1217}
1218
1219/**
1220 * Collect dispatches (must be entirely collected before dispatching - see unit
1221 * tests). Lazily allocate the array to conserve memory. We must loop through
1222 * each event and perform the traversal for each one. We cannot perform a
1223 * single traversal for the entire collection of events because each event may
1224 * have a different target.
1225 */
1226function accumulateTwoPhaseDispatchesSingle(event) {
1227 if (event && event.dispatchConfig.phasedRegistrationNames) {
1228 traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
1229 }
1230}
1231
1232/**
1233 * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
1234 */
1235function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
1236 if (event && event.dispatchConfig.phasedRegistrationNames) {
1237 var targetInst = event._targetInst;
1238 var parentInst = targetInst ? getParentInstance(targetInst) : null;
1239 traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);
1240 }
1241}
1242
1243/**
1244 * Accumulates without regard to direction, does not look for phased
1245 * registration names. Same as `accumulateDirectDispatchesSingle` but without
1246 * requiring that the `dispatchMarker` be the same as the dispatched ID.
1247 */
1248function accumulateDispatches(inst, ignoredDirection, event) {
1249 if (inst && event && event.dispatchConfig.registrationName) {
1250 var registrationName = event.dispatchConfig.registrationName;
1251 var listener = getListener(inst, registrationName);
1252 if (listener) {
1253 event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
1254 event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
1255 }
1256 }
1257}
1258
1259/**
1260 * Accumulates dispatches on an `SyntheticEvent`, but only for the
1261 * `dispatchMarker`.
1262 * @param {SyntheticEvent} event
1263 */
1264function accumulateDirectDispatchesSingle(event) {
1265 if (event && event.dispatchConfig.registrationName) {
1266 accumulateDispatches(event._targetInst, null, event);
1267 }
1268}
1269
1270function accumulateTwoPhaseDispatches(events) {
1271 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
1272}
1273
1274function accumulateTwoPhaseDispatchesSkipTarget(events) {
1275 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
1276}
1277
1278function accumulateEnterLeaveDispatches(leave, enter, from, to) {
1279 traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
1280}
1281
1282function accumulateDirectDispatches(events) {
1283 forEachAccumulated(events, accumulateDirectDispatchesSingle);
1284}
1285
1286var EventPropagators = Object.freeze({
1287 accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
1288 accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
1289 accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches,
1290 accumulateDirectDispatches: accumulateDirectDispatches
1291});
1292
1293/**
1294 * Copyright (c) 2013-present, Facebook, Inc.
1295 *
1296 * This source code is licensed under the MIT license found in the
1297 * LICENSE file in the root directory of this source tree.
1298 *
1299 */
1300
1301
1302
1303var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
1304
1305/**
1306 * Simple, lightweight module assisting with the detection and context of
1307 * Worker. Helps avoid circular dependencies and allows code to reason about
1308 * whether or not they are in a Worker, even if they never include the main
1309 * `ReactWorker` dependency.
1310 */
1311var ExecutionEnvironment = {
1312
1313 canUseDOM: canUseDOM,
1314
1315 canUseWorkers: typeof Worker !== 'undefined',
1316
1317 canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),
1318
1319 canUseViewport: canUseDOM && !!window.screen,
1320
1321 isInWorker: !canUseDOM // For now, this is true - might change in the future.
1322
1323};
1324
1325var ExecutionEnvironment_1 = ExecutionEnvironment;
1326
1327var contentKey = null;
1328
1329/**
1330 * Gets the key used to access text content on a DOM node.
1331 *
1332 * @return {?string} Key used to access text content.
1333 * @internal
1334 */
1335function getTextContentAccessor() {
1336 if (!contentKey && ExecutionEnvironment_1.canUseDOM) {
1337 // Prefer textContent to innerText because many browsers support both but
1338 // SVG <text> elements don't support innerText even when <div> does.
1339 contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';
1340 }
1341 return contentKey;
1342}
1343
1344/**
1345 * This helper object stores information about text content of a target node,
1346 * allowing comparison of content before and after a given event.
1347 *
1348 * Identify the node where selection currently begins, then observe
1349 * both its text content and its current position in the DOM. Since the
1350 * browser may natively replace the target node during composition, we can
1351 * use its position to find its replacement.
1352 *
1353 *
1354 */
1355var compositionState = {
1356 _root: null,
1357 _startText: null,
1358 _fallbackText: null
1359};
1360
1361function initialize(nativeEventTarget) {
1362 compositionState._root = nativeEventTarget;
1363 compositionState._startText = getText();
1364 return true;
1365}
1366
1367function reset() {
1368 compositionState._root = null;
1369 compositionState._startText = null;
1370 compositionState._fallbackText = null;
1371}
1372
1373function getData() {
1374 if (compositionState._fallbackText) {
1375 return compositionState._fallbackText;
1376 }
1377
1378 var start = void 0;
1379 var startValue = compositionState._startText;
1380 var startLength = startValue.length;
1381 var end = void 0;
1382 var endValue = getText();
1383 var endLength = endValue.length;
1384
1385 for (start = 0; start < startLength; start++) {
1386 if (startValue[start] !== endValue[start]) {
1387 break;
1388 }
1389 }
1390
1391 var minEnd = startLength - start;
1392 for (end = 1; end <= minEnd; end++) {
1393 if (startValue[startLength - end] !== endValue[endLength - end]) {
1394 break;
1395 }
1396 }
1397
1398 var sliceTail = end > 1 ? 1 - end : undefined;
1399 compositionState._fallbackText = endValue.slice(start, sliceTail);
1400 return compositionState._fallbackText;
1401}
1402
1403function getText() {
1404 if ('value' in compositionState._root) {
1405 return compositionState._root.value;
1406 }
1407 return compositionState._root[getTextContentAccessor()];
1408}
1409
1410var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
1411
1412var _assign = ReactInternals.assign;
1413
1414/* eslint valid-typeof: 0 */
1415
1416var didWarnForAddedNewProperty = false;
1417var isProxySupported = typeof Proxy === 'function';
1418var EVENT_POOL_SIZE = 10;
1419
1420var shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];
1421
1422/**
1423 * @interface Event
1424 * @see http://www.w3.org/TR/DOM-Level-3-Events/
1425 */
1426var EventInterface = {
1427 type: null,
1428 target: null,
1429 // currentTarget is set when dispatching; no use in copying it here
1430 currentTarget: emptyFunction_1.thatReturnsNull,
1431 eventPhase: null,
1432 bubbles: null,
1433 cancelable: null,
1434 timeStamp: function (event) {
1435 return event.timeStamp || Date.now();
1436 },
1437 defaultPrevented: null,
1438 isTrusted: null
1439};
1440
1441/**
1442 * Synthetic events are dispatched by event plugins, typically in response to a
1443 * top-level event delegation handler.
1444 *
1445 * These systems should generally use pooling to reduce the frequency of garbage
1446 * collection. The system should check `isPersistent` to determine whether the
1447 * event should be released into the pool after being dispatched. Users that
1448 * need a persisted event should invoke `persist`.
1449 *
1450 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by
1451 * normalizing browser quirks. Subclasses do not necessarily have to implement a
1452 * DOM interface; custom application-specific events can also subclass this.
1453 *
1454 * @param {object} dispatchConfig Configuration used to dispatch this event.
1455 * @param {*} targetInst Marker identifying the event target.
1456 * @param {object} nativeEvent Native browser event.
1457 * @param {DOMEventTarget} nativeEventTarget Target node.
1458 */
1459function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
1460 {
1461 // these have a getter/setter for warnings
1462 delete this.nativeEvent;
1463 delete this.preventDefault;
1464 delete this.stopPropagation;
1465 }
1466
1467 this.dispatchConfig = dispatchConfig;
1468 this._targetInst = targetInst;
1469 this.nativeEvent = nativeEvent;
1470
1471 var Interface = this.constructor.Interface;
1472 for (var propName in Interface) {
1473 if (!Interface.hasOwnProperty(propName)) {
1474 continue;
1475 }
1476 {
1477 delete this[propName]; // this has a getter/setter for warnings
1478 }
1479 var normalize = Interface[propName];
1480 if (normalize) {
1481 this[propName] = normalize(nativeEvent);
1482 } else {
1483 if (propName === 'target') {
1484 this.target = nativeEventTarget;
1485 } else {
1486 this[propName] = nativeEvent[propName];
1487 }
1488 }
1489 }
1490
1491 var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;
1492 if (defaultPrevented) {
1493 this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue;
1494 } else {
1495 this.isDefaultPrevented = emptyFunction_1.thatReturnsFalse;
1496 }
1497 this.isPropagationStopped = emptyFunction_1.thatReturnsFalse;
1498 return this;
1499}
1500
1501_assign(SyntheticEvent.prototype, {
1502 preventDefault: function () {
1503 this.defaultPrevented = true;
1504 var event = this.nativeEvent;
1505 if (!event) {
1506 return;
1507 }
1508
1509 if (event.preventDefault) {
1510 event.preventDefault();
1511 } else if (typeof event.returnValue !== 'unknown') {
1512 event.returnValue = false;
1513 }
1514 this.isDefaultPrevented = emptyFunction_1.thatReturnsTrue;
1515 },
1516
1517 stopPropagation: function () {
1518 var event = this.nativeEvent;
1519 if (!event) {
1520 return;
1521 }
1522
1523 if (event.stopPropagation) {
1524 event.stopPropagation();
1525 } else if (typeof event.cancelBubble !== 'unknown') {
1526 // The ChangeEventPlugin registers a "propertychange" event for
1527 // IE. This event does not support bubbling or cancelling, and
1528 // any references to cancelBubble throw "Member not found". A
1529 // typeof check of "unknown" circumvents this issue (and is also
1530 // IE specific).
1531 event.cancelBubble = true;
1532 }
1533
1534 this.isPropagationStopped = emptyFunction_1.thatReturnsTrue;
1535 },
1536
1537 /**
1538 * We release all dispatched `SyntheticEvent`s after each event loop, adding
1539 * them back into the pool. This allows a way to hold onto a reference that
1540 * won't be added back into the pool.
1541 */
1542 persist: function () {
1543 this.isPersistent = emptyFunction_1.thatReturnsTrue;
1544 },
1545
1546 /**
1547 * Checks if this event should be released back into the pool.
1548 *
1549 * @return {boolean} True if this should not be released, false otherwise.
1550 */
1551 isPersistent: emptyFunction_1.thatReturnsFalse,
1552
1553 /**
1554 * `PooledClass` looks for `destructor` on each instance it releases.
1555 */
1556 destructor: function () {
1557 var Interface = this.constructor.Interface;
1558 for (var propName in Interface) {
1559 {
1560 Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));
1561 }
1562 }
1563 for (var i = 0; i < shouldBeReleasedProperties.length; i++) {
1564 this[shouldBeReleasedProperties[i]] = null;
1565 }
1566 {
1567 Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));
1568 Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', emptyFunction_1));
1569 Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction_1));
1570 }
1571 }
1572});
1573
1574SyntheticEvent.Interface = EventInterface;
1575
1576/**
1577 * Helper to reduce boilerplate when creating subclasses.
1578 */
1579SyntheticEvent.extend = function (Interface) {
1580 var Super = this;
1581
1582 var E = function () {};
1583 E.prototype = Super.prototype;
1584 var prototype = new E();
1585
1586 function Class() {
1587 return Super.apply(this, arguments);
1588 }
1589 _assign(prototype, Class.prototype);
1590 Class.prototype = prototype;
1591 Class.prototype.constructor = Class;
1592
1593 Class.Interface = _assign({}, Super.Interface, Interface);
1594 Class.extend = Super.extend;
1595 addEventPoolingTo(Class);
1596
1597 return Class;
1598};
1599
1600/** Proxying after everything set on SyntheticEvent
1601 * to resolve Proxy issue on some WebKit browsers
1602 * in which some Event properties are set to undefined (GH#10010)
1603 */
1604{
1605 if (isProxySupported) {
1606 /*eslint-disable no-func-assign */
1607 SyntheticEvent = new Proxy(SyntheticEvent, {
1608 construct: function (target, args) {
1609 return this.apply(target, Object.create(target.prototype), args);
1610 },
1611 apply: function (constructor, that, args) {
1612 return new Proxy(constructor.apply(that, args), {
1613 set: function (target, prop, value) {
1614 if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {
1615 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.');
1616 didWarnForAddedNewProperty = true;
1617 }
1618 target[prop] = value;
1619 return true;
1620 }
1621 });
1622 }
1623 });
1624 /*eslint-enable no-func-assign */
1625 }
1626}
1627
1628addEventPoolingTo(SyntheticEvent);
1629
1630/**
1631 * Helper to nullify syntheticEvent instance properties when destructing
1632 *
1633 * @param {String} propName
1634 * @param {?object} getVal
1635 * @return {object} defineProperty object
1636 */
1637function getPooledWarningPropertyDefinition(propName, getVal) {
1638 var isFunction = typeof getVal === 'function';
1639 return {
1640 configurable: true,
1641 set: set,
1642 get: get
1643 };
1644
1645 function set(val) {
1646 var action = isFunction ? 'setting the method' : 'setting the property';
1647 warn(action, 'This is effectively a no-op');
1648 return val;
1649 }
1650
1651 function get() {
1652 var action = isFunction ? 'accessing the method' : 'accessing the property';
1653 var result = isFunction ? 'This is a no-op function' : 'This is set to null';
1654 warn(action, result);
1655 return getVal;
1656 }
1657
1658 function warn(action, result) {
1659 var warningCondition = false;
1660 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);
1661 }
1662}
1663
1664function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {
1665 var EventConstructor = this;
1666 if (EventConstructor.eventPool.length) {
1667 var instance = EventConstructor.eventPool.pop();
1668 EventConstructor.call(instance, dispatchConfig, targetInst, nativeEvent, nativeInst);
1669 return instance;
1670 }
1671 return new EventConstructor(dispatchConfig, targetInst, nativeEvent, nativeInst);
1672}
1673
1674function releasePooledEvent(event) {
1675 var EventConstructor = this;
1676 !(event instanceof EventConstructor) ? invariant_1(false, 'Trying to release an event instance into a pool of a different type.') : void 0;
1677 event.destructor();
1678 if (EventConstructor.eventPool.length < EVENT_POOL_SIZE) {
1679 EventConstructor.eventPool.push(event);
1680 }
1681}
1682
1683function addEventPoolingTo(EventConstructor) {
1684 EventConstructor.eventPool = [];
1685 EventConstructor.getPooled = getPooledEvent;
1686 EventConstructor.release = releasePooledEvent;
1687}
1688
1689var SyntheticEvent$1 = SyntheticEvent;
1690
1691/**
1692 * @interface Event
1693 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents
1694 */
1695var SyntheticCompositionEvent = SyntheticEvent$1.extend({
1696 data: null
1697});
1698
1699/**
1700 * @interface Event
1701 * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105
1702 * /#events-inputevents
1703 */
1704var SyntheticInputEvent = SyntheticEvent$1.extend({
1705 data: null
1706});
1707
1708var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
1709var START_KEYCODE = 229;
1710
1711var canUseCompositionEvent = ExecutionEnvironment_1.canUseDOM && 'CompositionEvent' in window;
1712
1713var documentMode = null;
1714if (ExecutionEnvironment_1.canUseDOM && 'documentMode' in document) {
1715 documentMode = document.documentMode;
1716}
1717
1718// Webkit offers a very useful `textInput` event that can be used to
1719// directly represent `beforeInput`. The IE `textinput` event is not as
1720// useful, so we don't use it.
1721var canUseTextInputEvent = ExecutionEnvironment_1.canUseDOM && 'TextEvent' in window && !documentMode;
1722
1723// In IE9+, we have access to composition events, but the data supplied
1724// by the native compositionend event may be incorrect. Japanese ideographic
1725// spaces, for instance (\u3000) are not recorded correctly.
1726var useFallbackCompositionData = ExecutionEnvironment_1.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);
1727
1728var SPACEBAR_CODE = 32;
1729var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
1730
1731// Events and their corresponding property names.
1732var eventTypes = {
1733 beforeInput: {
1734 phasedRegistrationNames: {
1735 bubbled: 'onBeforeInput',
1736 captured: 'onBeforeInputCapture'
1737 },
1738 dependencies: ['topCompositionEnd', 'topKeyPress', 'topTextInput', 'topPaste']
1739 },
1740 compositionEnd: {
1741 phasedRegistrationNames: {
1742 bubbled: 'onCompositionEnd',
1743 captured: 'onCompositionEndCapture'
1744 },
1745 dependencies: ['topBlur', 'topCompositionEnd', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
1746 },
1747 compositionStart: {
1748 phasedRegistrationNames: {
1749 bubbled: 'onCompositionStart',
1750 captured: 'onCompositionStartCapture'
1751 },
1752 dependencies: ['topBlur', 'topCompositionStart', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
1753 },
1754 compositionUpdate: {
1755 phasedRegistrationNames: {
1756 bubbled: 'onCompositionUpdate',
1757 captured: 'onCompositionUpdateCapture'
1758 },
1759 dependencies: ['topBlur', 'topCompositionUpdate', 'topKeyDown', 'topKeyPress', 'topKeyUp', 'topMouseDown']
1760 }
1761};
1762
1763// Track whether we've ever handled a keypress on the space key.
1764var hasSpaceKeypress = false;
1765
1766/**
1767 * Return whether a native keypress event is assumed to be a command.
1768 * This is required because Firefox fires `keypress` events for key commands
1769 * (cut, copy, select-all, etc.) even though no character is inserted.
1770 */
1771function isKeypressCommand(nativeEvent) {
1772 return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
1773 // ctrlKey && altKey is equivalent to AltGr, and is not a command.
1774 !(nativeEvent.ctrlKey && nativeEvent.altKey);
1775}
1776
1777/**
1778 * Translate native top level events into event types.
1779 *
1780 * @param {string} topLevelType
1781 * @return {object}
1782 */
1783function getCompositionEventType(topLevelType) {
1784 switch (topLevelType) {
1785 case 'topCompositionStart':
1786 return eventTypes.compositionStart;
1787 case 'topCompositionEnd':
1788 return eventTypes.compositionEnd;
1789 case 'topCompositionUpdate':
1790 return eventTypes.compositionUpdate;
1791 }
1792}
1793
1794/**
1795 * Does our fallback best-guess model think this event signifies that
1796 * composition has begun?
1797 *
1798 * @param {string} topLevelType
1799 * @param {object} nativeEvent
1800 * @return {boolean}
1801 */
1802function isFallbackCompositionStart(topLevelType, nativeEvent) {
1803 return topLevelType === 'topKeyDown' && nativeEvent.keyCode === START_KEYCODE;
1804}
1805
1806/**
1807 * Does our fallback mode think that this event is the end of composition?
1808 *
1809 * @param {string} topLevelType
1810 * @param {object} nativeEvent
1811 * @return {boolean}
1812 */
1813function isFallbackCompositionEnd(topLevelType, nativeEvent) {
1814 switch (topLevelType) {
1815 case 'topKeyUp':
1816 // Command keys insert or clear IME input.
1817 return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
1818 case 'topKeyDown':
1819 // Expect IME keyCode on each keydown. If we get any other
1820 // code we must have exited earlier.
1821 return nativeEvent.keyCode !== START_KEYCODE;
1822 case 'topKeyPress':
1823 case 'topMouseDown':
1824 case 'topBlur':
1825 // Events are not possible without cancelling IME.
1826 return true;
1827 default:
1828 return false;
1829 }
1830}
1831
1832/**
1833 * Google Input Tools provides composition data via a CustomEvent,
1834 * with the `data` property populated in the `detail` object. If this
1835 * is available on the event object, use it. If not, this is a plain
1836 * composition event and we have nothing special to extract.
1837 *
1838 * @param {object} nativeEvent
1839 * @return {?string}
1840 */
1841function getDataFromCustomEvent(nativeEvent) {
1842 var detail = nativeEvent.detail;
1843 if (typeof detail === 'object' && 'data' in detail) {
1844 return detail.data;
1845 }
1846 return null;
1847}
1848
1849// Track the current IME composition status, if any.
1850var isComposing = false;
1851
1852/**
1853 * @return {?object} A SyntheticCompositionEvent.
1854 */
1855function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
1856 var eventType = void 0;
1857 var fallbackData = void 0;
1858
1859 if (canUseCompositionEvent) {
1860 eventType = getCompositionEventType(topLevelType);
1861 } else if (!isComposing) {
1862 if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
1863 eventType = eventTypes.compositionStart;
1864 }
1865 } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
1866 eventType = eventTypes.compositionEnd;
1867 }
1868
1869 if (!eventType) {
1870 return null;
1871 }
1872
1873 if (useFallbackCompositionData) {
1874 // The current composition is stored statically and must not be
1875 // overwritten while composition continues.
1876 if (!isComposing && eventType === eventTypes.compositionStart) {
1877 isComposing = initialize(nativeEventTarget);
1878 } else if (eventType === eventTypes.compositionEnd) {
1879 if (isComposing) {
1880 fallbackData = getData();
1881 }
1882 }
1883 }
1884
1885 var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);
1886
1887 if (fallbackData) {
1888 // Inject data generated from fallback path into the synthetic event.
1889 // This matches the property of native CompositionEventInterface.
1890 event.data = fallbackData;
1891 } else {
1892 var customData = getDataFromCustomEvent(nativeEvent);
1893 if (customData !== null) {
1894 event.data = customData;
1895 }
1896 }
1897
1898 accumulateTwoPhaseDispatches(event);
1899 return event;
1900}
1901
1902/**
1903 * @param {TopLevelTypes} topLevelType Record from `BrowserEventConstants`.
1904 * @param {object} nativeEvent Native browser event.
1905 * @return {?string} The string corresponding to this `beforeInput` event.
1906 */
1907function getNativeBeforeInputChars(topLevelType, nativeEvent) {
1908 switch (topLevelType) {
1909 case 'topCompositionEnd':
1910 return getDataFromCustomEvent(nativeEvent);
1911 case 'topKeyPress':
1912 /**
1913 * If native `textInput` events are available, our goal is to make
1914 * use of them. However, there is a special case: the spacebar key.
1915 * In Webkit, preventing default on a spacebar `textInput` event
1916 * cancels character insertion, but it *also* causes the browser
1917 * to fall back to its default spacebar behavior of scrolling the
1918 * page.
1919 *
1920 * Tracking at:
1921 * https://code.google.com/p/chromium/issues/detail?id=355103
1922 *
1923 * To avoid this issue, use the keypress event as if no `textInput`
1924 * event is available.
1925 */
1926 var which = nativeEvent.which;
1927 if (which !== SPACEBAR_CODE) {
1928 return null;
1929 }
1930
1931 hasSpaceKeypress = true;
1932 return SPACEBAR_CHAR;
1933
1934 case 'topTextInput':
1935 // Record the characters to be added to the DOM.
1936 var chars = nativeEvent.data;
1937
1938 // If it's a spacebar character, assume that we have already handled
1939 // it at the keypress level and bail immediately. Android Chrome
1940 // doesn't give us keycodes, so we need to blacklist it.
1941 if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
1942 return null;
1943 }
1944
1945 return chars;
1946
1947 default:
1948 // For other native event types, do nothing.
1949 return null;
1950 }
1951}
1952
1953/**
1954 * For browsers that do not provide the `textInput` event, extract the
1955 * appropriate string to use for SyntheticInputEvent.
1956 *
1957 * @param {string} topLevelType Record from `BrowserEventConstants`.
1958 * @param {object} nativeEvent Native browser event.
1959 * @return {?string} The fallback string for this `beforeInput` event.
1960 */
1961function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
1962 // If we are currently composing (IME) and using a fallback to do so,
1963 // try to extract the composed characters from the fallback object.
1964 // If composition event is available, we extract a string only at
1965 // compositionevent, otherwise extract it at fallback events.
1966 if (isComposing) {
1967 if (topLevelType === 'topCompositionEnd' || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) {
1968 var chars = getData();
1969 reset();
1970 isComposing = false;
1971 return chars;
1972 }
1973 return null;
1974 }
1975
1976 switch (topLevelType) {
1977 case 'topPaste':
1978 // If a paste event occurs after a keypress, throw out the input
1979 // chars. Paste events should not lead to BeforeInput events.
1980 return null;
1981 case 'topKeyPress':
1982 /**
1983 * As of v27, Firefox may fire keypress events even when no character
1984 * will be inserted. A few possibilities:
1985 *
1986 * - `which` is `0`. Arrow keys, Esc key, etc.
1987 *
1988 * - `which` is the pressed key code, but no char is available.
1989 * Ex: 'AltGr + d` in Polish. There is no modified character for
1990 * this key combination and no character is inserted into the
1991 * document, but FF fires the keypress for char code `100` anyway.
1992 * No `input` event will occur.
1993 *
1994 * - `which` is the pressed key code, but a command combination is
1995 * being used. Ex: `Cmd+C`. No character is inserted, and no
1996 * `input` event will occur.
1997 */
1998 if (!isKeypressCommand(nativeEvent)) {
1999 // IE fires the `keypress` event when a user types an emoji via
2000 // Touch keyboard of Windows. In such a case, the `char` property
2001 // holds an emoji character like `\uD83D\uDE0A`. Because its length
2002 // is 2, the property `which` does not represent an emoji correctly.
2003 // In such a case, we directly return the `char` property instead of
2004 // using `which`.
2005 if (nativeEvent.char && nativeEvent.char.length > 1) {
2006 return nativeEvent.char;
2007 } else if (nativeEvent.which) {
2008 return String.fromCharCode(nativeEvent.which);
2009 }
2010 }
2011 return null;
2012 case 'topCompositionEnd':
2013 return useFallbackCompositionData ? null : nativeEvent.data;
2014 default:
2015 return null;
2016 }
2017}
2018
2019/**
2020 * Extract a SyntheticInputEvent for `beforeInput`, based on either native
2021 * `textInput` or fallback behavior.
2022 *
2023 * @return {?object} A SyntheticInputEvent.
2024 */
2025function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
2026 var chars = void 0;
2027
2028 if (canUseTextInputEvent) {
2029 chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
2030 } else {
2031 chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
2032 }
2033
2034 // If no characters are being inserted, no BeforeInput event should
2035 // be fired.
2036 if (!chars) {
2037 return null;
2038 }
2039
2040 var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);
2041
2042 event.data = chars;
2043 accumulateTwoPhaseDispatches(event);
2044 return event;
2045}
2046
2047/**
2048 * Create an `onBeforeInput` event to match
2049 * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
2050 *
2051 * This event plugin is based on the native `textInput` event
2052 * available in Chrome, Safari, Opera, and IE. This event fires after
2053 * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
2054 *
2055 * `beforeInput` is spec'd but not implemented in any browsers, and
2056 * the `input` event does not provide any useful information about what has
2057 * actually been added, contrary to the spec. Thus, `textInput` is the best
2058 * available event to identify the characters that have actually been inserted
2059 * into the target node.
2060 *
2061 * This plugin is also responsible for emitting `composition` events, thus
2062 * allowing us to share composition fallback code for both `beforeInput` and
2063 * `composition` event types.
2064 */
2065var BeforeInputEventPlugin = {
2066 eventTypes: eventTypes,
2067
2068 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
2069 var composition = extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget);
2070
2071 var beforeInput = extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget);
2072
2073 if (composition === null) {
2074 return beforeInput;
2075 }
2076
2077 if (beforeInput === null) {
2078 return composition;
2079 }
2080
2081 return [composition, beforeInput];
2082 }
2083};
2084
2085// Use to restore controlled state after a change event has fired.
2086
2087var fiberHostComponent = null;
2088
2089var ReactControlledComponentInjection = {
2090 injectFiberControlledHostComponent: function (hostComponentImpl) {
2091 // The fiber implementation doesn't use dynamic dispatch so we need to
2092 // inject the implementation.
2093 fiberHostComponent = hostComponentImpl;
2094 }
2095};
2096
2097var restoreTarget = null;
2098var restoreQueue = null;
2099
2100function restoreStateOfTarget(target) {
2101 // We perform this translation at the end of the event loop so that we
2102 // always receive the correct fiber here
2103 var internalInstance = getInstanceFromNode(target);
2104 if (!internalInstance) {
2105 // Unmounted
2106 return;
2107 }
2108 !(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;
2109 var props = getFiberCurrentPropsFromNode(internalInstance.stateNode);
2110 fiberHostComponent.restoreControlledState(internalInstance.stateNode, internalInstance.type, props);
2111}
2112
2113var injection$2 = ReactControlledComponentInjection;
2114
2115function enqueueStateRestore(target) {
2116 if (restoreTarget) {
2117 if (restoreQueue) {
2118 restoreQueue.push(target);
2119 } else {
2120 restoreQueue = [target];
2121 }
2122 } else {
2123 restoreTarget = target;
2124 }
2125}
2126
2127function restoreStateIfNeeded() {
2128 if (!restoreTarget) {
2129 return;
2130 }
2131 var target = restoreTarget;
2132 var queuedTargets = restoreQueue;
2133 restoreTarget = null;
2134 restoreQueue = null;
2135
2136 restoreStateOfTarget(target);
2137 if (queuedTargets) {
2138 for (var i = 0; i < queuedTargets.length; i++) {
2139 restoreStateOfTarget(queuedTargets[i]);
2140 }
2141 }
2142}
2143
2144var ReactControlledComponent = Object.freeze({
2145 injection: injection$2,
2146 enqueueStateRestore: enqueueStateRestore,
2147 restoreStateIfNeeded: restoreStateIfNeeded
2148});
2149
2150// Used as a way to call batchedUpdates when we don't have a reference to
2151// the renderer. Such as when we're dispatching events or if third party
2152// libraries need to call batchedUpdates. Eventually, this API will go away when
2153// everything is batched by default. We'll then have a similar API to opt-out of
2154// scheduled work and instead do synchronous work.
2155
2156// Defaults
2157var fiberBatchedUpdates = function (fn, bookkeeping) {
2158 return fn(bookkeeping);
2159};
2160
2161var isNestingBatched = false;
2162function batchedUpdates(fn, bookkeeping) {
2163 if (isNestingBatched) {
2164 // If we are currently inside another batch, we need to wait until it
2165 // fully completes before restoring state. Therefore, we add the target to
2166 // a queue of work.
2167 return fiberBatchedUpdates(fn, bookkeeping);
2168 }
2169 isNestingBatched = true;
2170 try {
2171 return fiberBatchedUpdates(fn, bookkeeping);
2172 } finally {
2173 // Here we wait until all updates have propagated, which is important
2174 // when using controlled components within layers:
2175 // https://github.com/facebook/react/issues/1698
2176 // Then we restore state of any controlled component.
2177 isNestingBatched = false;
2178 restoreStateIfNeeded();
2179 }
2180}
2181
2182var ReactGenericBatchingInjection = {
2183 injectFiberBatchedUpdates: function (_batchedUpdates) {
2184 fiberBatchedUpdates = _batchedUpdates;
2185 }
2186};
2187
2188var injection$3 = ReactGenericBatchingInjection;
2189
2190/**
2191 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
2192 */
2193var supportedInputTypes = {
2194 color: true,
2195 date: true,
2196 datetime: true,
2197 'datetime-local': true,
2198 email: true,
2199 month: true,
2200 number: true,
2201 password: true,
2202 range: true,
2203 search: true,
2204 tel: true,
2205 text: true,
2206 time: true,
2207 url: true,
2208 week: true
2209};
2210
2211function isTextInputElement(elem) {
2212 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
2213
2214 if (nodeName === 'input') {
2215 return !!supportedInputTypes[elem.type];
2216 }
2217
2218 if (nodeName === 'textarea') {
2219 return true;
2220 }
2221
2222 return false;
2223}
2224
2225/**
2226 * HTML nodeType values that represent the type of the node
2227 */
2228
2229var ELEMENT_NODE = 1;
2230var TEXT_NODE = 3;
2231var COMMENT_NODE = 8;
2232var DOCUMENT_NODE = 9;
2233var DOCUMENT_FRAGMENT_NODE = 11;
2234
2235/**
2236 * Gets the target node from a native browser event by accounting for
2237 * inconsistencies in browser DOM APIs.
2238 *
2239 * @param {object} nativeEvent Native browser event.
2240 * @return {DOMEventTarget} Target node.
2241 */
2242function getEventTarget(nativeEvent) {
2243 var target = nativeEvent.target || window;
2244
2245 // Normalize SVG <use> element events #4963
2246 if (target.correspondingUseElement) {
2247 target = target.correspondingUseElement;
2248 }
2249
2250 // Safari may fire events on text nodes (Node.TEXT_NODE is 3).
2251 // @see http://www.quirksmode.org/js/events_properties.html
2252 return target.nodeType === TEXT_NODE ? target.parentNode : target;
2253}
2254
2255/**
2256 * Checks if an event is supported in the current execution environment.
2257 *
2258 * NOTE: This will not work correctly for non-generic events such as `change`,
2259 * `reset`, `load`, `error`, and `select`.
2260 *
2261 * Borrows from Modernizr.
2262 *
2263 * @param {string} eventNameSuffix Event name, e.g. "click".
2264 * @param {?boolean} capture Check if the capture phase is supported.
2265 * @return {boolean} True if the event is supported.
2266 * @internal
2267 * @license Modernizr 3.0.0pre (Custom Build) | MIT
2268 */
2269function isEventSupported(eventNameSuffix, capture) {
2270 if (!ExecutionEnvironment_1.canUseDOM || capture && !('addEventListener' in document)) {
2271 return false;
2272 }
2273
2274 var eventName = 'on' + eventNameSuffix;
2275 var isSupported = eventName in document;
2276
2277 if (!isSupported) {
2278 var element = document.createElement('div');
2279 element.setAttribute(eventName, 'return;');
2280 isSupported = typeof element[eventName] === 'function';
2281 }
2282
2283 return isSupported;
2284}
2285
2286function isCheckable(elem) {
2287 var type = elem.type;
2288 var nodeName = elem.nodeName;
2289 return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
2290}
2291
2292function getTracker(node) {
2293 return node._valueTracker;
2294}
2295
2296function detachTracker(node) {
2297 node._valueTracker = null;
2298}
2299
2300function getValueFromNode(node) {
2301 var value = '';
2302 if (!node) {
2303 return value;
2304 }
2305
2306 if (isCheckable(node)) {
2307 value = node.checked ? 'true' : 'false';
2308 } else {
2309 value = node.value;
2310 }
2311
2312 return value;
2313}
2314
2315function trackValueOnNode(node) {
2316 var valueField = isCheckable(node) ? 'checked' : 'value';
2317 var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);
2318
2319 var currentValue = '' + node[valueField];
2320
2321 // if someone has already defined a value or Safari, then bail
2322 // and don't track value will cause over reporting of changes,
2323 // but it's better then a hard failure
2324 // (needed for certain tests that spyOn input values and Safari)
2325 if (node.hasOwnProperty(valueField) || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
2326 return;
2327 }
2328
2329 Object.defineProperty(node, valueField, {
2330 configurable: true,
2331 get: function () {
2332 return descriptor.get.call(this);
2333 },
2334 set: function (value) {
2335 currentValue = '' + value;
2336 descriptor.set.call(this, value);
2337 }
2338 });
2339 // We could've passed this the first time
2340 // but it triggers a bug in IE11 and Edge 14/15.
2341 // Calling defineProperty() again should be equivalent.
2342 // https://github.com/facebook/react/issues/11768
2343 Object.defineProperty(node, valueField, {
2344 enumerable: descriptor.enumerable
2345 });
2346
2347 var tracker = {
2348 getValue: function () {
2349 return currentValue;
2350 },
2351 setValue: function (value) {
2352 currentValue = '' + value;
2353 },
2354 stopTracking: function () {
2355 detachTracker(node);
2356 delete node[valueField];
2357 }
2358 };
2359 return tracker;
2360}
2361
2362function track(node) {
2363 if (getTracker(node)) {
2364 return;
2365 }
2366
2367 // TODO: Once it's just Fiber we can move this to node._wrapperState
2368 node._valueTracker = trackValueOnNode(node);
2369}
2370
2371function updateValueIfChanged(node) {
2372 if (!node) {
2373 return false;
2374 }
2375
2376 var tracker = getTracker(node);
2377 // if there is no tracker at this point it's unlikely
2378 // that trying again will succeed
2379 if (!tracker) {
2380 return true;
2381 }
2382
2383 var lastValue = tracker.getValue();
2384 var nextValue = getValueFromNode(node);
2385 if (nextValue !== lastValue) {
2386 tracker.setValue(nextValue);
2387 return true;
2388 }
2389 return false;
2390}
2391
2392var ReactInternals$1 = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
2393
2394var ReactCurrentOwner = ReactInternals$1.ReactCurrentOwner;
2395var ReactDebugCurrentFrame = ReactInternals$1.ReactDebugCurrentFrame;
2396
2397var describeComponentFrame = function (name, source, ownerName) {
2398 return '\n in ' + (name || 'Unknown') + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
2399};
2400
2401// The Symbol used to tag the ReactElement-like types. If there is no native Symbol
2402// nor polyfill, then a plain number is used for performance.
2403var hasSymbol = typeof Symbol === 'function' && Symbol['for'];
2404
2405var REACT_ELEMENT_TYPE = hasSymbol ? Symbol['for']('react.element') : 0xeac7;
2406var REACT_CALL_TYPE = hasSymbol ? Symbol['for']('react.call') : 0xeac8;
2407var REACT_RETURN_TYPE = hasSymbol ? Symbol['for']('react.return') : 0xeac9;
2408var REACT_PORTAL_TYPE = hasSymbol ? Symbol['for']('react.portal') : 0xeaca;
2409var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol['for']('react.fragment') : 0xeacb;
2410
2411var MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
2412var FAUX_ITERATOR_SYMBOL = '@@iterator';
2413
2414function getIteratorFn(maybeIterable) {
2415 if (maybeIterable === null || typeof maybeIterable === 'undefined') {
2416 return null;
2417 }
2418 var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];
2419 if (typeof maybeIterator === 'function') {
2420 return maybeIterator;
2421 }
2422 return null;
2423}
2424
2425function getComponentName(fiber) {
2426 var type = fiber.type;
2427
2428 if (typeof type === 'function') {
2429 return type.displayName || type.name;
2430 }
2431 if (typeof type === 'string') {
2432 return type;
2433 }
2434 switch (type) {
2435 case REACT_FRAGMENT_TYPE:
2436 return 'ReactFragment';
2437 case REACT_PORTAL_TYPE:
2438 return 'ReactPortal';
2439 case REACT_CALL_TYPE:
2440 return 'ReactCall';
2441 case REACT_RETURN_TYPE:
2442 return 'ReactReturn';
2443 }
2444 return null;
2445}
2446
2447function describeFiber(fiber) {
2448 switch (fiber.tag) {
2449 case IndeterminateComponent:
2450 case FunctionalComponent:
2451 case ClassComponent:
2452 case HostComponent:
2453 var owner = fiber._debugOwner;
2454 var source = fiber._debugSource;
2455 var name = getComponentName(fiber);
2456 var ownerName = null;
2457 if (owner) {
2458 ownerName = getComponentName(owner);
2459 }
2460 return describeComponentFrame(name, source, ownerName);
2461 default:
2462 return '';
2463 }
2464}
2465
2466// This function can only be called with a work-in-progress fiber and
2467// only during begin or complete phase. Do not call it under any other
2468// circumstances.
2469function getStackAddendumByWorkInProgressFiber(workInProgress) {
2470 var info = '';
2471 var node = workInProgress;
2472 do {
2473 info += describeFiber(node);
2474 // Otherwise this return pointer might point to the wrong tree:
2475 node = node['return'];
2476 } while (node);
2477 return info;
2478}
2479
2480function getCurrentFiberOwnerName$1() {
2481 {
2482 var fiber = ReactDebugCurrentFiber.current;
2483 if (fiber === null) {
2484 return null;
2485 }
2486 var owner = fiber._debugOwner;
2487 if (owner !== null && typeof owner !== 'undefined') {
2488 return getComponentName(owner);
2489 }
2490 }
2491 return null;
2492}
2493
2494function getCurrentFiberStackAddendum$1() {
2495 {
2496 var fiber = ReactDebugCurrentFiber.current;
2497 if (fiber === null) {
2498 return null;
2499 }
2500 // Safe because if current fiber exists, we are reconciling,
2501 // and it is guaranteed to be the work-in-progress version.
2502 return getStackAddendumByWorkInProgressFiber(fiber);
2503 }
2504 return null;
2505}
2506
2507function resetCurrentFiber() {
2508 ReactDebugCurrentFrame.getCurrentStack = null;
2509 ReactDebugCurrentFiber.current = null;
2510 ReactDebugCurrentFiber.phase = null;
2511}
2512
2513function setCurrentFiber(fiber) {
2514 ReactDebugCurrentFrame.getCurrentStack = getCurrentFiberStackAddendum$1;
2515 ReactDebugCurrentFiber.current = fiber;
2516 ReactDebugCurrentFiber.phase = null;
2517}
2518
2519function setCurrentPhase(phase) {
2520 ReactDebugCurrentFiber.phase = phase;
2521}
2522
2523var ReactDebugCurrentFiber = {
2524 current: null,
2525 phase: null,
2526 resetCurrentFiber: resetCurrentFiber,
2527 setCurrentFiber: setCurrentFiber,
2528 setCurrentPhase: setCurrentPhase,
2529 getCurrentFiberOwnerName: getCurrentFiberOwnerName$1,
2530 getCurrentFiberStackAddendum: getCurrentFiberStackAddendum$1
2531};
2532
2533// A reserved attribute.
2534// It is handled by React separately and shouldn't be written to the DOM.
2535var RESERVED = 0;
2536
2537// A simple string attribute.
2538// Attributes that aren't in the whitelist are presumed to have this type.
2539var STRING = 1;
2540
2541// A string attribute that accepts booleans in React. In HTML, these are called
2542// "enumerated" attributes with "true" and "false" as possible values.
2543// When true, it should be set to a "true" string.
2544// When false, it should be set to a "false" string.
2545var BOOLEANISH_STRING = 2;
2546
2547// A real boolean attribute.
2548// When true, it should be present (set either to an empty string or its name).
2549// When false, it should be omitted.
2550var BOOLEAN = 3;
2551
2552// An attribute that can be used as a flag as well as with a value.
2553// When true, it should be present (set either to an empty string or its name).
2554// When false, it should be omitted.
2555// For any other value, should be present with that value.
2556var OVERLOADED_BOOLEAN = 4;
2557
2558// An attribute that must be numeric or parse as a numeric.
2559// When falsy, it should be removed.
2560var NUMERIC = 5;
2561
2562// An attribute that must be positive numeric or parse as a positive numeric.
2563// When falsy, it should be removed.
2564var POSITIVE_NUMERIC = 6;
2565
2566/* eslint-disable max-len */
2567var 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';
2568/* eslint-enable max-len */
2569var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
2570
2571
2572var ROOT_ATTRIBUTE_NAME = 'data-reactroot';
2573var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$');
2574
2575var illegalAttributeNameCache = {};
2576var validatedAttributeNameCache = {};
2577
2578function isAttributeNameSafe(attributeName) {
2579 if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
2580 return true;
2581 }
2582 if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
2583 return false;
2584 }
2585 if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
2586 validatedAttributeNameCache[attributeName] = true;
2587 return true;
2588 }
2589 illegalAttributeNameCache[attributeName] = true;
2590 {
2591 warning_1(false, 'Invalid attribute name: `%s`', attributeName);
2592 }
2593 return false;
2594}
2595
2596function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) {
2597 if (propertyInfo !== null) {
2598 return propertyInfo.type === RESERVED;
2599 }
2600 if (isCustomComponentTag) {
2601 return false;
2602 }
2603 if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) {
2604 return true;
2605 }
2606 return false;
2607}
2608
2609function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) {
2610 if (propertyInfo !== null && propertyInfo.type === RESERVED) {
2611 return false;
2612 }
2613 switch (typeof value) {
2614 case 'function':
2615 // $FlowIssue symbol is perfectly valid here
2616 case 'symbol':
2617 // eslint-disable-line
2618 return true;
2619 case 'boolean':
2620 {
2621 if (isCustomComponentTag) {
2622 return false;
2623 }
2624 if (propertyInfo !== null) {
2625 return !propertyInfo.acceptsBooleans;
2626 } else {
2627 var prefix = name.toLowerCase().slice(0, 5);
2628 return prefix !== 'data-' && prefix !== 'aria-';
2629 }
2630 }
2631 default:
2632 return false;
2633 }
2634}
2635
2636function shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag) {
2637 if (value === null || typeof value === 'undefined') {
2638 return true;
2639 }
2640 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag)) {
2641 return true;
2642 }
2643 if (propertyInfo !== null) {
2644 switch (propertyInfo.type) {
2645 case BOOLEAN:
2646 return !value;
2647 case OVERLOADED_BOOLEAN:
2648 return value === false;
2649 case NUMERIC:
2650 return isNaN(value);
2651 case POSITIVE_NUMERIC:
2652 return isNaN(value) || value < 1;
2653 }
2654 }
2655 return false;
2656}
2657
2658function getPropertyInfo(name) {
2659 return properties.hasOwnProperty(name) ? properties[name] : null;
2660}
2661
2662function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace) {
2663 this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN;
2664 this.attributeName = attributeName;
2665 this.attributeNamespace = attributeNamespace;
2666 this.mustUseProperty = mustUseProperty;
2667 this.propertyName = name;
2668 this.type = type;
2669}
2670
2671// When adding attributes to this list, be sure to also add them to
2672// the `possibleStandardNames` module to ensure casing and incorrect
2673// name warnings.
2674var properties = {};
2675
2676// These props are reserved by React. They shouldn't be written to the DOM.
2677['children', 'dangerouslySetInnerHTML',
2678// TODO: This prevents the assignment of defaultValue to regular
2679// elements (not just inputs). Now that ReactDOMInput assigns to the
2680// defaultValue property -- do we need this?
2681'defaultValue', 'defaultChecked', 'innerHTML', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'style'].forEach(function (name) {
2682 properties[name] = new PropertyInfoRecord(name, RESERVED, false, // mustUseProperty
2683 name, // attributeName
2684 null);
2685});
2686
2687// A few React string attributes have a different name.
2688// This is a mapping from React prop names to the attribute names.
2689new Map([['acceptCharset', 'accept-charset'], ['className', 'class'], ['htmlFor', 'for'], ['httpEquiv', 'http-equiv']]).forEach(function (attributeName, name) {
2690 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
2691 attributeName, // attributeName
2692 null);
2693});
2694
2695// These are "enumerated" HTML attributes that accept "true" and "false".
2696// In React, we let users pass `true` and `false` even though technically
2697// these aren't boolean attributes (they are coerced to strings).
2698['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (name) {
2699 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty
2700 name.toLowerCase(), // attributeName
2701 null);
2702});
2703
2704// These are "enumerated" SVG attributes that accept "true" and "false".
2705// In React, we let users pass `true` and `false` even though technically
2706// these aren't boolean attributes (they are coerced to strings).
2707// Since these are SVG attributes, their attribute names are case-sensitive.
2708['autoReverse', 'externalResourcesRequired', 'preserveAlpha'].forEach(function (name) {
2709 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty
2710 name, // attributeName
2711 null);
2712});
2713
2714// These are HTML boolean attributes.
2715['allowFullScreen', 'async',
2716// Note: there is a special case that prevents it from being written to the DOM
2717// on the client side because the browsers are inconsistent. Instead we call focus().
2718'autoFocus', 'autoPlay', 'controls', 'default', 'defer', 'disabled', 'formNoValidate', 'hidden', 'loop', 'noModule', 'noValidate', 'open', 'playsInline', 'readOnly', 'required', 'reversed', 'scoped', 'seamless',
2719// Microdata
2720'itemScope'].forEach(function (name) {
2721 properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, // mustUseProperty
2722 name.toLowerCase(), // attributeName
2723 null);
2724});
2725
2726// These are the few React props that we set as DOM properties
2727// rather than attributes. These are all booleans.
2728['checked',
2729// Note: `option.selected` is not updated if `select.multiple` is
2730// disabled with `removeAttribute`. We have special logic for handling this.
2731'multiple', 'muted', 'selected'].forEach(function (name) {
2732 properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, // mustUseProperty
2733 name.toLowerCase(), // attributeName
2734 null);
2735});
2736
2737// These are HTML attributes that are "overloaded booleans": they behave like
2738// booleans, but can also accept a string value.
2739['capture', 'download'].forEach(function (name) {
2740 properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, // mustUseProperty
2741 name.toLowerCase(), // attributeName
2742 null);
2743});
2744
2745// These are HTML attributes that must be positive numbers.
2746['cols', 'rows', 'size', 'span'].forEach(function (name) {
2747 properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, // mustUseProperty
2748 name.toLowerCase(), // attributeName
2749 null);
2750});
2751
2752// These are HTML attributes that must be numbers.
2753['rowSpan', 'start'].forEach(function (name) {
2754 properties[name] = new PropertyInfoRecord(name, NUMERIC, false, // mustUseProperty
2755 name.toLowerCase(), // attributeName
2756 null);
2757});
2758
2759var CAMELIZE = /[\-\:]([a-z])/g;
2760var capitalize = function (token) {
2761 return token[1].toUpperCase();
2762};
2763
2764// This is a list of all SVG attributes that need special casing, namespacing,
2765// or boolean value assignment. Regular attributes that just accept strings
2766// and have the same names are omitted, just like in the HTML whitelist.
2767// Some of these attributes can be hard to find. This list was created by
2768// scrapping the MDN documentation.
2769['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) {
2770 var name = attributeName.replace(CAMELIZE, capitalize);
2771 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
2772 attributeName, null);
2773});
2774
2775// String SVG attributes with the xlink namespace.
2776['xlink:actuate', 'xlink:arcrole', 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type'].forEach(function (attributeName) {
2777 var name = attributeName.replace(CAMELIZE, capitalize);
2778 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
2779 attributeName, 'http://www.w3.org/1999/xlink');
2780});
2781
2782// String SVG attributes with the xml namespace.
2783['xml:base', 'xml:lang', 'xml:space'].forEach(function (attributeName) {
2784 var name = attributeName.replace(CAMELIZE, capitalize);
2785 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty
2786 attributeName, 'http://www.w3.org/XML/1998/namespace');
2787});
2788
2789// Special case: this attribute exists both in HTML and SVG.
2790// Its "tabindex" attribute name is case-sensitive in SVG so we can't just use
2791// its React `tabIndex` name, like we do for attributes that exist only in HTML.
2792properties.tabIndex = new PropertyInfoRecord('tabIndex', STRING, false, // mustUseProperty
2793'tabindex', // attributeName
2794null);
2795
2796/**
2797 * Get the value for a property on a node. Only used in DEV for SSR validation.
2798 * The "expected" argument is used as a hint of what the expected value is.
2799 * Some properties have multiple equivalent values.
2800 */
2801function getValueForProperty(node, name, expected, propertyInfo) {
2802 {
2803 if (propertyInfo.mustUseProperty) {
2804 var propertyName = propertyInfo.propertyName;
2805
2806 return node[propertyName];
2807 } else {
2808 var attributeName = propertyInfo.attributeName;
2809
2810 var stringValue = null;
2811
2812 if (propertyInfo.type === OVERLOADED_BOOLEAN) {
2813 if (node.hasAttribute(attributeName)) {
2814 var value = node.getAttribute(attributeName);
2815 if (value === '') {
2816 return true;
2817 }
2818 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
2819 return value;
2820 }
2821 if (value === '' + expected) {
2822 return expected;
2823 }
2824 return value;
2825 }
2826 } else if (node.hasAttribute(attributeName)) {
2827 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
2828 // We had an attribute but shouldn't have had one, so read it
2829 // for the error message.
2830 return node.getAttribute(attributeName);
2831 }
2832 if (propertyInfo.type === BOOLEAN) {
2833 // If this was a boolean, it doesn't matter what the value is
2834 // the fact that we have it is the same as the expected.
2835 return expected;
2836 }
2837 // Even if this property uses a namespace we use getAttribute
2838 // because we assume its namespaced name is the same as our config.
2839 // To use getAttributeNS we need the local name which we don't have
2840 // in our config atm.
2841 stringValue = node.getAttribute(attributeName);
2842 }
2843
2844 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) {
2845 return stringValue === null ? expected : stringValue;
2846 } else if (stringValue === '' + expected) {
2847 return expected;
2848 } else {
2849 return stringValue;
2850 }
2851 }
2852 }
2853}
2854
2855/**
2856 * Get the value for a attribute on a node. Only used in DEV for SSR validation.
2857 * The third argument is used as a hint of what the expected value is. Some
2858 * attributes have multiple equivalent values.
2859 */
2860function getValueForAttribute(node, name, expected) {
2861 {
2862 if (!isAttributeNameSafe(name)) {
2863 return;
2864 }
2865 if (!node.hasAttribute(name)) {
2866 return expected === undefined ? undefined : null;
2867 }
2868 var value = node.getAttribute(name);
2869 if (value === '' + expected) {
2870 return expected;
2871 }
2872 return value;
2873 }
2874}
2875
2876/**
2877 * Sets the value for a property on a node.
2878 *
2879 * @param {DOMElement} node
2880 * @param {string} name
2881 * @param {*} value
2882 */
2883function setValueForProperty(node, name, value, isCustomComponentTag) {
2884 var propertyInfo = getPropertyInfo(name);
2885 if (shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag)) {
2886 return;
2887 }
2888 if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
2889 value = null;
2890 }
2891 // If the prop isn't in the special list, treat it as a simple attribute.
2892 if (isCustomComponentTag || propertyInfo === null) {
2893 if (isAttributeNameSafe(name)) {
2894 var _attributeName = name;
2895 if (value === null) {
2896 node.removeAttribute(_attributeName);
2897 } else {
2898 node.setAttribute(_attributeName, '' + value);
2899 }
2900 }
2901 return;
2902 }
2903 var mustUseProperty = propertyInfo.mustUseProperty;
2904
2905 if (mustUseProperty) {
2906 var propertyName = propertyInfo.propertyName;
2907
2908 if (value === null) {
2909 var type = propertyInfo.type;
2910
2911 node[propertyName] = type === BOOLEAN ? false : '';
2912 } else {
2913 // Contrary to `setAttribute`, object properties are properly
2914 // `toString`ed by IE8/9.
2915 node[propertyName] = value;
2916 }
2917 return;
2918 }
2919 // The rest are treated as attributes with special cases.
2920 var attributeName = propertyInfo.attributeName,
2921 attributeNamespace = propertyInfo.attributeNamespace;
2922
2923 if (value === null) {
2924 node.removeAttribute(attributeName);
2925 } else {
2926 var _type = propertyInfo.type;
2927
2928 var attributeValue = void 0;
2929 if (_type === BOOLEAN || _type === OVERLOADED_BOOLEAN && value === true) {
2930 attributeValue = '';
2931 } else {
2932 // `setAttribute` with objects becomes only `[object]` in IE8/9,
2933 // ('' + value) makes it output the correct toString()-value.
2934 attributeValue = '' + value;
2935 }
2936 if (attributeNamespace) {
2937 node.setAttributeNS(attributeNamespace, attributeName, attributeValue);
2938 } else {
2939 node.setAttribute(attributeName, attributeValue);
2940 }
2941 }
2942}
2943
2944/**
2945 * Copyright (c) 2013-present, Facebook, Inc.
2946 *
2947 * This source code is licensed under the MIT license found in the
2948 * LICENSE file in the root directory of this source tree.
2949 */
2950
2951
2952
2953var ReactPropTypesSecret$1 = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
2954
2955var ReactPropTypesSecret_1 = ReactPropTypesSecret$1;
2956
2957/**
2958 * Copyright (c) 2013-present, Facebook, Inc.
2959 *
2960 * This source code is licensed under the MIT license found in the
2961 * LICENSE file in the root directory of this source tree.
2962 */
2963
2964
2965
2966{
2967 var invariant$2 = invariant_1;
2968 var warning$2 = warning_1;
2969 var ReactPropTypesSecret = ReactPropTypesSecret_1;
2970 var loggedTypeFailures = {};
2971}
2972
2973/**
2974 * Assert that the values match with the type specs.
2975 * Error messages are memorized and will only be shown once.
2976 *
2977 * @param {object} typeSpecs Map of name to a ReactPropType
2978 * @param {object} values Runtime values that need to be type-checked
2979 * @param {string} location e.g. "prop", "context", "child context"
2980 * @param {string} componentName Name of the component for error messages.
2981 * @param {?Function} getStack Returns the component stack.
2982 * @private
2983 */
2984function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
2985 {
2986 for (var typeSpecName in typeSpecs) {
2987 if (typeSpecs.hasOwnProperty(typeSpecName)) {
2988 var error;
2989 // Prop type validation may throw. In case they do, we don't want to
2990 // fail the render phase where it didn't fail before. So we log it.
2991 // After these have been cleaned up, we'll let them throw.
2992 try {
2993 // This is intentionally an invariant that gets caught. It's the same
2994 // behavior as without this statement except with a better message.
2995 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]);
2996 error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
2997 } catch (ex) {
2998 error = ex;
2999 }
3000 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);
3001 if (error instanceof Error && !(error.message in loggedTypeFailures)) {
3002 // Only monitor this failure once because there tends to be a lot of the
3003 // same error.
3004 loggedTypeFailures[error.message] = true;
3005
3006 var stack = getStack ? getStack() : '';
3007
3008 warning$2(false, 'Failed %s type: %s%s', location, error.message, stack != null ? stack : '');
3009 }
3010 }
3011 }
3012 }
3013}
3014
3015var checkPropTypes_1 = checkPropTypes;
3016
3017var ReactControlledValuePropTypes = {
3018 checkPropTypes: null
3019};
3020
3021{
3022 var hasReadOnlyValue = {
3023 button: true,
3024 checkbox: true,
3025 image: true,
3026 hidden: true,
3027 radio: true,
3028 reset: true,
3029 submit: true
3030 };
3031
3032 var propTypes = {
3033 value: function (props, propName, componentName) {
3034 if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {
3035 return null;
3036 }
3037 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`.');
3038 },
3039 checked: function (props, propName, componentName) {
3040 if (!props[propName] || props.onChange || props.readOnly || props.disabled) {
3041 return null;
3042 }
3043 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`.');
3044 }
3045 };
3046
3047 /**
3048 * Provide a linked `value` attribute for controlled forms. You should not use
3049 * this outside of the ReactDOM controlled form components.
3050 */
3051 ReactControlledValuePropTypes.checkPropTypes = function (tagName, props, getStack) {
3052 checkPropTypes_1(propTypes, props, 'prop', tagName, getStack);
3053 };
3054}
3055
3056// TODO: direct imports like some-package/src/* are bad. Fix me.
3057var getCurrentFiberOwnerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
3058var getCurrentFiberStackAddendum = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
3059
3060var didWarnValueDefaultValue = false;
3061var didWarnCheckedDefaultChecked = false;
3062var didWarnControlledToUncontrolled = false;
3063var didWarnUncontrolledToControlled = false;
3064
3065function isControlled(props) {
3066 var usesChecked = props.type === 'checkbox' || props.type === 'radio';
3067 return usesChecked ? props.checked != null : props.value != null;
3068}
3069
3070/**
3071 * Implements an <input> host component that allows setting these optional
3072 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
3073 *
3074 * If `checked` or `value` are not supplied (or null/undefined), user actions
3075 * that affect the checked state or value will trigger updates to the element.
3076 *
3077 * If they are supplied (and not null/undefined), the rendered element will not
3078 * trigger updates to the element. Instead, the props must change in order for
3079 * the rendered element to be updated.
3080 *
3081 * The rendered element will be initialized as unchecked (or `defaultChecked`)
3082 * with an empty value (or `defaultValue`).
3083 *
3084 * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
3085 */
3086
3087function getHostProps(element, props) {
3088 var node = element;
3089 var checked = props.checked;
3090
3091 var hostProps = _assign({}, props, {
3092 defaultChecked: undefined,
3093 defaultValue: undefined,
3094 value: undefined,
3095 checked: checked != null ? checked : node._wrapperState.initialChecked
3096 });
3097
3098 return hostProps;
3099}
3100
3101function initWrapperState(element, props) {
3102 {
3103 ReactControlledValuePropTypes.checkPropTypes('input', props, getCurrentFiberStackAddendum);
3104
3105 if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
3106 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);
3107 didWarnCheckedDefaultChecked = true;
3108 }
3109 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
3110 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);
3111 didWarnValueDefaultValue = true;
3112 }
3113 }
3114
3115 var node = element;
3116 var defaultValue = props.defaultValue == null ? '' : props.defaultValue;
3117
3118 node._wrapperState = {
3119 initialChecked: props.checked != null ? props.checked : props.defaultChecked,
3120 initialValue: getSafeValue(props.value != null ? props.value : defaultValue),
3121 controlled: isControlled(props)
3122 };
3123}
3124
3125function updateChecked(element, props) {
3126 var node = element;
3127 var checked = props.checked;
3128 if (checked != null) {
3129 setValueForProperty(node, 'checked', checked, false);
3130 }
3131}
3132
3133function updateWrapper(element, props) {
3134 var node = element;
3135 {
3136 var _controlled = isControlled(props);
3137
3138 if (!node._wrapperState.controlled && _controlled && !didWarnUncontrolledToControlled) {
3139 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());
3140 didWarnUncontrolledToControlled = true;
3141 }
3142 if (node._wrapperState.controlled && !_controlled && !didWarnControlledToUncontrolled) {
3143 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());
3144 didWarnControlledToUncontrolled = true;
3145 }
3146 }
3147
3148 updateChecked(element, props);
3149
3150 var value = getSafeValue(props.value);
3151
3152 if (value != null) {
3153 if (props.type === 'number') {
3154 if (value === 0 && node.value === '' ||
3155 // eslint-disable-next-line
3156 node.value != value) {
3157 node.value = '' + value;
3158 }
3159 } else if (node.value !== '' + value) {
3160 node.value = '' + value;
3161 }
3162 }
3163
3164 if (props.hasOwnProperty('value')) {
3165 setDefaultValue(node, props.type, value);
3166 } else if (props.hasOwnProperty('defaultValue')) {
3167 setDefaultValue(node, props.type, getSafeValue(props.defaultValue));
3168 }
3169
3170 if (props.checked == null && props.defaultChecked != null) {
3171 node.defaultChecked = !!props.defaultChecked;
3172 }
3173}
3174
3175function postMountWrapper(element, props) {
3176 var node = element;
3177
3178 if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) {
3179 // Do not assign value if it is already set. This prevents user text input
3180 // from being lost during SSR hydration.
3181 if (node.value === '') {
3182 node.value = '' + node._wrapperState.initialValue;
3183 }
3184
3185 // value must be assigned before defaultValue. This fixes an issue where the
3186 // visually displayed value of date inputs disappears on mobile Safari and Chrome:
3187 // https://github.com/facebook/react/issues/7233
3188 node.defaultValue = '' + node._wrapperState.initialValue;
3189 }
3190
3191 // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
3192 // this is needed to work around a chrome bug where setting defaultChecked
3193 // will sometimes influence the value of checked (even after detachment).
3194 // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
3195 // We need to temporarily unset name to avoid disrupting radio button groups.
3196 var name = node.name;
3197 if (name !== '') {
3198 node.name = '';
3199 }
3200 node.defaultChecked = !node.defaultChecked;
3201 node.defaultChecked = !node.defaultChecked;
3202 if (name !== '') {
3203 node.name = name;
3204 }
3205}
3206
3207function restoreControlledState(element, props) {
3208 var node = element;
3209 updateWrapper(node, props);
3210 updateNamedCousins(node, props);
3211}
3212
3213function updateNamedCousins(rootNode, props) {
3214 var name = props.name;
3215 if (props.type === 'radio' && name != null) {
3216 var queryRoot = rootNode;
3217
3218 while (queryRoot.parentNode) {
3219 queryRoot = queryRoot.parentNode;
3220 }
3221
3222 // If `rootNode.form` was non-null, then we could try `form.elements`,
3223 // but that sometimes behaves strangely in IE8. We could also try using
3224 // `form.getElementsByName`, but that will only return direct children
3225 // and won't include inputs that use the HTML5 `form=` attribute. Since
3226 // the input might not even be in a form. It might not even be in the
3227 // document. Let's just use the local `querySelectorAll` to ensure we don't
3228 // miss anything.
3229 var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]');
3230
3231 for (var i = 0; i < group.length; i++) {
3232 var otherNode = group[i];
3233 if (otherNode === rootNode || otherNode.form !== rootNode.form) {
3234 continue;
3235 }
3236 // This will throw if radio buttons rendered by different copies of React
3237 // and the same name are rendered into the same form (same as #1939).
3238 // That's probably okay; we don't support it just as we don't support
3239 // mixing React radio buttons with non-React ones.
3240 var otherProps = getFiberCurrentPropsFromNode$1(otherNode);
3241 !otherProps ? invariant_1(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : void 0;
3242
3243 // We need update the tracked value on the named cousin since the value
3244 // was changed but the input saw no event or value set
3245 updateValueIfChanged(otherNode);
3246
3247 // If this is a controlled radio button group, forcing the input that
3248 // was previously checked to update will cause it to be come re-checked
3249 // as appropriate.
3250 updateWrapper(otherNode, otherProps);
3251 }
3252 }
3253}
3254
3255// In Chrome, assigning defaultValue to certain input types triggers input validation.
3256// For number inputs, the display value loses trailing decimal points. For email inputs,
3257// Chrome raises "The specified value <x> is not a valid email address".
3258//
3259// Here we check to see if the defaultValue has actually changed, avoiding these problems
3260// when the user is inputting text
3261//
3262// https://github.com/facebook/react/issues/7253
3263function setDefaultValue(node, type, value) {
3264 if (
3265 // Focused number inputs synchronize on blur. See ChangeEventPlugin.js
3266 type !== 'number' || node.ownerDocument.activeElement !== node) {
3267 if (value == null) {
3268 node.defaultValue = '' + node._wrapperState.initialValue;
3269 } else if (node.defaultValue !== '' + value) {
3270 node.defaultValue = '' + value;
3271 }
3272 }
3273}
3274
3275function getSafeValue(value) {
3276 switch (typeof value) {
3277 case 'boolean':
3278 case 'number':
3279 case 'object':
3280 case 'string':
3281 case 'undefined':
3282 return value;
3283 default:
3284 // function, symbol are assigned as empty strings
3285 return '';
3286 }
3287}
3288
3289var eventTypes$1 = {
3290 change: {
3291 phasedRegistrationNames: {
3292 bubbled: 'onChange',
3293 captured: 'onChangeCapture'
3294 },
3295 dependencies: ['topBlur', 'topChange', 'topClick', 'topFocus', 'topInput', 'topKeyDown', 'topKeyUp', 'topSelectionChange']
3296 }
3297};
3298
3299function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
3300 var event = SyntheticEvent$1.getPooled(eventTypes$1.change, inst, nativeEvent, target);
3301 event.type = 'change';
3302 // Flag this event loop as needing state restore.
3303 enqueueStateRestore(target);
3304 accumulateTwoPhaseDispatches(event);
3305 return event;
3306}
3307/**
3308 * For IE shims
3309 */
3310var activeElement = null;
3311var activeElementInst = null;
3312
3313/**
3314 * SECTION: handle `change` event
3315 */
3316function shouldUseChangeEvent(elem) {
3317 var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
3318 return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
3319}
3320
3321function manualDispatchChangeEvent(nativeEvent) {
3322 var event = createAndAccumulateChangeEvent(activeElementInst, nativeEvent, getEventTarget(nativeEvent));
3323
3324 // If change and propertychange bubbled, we'd just bind to it like all the
3325 // other events and have it go through ReactBrowserEventEmitter. Since it
3326 // doesn't, we manually listen for the events and so we have to enqueue and
3327 // process the abstract event manually.
3328 //
3329 // Batching is necessary here in order to ensure that all event handlers run
3330 // before the next rerender (including event handlers attached to ancestor
3331 // elements instead of directly on the input). Without this, controlled
3332 // components don't work properly in conjunction with event bubbling because
3333 // the component is rerendered and the value reverted before all the event
3334 // handlers can run. See https://github.com/facebook/react/issues/708.
3335 batchedUpdates(runEventInBatch, event);
3336}
3337
3338function runEventInBatch(event) {
3339 runEventsInBatch(event, false);
3340}
3341
3342function getInstIfValueChanged(targetInst) {
3343 var targetNode = getNodeFromInstance$1(targetInst);
3344 if (updateValueIfChanged(targetNode)) {
3345 return targetInst;
3346 }
3347}
3348
3349function getTargetInstForChangeEvent(topLevelType, targetInst) {
3350 if (topLevelType === 'topChange') {
3351 return targetInst;
3352 }
3353}
3354
3355/**
3356 * SECTION: handle `input` event
3357 */
3358var isInputEventSupported = false;
3359if (ExecutionEnvironment_1.canUseDOM) {
3360 // IE9 claims to support the input event but fails to trigger it when
3361 // deleting text, so we ignore its input events.
3362 isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9);
3363}
3364
3365/**
3366 * (For IE <=9) Starts tracking propertychange events on the passed-in element
3367 * and override the value property so that we can distinguish user events from
3368 * value changes in JS.
3369 */
3370function startWatchingForValueChange(target, targetInst) {
3371 activeElement = target;
3372 activeElementInst = targetInst;
3373 activeElement.attachEvent('onpropertychange', handlePropertyChange);
3374}
3375
3376/**
3377 * (For IE <=9) Removes the event listeners from the currently-tracked element,
3378 * if any exists.
3379 */
3380function stopWatchingForValueChange() {
3381 if (!activeElement) {
3382 return;
3383 }
3384 activeElement.detachEvent('onpropertychange', handlePropertyChange);
3385 activeElement = null;
3386 activeElementInst = null;
3387}
3388
3389/**
3390 * (For IE <=9) Handles a propertychange event, sending a `change` event if
3391 * the value of the active element has changed.
3392 */
3393function handlePropertyChange(nativeEvent) {
3394 if (nativeEvent.propertyName !== 'value') {
3395 return;
3396 }
3397 if (getInstIfValueChanged(activeElementInst)) {
3398 manualDispatchChangeEvent(nativeEvent);
3399 }
3400}
3401
3402function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) {
3403 if (topLevelType === 'topFocus') {
3404 // In IE9, propertychange fires for most input events but is buggy and
3405 // doesn't fire when text is deleted, but conveniently, selectionchange
3406 // appears to fire in all of the remaining cases so we catch those and
3407 // forward the event if the value has changed
3408 // In either case, we don't want to call the event handler if the value
3409 // is changed from JS so we redefine a setter for `.value` that updates
3410 // our activeElementValue variable, allowing us to ignore those changes
3411 //
3412 // stopWatching() should be a noop here but we call it just in case we
3413 // missed a blur event somehow.
3414 stopWatchingForValueChange();
3415 startWatchingForValueChange(target, targetInst);
3416 } else if (topLevelType === 'topBlur') {
3417 stopWatchingForValueChange();
3418 }
3419}
3420
3421// For IE8 and IE9.
3422function getTargetInstForInputEventPolyfill(topLevelType, targetInst) {
3423 if (topLevelType === 'topSelectionChange' || topLevelType === 'topKeyUp' || topLevelType === 'topKeyDown') {
3424 // On the selectionchange event, the target is just document which isn't
3425 // helpful for us so just check activeElement instead.
3426 //
3427 // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
3428 // propertychange on the first input event after setting `value` from a
3429 // script and fires only keydown, keypress, keyup. Catching keyup usually
3430 // gets it and catching keydown lets us fire an event for the first
3431 // keystroke if user does a key repeat (it'll be a little delayed: right
3432 // before the second keystroke). Other input methods (e.g., paste) seem to
3433 // fire selectionchange normally.
3434 return getInstIfValueChanged(activeElementInst);
3435 }
3436}
3437
3438/**
3439 * SECTION: handle `click` event
3440 */
3441function shouldUseClickEvent(elem) {
3442 // Use the `click` event to detect changes to checkbox and radio inputs.
3443 // This approach works across all browsers, whereas `change` does not fire
3444 // until `blur` in IE8.
3445 var nodeName = elem.nodeName;
3446 return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
3447}
3448
3449function getTargetInstForClickEvent(topLevelType, targetInst) {
3450 if (topLevelType === 'topClick') {
3451 return getInstIfValueChanged(targetInst);
3452 }
3453}
3454
3455function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) {
3456 if (topLevelType === 'topInput' || topLevelType === 'topChange') {
3457 return getInstIfValueChanged(targetInst);
3458 }
3459}
3460
3461function handleControlledInputBlur(inst, node) {
3462 // TODO: In IE, inst is occasionally null. Why?
3463 if (inst == null) {
3464 return;
3465 }
3466
3467 // Fiber and ReactDOM keep wrapper state in separate places
3468 var state = inst._wrapperState || node._wrapperState;
3469
3470 if (!state || !state.controlled || node.type !== 'number') {
3471 return;
3472 }
3473
3474 // If controlled, assign the value attribute to the current value on blur
3475 setDefaultValue(node, 'number', node.value);
3476}
3477
3478/**
3479 * This plugin creates an `onChange` event that normalizes change events
3480 * across form elements. This event fires at a time when it's possible to
3481 * change the element's value without seeing a flicker.
3482 *
3483 * Supported elements are:
3484 * - input (see `isTextInputElement`)
3485 * - textarea
3486 * - select
3487 */
3488var ChangeEventPlugin = {
3489 eventTypes: eventTypes$1,
3490
3491 _isInputEventSupported: isInputEventSupported,
3492
3493 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
3494 var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
3495
3496 var getTargetInstFunc = void 0,
3497 handleEventFunc = void 0;
3498 if (shouldUseChangeEvent(targetNode)) {
3499 getTargetInstFunc = getTargetInstForChangeEvent;
3500 } else if (isTextInputElement(targetNode)) {
3501 if (isInputEventSupported) {
3502 getTargetInstFunc = getTargetInstForInputOrChangeEvent;
3503 } else {
3504 getTargetInstFunc = getTargetInstForInputEventPolyfill;
3505 handleEventFunc = handleEventsForInputEventPolyfill;
3506 }
3507 } else if (shouldUseClickEvent(targetNode)) {
3508 getTargetInstFunc = getTargetInstForClickEvent;
3509 }
3510
3511 if (getTargetInstFunc) {
3512 var inst = getTargetInstFunc(topLevelType, targetInst);
3513 if (inst) {
3514 var event = createAndAccumulateChangeEvent(inst, nativeEvent, nativeEventTarget);
3515 return event;
3516 }
3517 }
3518
3519 if (handleEventFunc) {
3520 handleEventFunc(topLevelType, targetNode, targetInst);
3521 }
3522
3523 // When blurring, set the value attribute for number inputs
3524 if (topLevelType === 'topBlur') {
3525 handleControlledInputBlur(targetInst, targetNode);
3526 }
3527 }
3528};
3529
3530/**
3531 * Module that is injectable into `EventPluginHub`, that specifies a
3532 * deterministic ordering of `EventPlugin`s. A convenient way to reason about
3533 * plugins, without having to package every one of them. This is better than
3534 * having plugins be ordered in the same order that they are injected because
3535 * that ordering would be influenced by the packaging order.
3536 * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
3537 * preventing default on events is convenient in `SimpleEventPlugin` handlers.
3538 */
3539var DOMEventPluginOrder = ['ResponderEventPlugin', 'SimpleEventPlugin', 'TapEventPlugin', 'EnterLeaveEventPlugin', 'ChangeEventPlugin', 'SelectEventPlugin', 'BeforeInputEventPlugin'];
3540
3541var SyntheticUIEvent = SyntheticEvent$1.extend({
3542 view: null,
3543 detail: null
3544});
3545
3546/**
3547 * Translation from modifier key to the associated property in the event.
3548 * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers
3549 */
3550
3551var modifierKeyToProp = {
3552 Alt: 'altKey',
3553 Control: 'ctrlKey',
3554 Meta: 'metaKey',
3555 Shift: 'shiftKey'
3556};
3557
3558// IE8 does not implement getModifierState so we simply map it to the only
3559// modifier keys exposed by the event itself, does not support Lock-keys.
3560// Currently, all major browsers except Chrome seems to support Lock-keys.
3561function modifierStateGetter(keyArg) {
3562 var syntheticEvent = this;
3563 var nativeEvent = syntheticEvent.nativeEvent;
3564 if (nativeEvent.getModifierState) {
3565 return nativeEvent.getModifierState(keyArg);
3566 }
3567 var keyProp = modifierKeyToProp[keyArg];
3568 return keyProp ? !!nativeEvent[keyProp] : false;
3569}
3570
3571function getEventModifierState(nativeEvent) {
3572 return modifierStateGetter;
3573}
3574
3575/**
3576 * @interface MouseEvent
3577 * @see http://www.w3.org/TR/DOM-Level-3-Events/
3578 */
3579var SyntheticMouseEvent = SyntheticUIEvent.extend({
3580 screenX: null,
3581 screenY: null,
3582 clientX: null,
3583 clientY: null,
3584 pageX: null,
3585 pageY: null,
3586 ctrlKey: null,
3587 shiftKey: null,
3588 altKey: null,
3589 metaKey: null,
3590 getModifierState: getEventModifierState,
3591 button: null,
3592 buttons: null,
3593 relatedTarget: function (event) {
3594 return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);
3595 }
3596});
3597
3598var eventTypes$2 = {
3599 mouseEnter: {
3600 registrationName: 'onMouseEnter',
3601 dependencies: ['topMouseOut', 'topMouseOver']
3602 },
3603 mouseLeave: {
3604 registrationName: 'onMouseLeave',
3605 dependencies: ['topMouseOut', 'topMouseOver']
3606 }
3607};
3608
3609var EnterLeaveEventPlugin = {
3610 eventTypes: eventTypes$2,
3611
3612 /**
3613 * For almost every interaction we care about, there will be both a top-level
3614 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
3615 * we do not extract duplicate events. However, moving the mouse into the
3616 * browser from outside will not fire a `mouseout` event. In this case, we use
3617 * the `mouseover` top-level event.
3618 */
3619 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
3620 if (topLevelType === 'topMouseOver' && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
3621 return null;
3622 }
3623 if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') {
3624 // Must not be a mouse in or mouse out - ignoring.
3625 return null;
3626 }
3627
3628 var win = void 0;
3629 if (nativeEventTarget.window === nativeEventTarget) {
3630 // `nativeEventTarget` is probably a window object.
3631 win = nativeEventTarget;
3632 } else {
3633 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
3634 var doc = nativeEventTarget.ownerDocument;
3635 if (doc) {
3636 win = doc.defaultView || doc.parentWindow;
3637 } else {
3638 win = window;
3639 }
3640 }
3641
3642 var from = void 0;
3643 var to = void 0;
3644 if (topLevelType === 'topMouseOut') {
3645 from = targetInst;
3646 var related = nativeEvent.relatedTarget || nativeEvent.toElement;
3647 to = related ? getClosestInstanceFromNode(related) : null;
3648 } else {
3649 // Moving to a node from outside the window.
3650 from = null;
3651 to = targetInst;
3652 }
3653
3654 if (from === to) {
3655 // Nothing pertains to our managed components.
3656 return null;
3657 }
3658
3659 var fromNode = from == null ? win : getNodeFromInstance$1(from);
3660 var toNode = to == null ? win : getNodeFromInstance$1(to);
3661
3662 var leave = SyntheticMouseEvent.getPooled(eventTypes$2.mouseLeave, from, nativeEvent, nativeEventTarget);
3663 leave.type = 'mouseleave';
3664 leave.target = fromNode;
3665 leave.relatedTarget = toNode;
3666
3667 var enter = SyntheticMouseEvent.getPooled(eventTypes$2.mouseEnter, to, nativeEvent, nativeEventTarget);
3668 enter.type = 'mouseenter';
3669 enter.target = toNode;
3670 enter.relatedTarget = fromNode;
3671
3672 accumulateEnterLeaveDispatches(leave, enter, from, to);
3673
3674 return [leave, enter];
3675 }
3676};
3677
3678/**
3679 * Copyright (c) 2013-present, Facebook, Inc.
3680 *
3681 * This source code is licensed under the MIT license found in the
3682 * LICENSE file in the root directory of this source tree.
3683 *
3684 * @typechecks
3685 */
3686
3687/* eslint-disable fb-www/typeof-undefined */
3688
3689/**
3690 * Same as document.activeElement but wraps in a try-catch block. In IE it is
3691 * not safe to call document.activeElement if there is nothing focused.
3692 *
3693 * The activeElement will be null only if the document or document body is not
3694 * yet defined.
3695 *
3696 * @param {?DOMDocument} doc Defaults to current document.
3697 * @return {?DOMElement}
3698 */
3699function getActiveElement(doc) /*?DOMElement*/{
3700 doc = doc || (typeof document !== 'undefined' ? document : undefined);
3701 if (typeof doc === 'undefined') {
3702 return null;
3703 }
3704 try {
3705 return doc.activeElement || doc.body;
3706 } catch (e) {
3707 return doc.body;
3708 }
3709}
3710
3711var getActiveElement_1 = getActiveElement;
3712
3713/**
3714 * Copyright (c) 2013-present, Facebook, Inc.
3715 *
3716 * This source code is licensed under the MIT license found in the
3717 * LICENSE file in the root directory of this source tree.
3718 *
3719 * @typechecks
3720 *
3721 */
3722
3723/*eslint-disable no-self-compare */
3724
3725
3726
3727var hasOwnProperty = Object.prototype.hasOwnProperty;
3728
3729/**
3730 * inlined Object.is polyfill to avoid requiring consumers ship their own
3731 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
3732 */
3733function is(x, y) {
3734 // SameValue algorithm
3735 if (x === y) {
3736 // Steps 1-5, 7-10
3737 // Steps 6.b-6.e: +0 != -0
3738 // Added the nonzero y check to make Flow happy, but it is redundant
3739 return x !== 0 || y !== 0 || 1 / x === 1 / y;
3740 } else {
3741 // Step 6.a: NaN == NaN
3742 return x !== x && y !== y;
3743 }
3744}
3745
3746/**
3747 * Performs equality by iterating through keys on an object and returning false
3748 * when any key has values which are not strictly equal between the arguments.
3749 * Returns true when the values of all keys are strictly equal.
3750 */
3751function shallowEqual(objA, objB) {
3752 if (is(objA, objB)) {
3753 return true;
3754 }
3755
3756 if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
3757 return false;
3758 }
3759
3760 var keysA = Object.keys(objA);
3761 var keysB = Object.keys(objB);
3762
3763 if (keysA.length !== keysB.length) {
3764 return false;
3765 }
3766
3767 // Test for A's keys different from B.
3768 for (var i = 0; i < keysA.length; i++) {
3769 if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
3770 return false;
3771 }
3772 }
3773
3774 return true;
3775}
3776
3777var shallowEqual_1 = shallowEqual;
3778
3779/**
3780 * `ReactInstanceMap` maintains a mapping from a public facing stateful
3781 * instance (key) and the internal representation (value). This allows public
3782 * methods to accept the user facing instance as an argument and map them back
3783 * to internal methods.
3784 *
3785 * Note that this module is currently shared and assumed to be stateless.
3786 * If this becomes an actual Map, that will break.
3787 */
3788
3789/**
3790 * This API should be called `delete` but we'd have to make sure to always
3791 * transform these to strings for IE support. When this transform is fully
3792 * supported we can rename it.
3793 */
3794
3795
3796function get(key) {
3797 return key._reactInternalFiber;
3798}
3799
3800function has(key) {
3801 return key._reactInternalFiber !== undefined;
3802}
3803
3804function set(key, value) {
3805 key._reactInternalFiber = value;
3806}
3807
3808// Don't change these two values:
3809var NoEffect = 0;
3810var PerformedWork = 1;
3811
3812// You can change the rest (and add more).
3813var Placement = 2;
3814var Update = 4;
3815var PlacementAndUpdate = 6;
3816var Deletion = 8;
3817var ContentReset = 16;
3818var Callback = 32;
3819var Err = 64;
3820var Ref = 128;
3821
3822var MOUNTING = 1;
3823var MOUNTED = 2;
3824var UNMOUNTED = 3;
3825
3826function isFiberMountedImpl(fiber) {
3827 var node = fiber;
3828 if (!fiber.alternate) {
3829 // If there is no alternate, this might be a new tree that isn't inserted
3830 // yet. If it is, then it will have a pending insertion effect on it.
3831 if ((node.effectTag & Placement) !== NoEffect) {
3832 return MOUNTING;
3833 }
3834 while (node['return']) {
3835 node = node['return'];
3836 if ((node.effectTag & Placement) !== NoEffect) {
3837 return MOUNTING;
3838 }
3839 }
3840 } else {
3841 while (node['return']) {
3842 node = node['return'];
3843 }
3844 }
3845 if (node.tag === HostRoot) {
3846 // TODO: Check if this was a nested HostRoot when used with
3847 // renderContainerIntoSubtree.
3848 return MOUNTED;
3849 }
3850 // If we didn't hit the root, that means that we're in an disconnected tree
3851 // that has been unmounted.
3852 return UNMOUNTED;
3853}
3854
3855function isFiberMounted(fiber) {
3856 return isFiberMountedImpl(fiber) === MOUNTED;
3857}
3858
3859function isMounted(component) {
3860 {
3861 var owner = ReactCurrentOwner.current;
3862 if (owner !== null && owner.tag === ClassComponent) {
3863 var ownerFiber = owner;
3864 var instance = ownerFiber.stateNode;
3865 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');
3866 instance._warnedAboutRefsInRender = true;
3867 }
3868 }
3869
3870 var fiber = get(component);
3871 if (!fiber) {
3872 return false;
3873 }
3874 return isFiberMountedImpl(fiber) === MOUNTED;
3875}
3876
3877function assertIsMounted(fiber) {
3878 !(isFiberMountedImpl(fiber) === MOUNTED) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
3879}
3880
3881function findCurrentFiberUsingSlowPath(fiber) {
3882 var alternate = fiber.alternate;
3883 if (!alternate) {
3884 // If there is no alternate, then we only need to check if it is mounted.
3885 var state = isFiberMountedImpl(fiber);
3886 !(state !== UNMOUNTED) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
3887 if (state === MOUNTING) {
3888 return null;
3889 }
3890 return fiber;
3891 }
3892 // If we have two possible branches, we'll walk backwards up to the root
3893 // to see what path the root points to. On the way we may hit one of the
3894 // special cases and we'll deal with them.
3895 var a = fiber;
3896 var b = alternate;
3897 while (true) {
3898 var parentA = a['return'];
3899 var parentB = parentA ? parentA.alternate : null;
3900 if (!parentA || !parentB) {
3901 // We're at the root.
3902 break;
3903 }
3904
3905 // If both copies of the parent fiber point to the same child, we can
3906 // assume that the child is current. This happens when we bailout on low
3907 // priority: the bailed out fiber's child reuses the current child.
3908 if (parentA.child === parentB.child) {
3909 var child = parentA.child;
3910 while (child) {
3911 if (child === a) {
3912 // We've determined that A is the current branch.
3913 assertIsMounted(parentA);
3914 return fiber;
3915 }
3916 if (child === b) {
3917 // We've determined that B is the current branch.
3918 assertIsMounted(parentA);
3919 return alternate;
3920 }
3921 child = child.sibling;
3922 }
3923 // We should never have an alternate for any mounting node. So the only
3924 // way this could possibly happen is if this was unmounted, if at all.
3925 invariant_1(false, 'Unable to find node on an unmounted component.');
3926 }
3927
3928 if (a['return'] !== b['return']) {
3929 // The return pointer of A and the return pointer of B point to different
3930 // fibers. We assume that return pointers never criss-cross, so A must
3931 // belong to the child set of A.return, and B must belong to the child
3932 // set of B.return.
3933 a = parentA;
3934 b = parentB;
3935 } else {
3936 // The return pointers point to the same fiber. We'll have to use the
3937 // default, slow path: scan the child sets of each parent alternate to see
3938 // which child belongs to which set.
3939 //
3940 // Search parent A's child set
3941 var didFindChild = false;
3942 var _child = parentA.child;
3943 while (_child) {
3944 if (_child === a) {
3945 didFindChild = true;
3946 a = parentA;
3947 b = parentB;
3948 break;
3949 }
3950 if (_child === b) {
3951 didFindChild = true;
3952 b = parentA;
3953 a = parentB;
3954 break;
3955 }
3956 _child = _child.sibling;
3957 }
3958 if (!didFindChild) {
3959 // Search parent B's child set
3960 _child = parentB.child;
3961 while (_child) {
3962 if (_child === a) {
3963 didFindChild = true;
3964 a = parentB;
3965 b = parentA;
3966 break;
3967 }
3968 if (_child === b) {
3969 didFindChild = true;
3970 b = parentB;
3971 a = parentA;
3972 break;
3973 }
3974 _child = _child.sibling;
3975 }
3976 !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;
3977 }
3978 }
3979
3980 !(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;
3981 }
3982 // If the root is not a host container, we're in a disconnected tree. I.e.
3983 // unmounted.
3984 !(a.tag === HostRoot) ? invariant_1(false, 'Unable to find node on an unmounted component.') : void 0;
3985 if (a.stateNode.current === a) {
3986 // We've determined that A is the current branch.
3987 return fiber;
3988 }
3989 // Otherwise B has to be current branch.
3990 return alternate;
3991}
3992
3993function findCurrentHostFiber(parent) {
3994 var currentParent = findCurrentFiberUsingSlowPath(parent);
3995 if (!currentParent) {
3996 return null;
3997 }
3998
3999 // Next we'll drill down this component to find the first HostComponent/Text.
4000 var node = currentParent;
4001 while (true) {
4002 if (node.tag === HostComponent || node.tag === HostText) {
4003 return node;
4004 } else if (node.child) {
4005 node.child['return'] = node;
4006 node = node.child;
4007 continue;
4008 }
4009 if (node === currentParent) {
4010 return null;
4011 }
4012 while (!node.sibling) {
4013 if (!node['return'] || node['return'] === currentParent) {
4014 return null;
4015 }
4016 node = node['return'];
4017 }
4018 node.sibling['return'] = node['return'];
4019 node = node.sibling;
4020 }
4021 // Flow needs the return null here, but ESLint complains about it.
4022 // eslint-disable-next-line no-unreachable
4023 return null;
4024}
4025
4026function findCurrentHostFiberWithNoPortals(parent) {
4027 var currentParent = findCurrentFiberUsingSlowPath(parent);
4028 if (!currentParent) {
4029 return null;
4030 }
4031
4032 // Next we'll drill down this component to find the first HostComponent/Text.
4033 var node = currentParent;
4034 while (true) {
4035 if (node.tag === HostComponent || node.tag === HostText) {
4036 return node;
4037 } else if (node.child && node.tag !== HostPortal) {
4038 node.child['return'] = node;
4039 node = node.child;
4040 continue;
4041 }
4042 if (node === currentParent) {
4043 return null;
4044 }
4045 while (!node.sibling) {
4046 if (!node['return'] || node['return'] === currentParent) {
4047 return null;
4048 }
4049 node = node['return'];
4050 }
4051 node.sibling['return'] = node['return'];
4052 node = node.sibling;
4053 }
4054 // Flow needs the return null here, but ESLint complains about it.
4055 // eslint-disable-next-line no-unreachable
4056 return null;
4057}
4058
4059function addEventBubbleListener(element, eventType, listener) {
4060 element.addEventListener(eventType, listener, false);
4061}
4062
4063function addEventCaptureListener(element, eventType, listener) {
4064 element.addEventListener(eventType, listener, true);
4065}
4066
4067var CALLBACK_BOOKKEEPING_POOL_SIZE = 10;
4068var callbackBookkeepingPool = [];
4069
4070/**
4071 * Find the deepest React component completely containing the root of the
4072 * passed-in instance (for use when entire React trees are nested within each
4073 * other). If React trees are not nested, returns null.
4074 */
4075function findRootContainerNode(inst) {
4076 // TODO: It may be a good idea to cache this to prevent unnecessary DOM
4077 // traversal, but caching is difficult to do correctly without using a
4078 // mutation observer to listen for all DOM changes.
4079 while (inst['return']) {
4080 inst = inst['return'];
4081 }
4082 if (inst.tag !== HostRoot) {
4083 // This can happen if we're in a detached tree.
4084 return null;
4085 }
4086 return inst.stateNode.containerInfo;
4087}
4088
4089// Used to store ancestor hierarchy in top level callback
4090function getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst) {
4091 if (callbackBookkeepingPool.length) {
4092 var instance = callbackBookkeepingPool.pop();
4093 instance.topLevelType = topLevelType;
4094 instance.nativeEvent = nativeEvent;
4095 instance.targetInst = targetInst;
4096 return instance;
4097 }
4098 return {
4099 topLevelType: topLevelType,
4100 nativeEvent: nativeEvent,
4101 targetInst: targetInst,
4102 ancestors: []
4103 };
4104}
4105
4106function releaseTopLevelCallbackBookKeeping(instance) {
4107 instance.topLevelType = null;
4108 instance.nativeEvent = null;
4109 instance.targetInst = null;
4110 instance.ancestors.length = 0;
4111 if (callbackBookkeepingPool.length < CALLBACK_BOOKKEEPING_POOL_SIZE) {
4112 callbackBookkeepingPool.push(instance);
4113 }
4114}
4115
4116function handleTopLevel(bookKeeping) {
4117 var targetInst = bookKeeping.targetInst;
4118
4119 // Loop through the hierarchy, in case there's any nested components.
4120 // It's important that we build the array of ancestors before calling any
4121 // event handlers, because event handlers can modify the DOM, leading to
4122 // inconsistencies with ReactMount's node cache. See #1105.
4123 var ancestor = targetInst;
4124 do {
4125 if (!ancestor) {
4126 bookKeeping.ancestors.push(ancestor);
4127 break;
4128 }
4129 var root = findRootContainerNode(ancestor);
4130 if (!root) {
4131 break;
4132 }
4133 bookKeeping.ancestors.push(ancestor);
4134 ancestor = getClosestInstanceFromNode(root);
4135 } while (ancestor);
4136
4137 for (var i = 0; i < bookKeeping.ancestors.length; i++) {
4138 targetInst = bookKeeping.ancestors[i];
4139 runExtractedEventsInBatch(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));
4140 }
4141}
4142
4143// TODO: can we stop exporting these?
4144var _enabled = true;
4145
4146function setEnabled(enabled) {
4147 _enabled = !!enabled;
4148}
4149
4150function isEnabled() {
4151 return _enabled;
4152}
4153
4154/**
4155 * Traps top-level events by using event bubbling.
4156 *
4157 * @param {string} topLevelType Record from `BrowserEventConstants`.
4158 * @param {string} handlerBaseName Event name (e.g. "click").
4159 * @param {object} element Element on which to attach listener.
4160 * @return {?object} An object with a remove function which will forcefully
4161 * remove the listener.
4162 * @internal
4163 */
4164function trapBubbledEvent(topLevelType, handlerBaseName, element) {
4165 if (!element) {
4166 return null;
4167 }
4168 addEventBubbleListener(element, handlerBaseName, dispatchEvent.bind(null, topLevelType));
4169}
4170
4171/**
4172 * Traps a top-level event by using event capturing.
4173 *
4174 * @param {string} topLevelType Record from `BrowserEventConstants`.
4175 * @param {string} handlerBaseName Event name (e.g. "click").
4176 * @param {object} element Element on which to attach listener.
4177 * @return {?object} An object with a remove function which will forcefully
4178 * remove the listener.
4179 * @internal
4180 */
4181function trapCapturedEvent(topLevelType, handlerBaseName, element) {
4182 if (!element) {
4183 return null;
4184 }
4185 addEventCaptureListener(element, handlerBaseName, dispatchEvent.bind(null, topLevelType));
4186}
4187
4188function dispatchEvent(topLevelType, nativeEvent) {
4189 if (!_enabled) {
4190 return;
4191 }
4192
4193 var nativeEventTarget = getEventTarget(nativeEvent);
4194 var targetInst = getClosestInstanceFromNode(nativeEventTarget);
4195 if (targetInst !== null && typeof targetInst.tag === 'number' && !isFiberMounted(targetInst)) {
4196 // If we get an event (ex: img onload) before committing that
4197 // component's mount, ignore it for now (that is, treat it as if it was an
4198 // event on a non-React tree). We might also consider queueing events and
4199 // dispatching them after the mount.
4200 targetInst = null;
4201 }
4202
4203 var bookKeeping = getTopLevelCallbackBookKeeping(topLevelType, nativeEvent, targetInst);
4204
4205 try {
4206 // Event queue being processed in the same cycle allows
4207 // `preventDefault`.
4208 batchedUpdates(handleTopLevel, bookKeeping);
4209 } finally {
4210 releaseTopLevelCallbackBookKeeping(bookKeeping);
4211 }
4212}
4213
4214var ReactDOMEventListener = Object.freeze({
4215 get _enabled () { return _enabled; },
4216 setEnabled: setEnabled,
4217 isEnabled: isEnabled,
4218 trapBubbledEvent: trapBubbledEvent,
4219 trapCapturedEvent: trapCapturedEvent,
4220 dispatchEvent: dispatchEvent
4221});
4222
4223/**
4224 * Generate a mapping of standard vendor prefixes using the defined style property and event name.
4225 *
4226 * @param {string} styleProp
4227 * @param {string} eventName
4228 * @returns {object}
4229 */
4230function makePrefixMap(styleProp, eventName) {
4231 var prefixes = {};
4232
4233 prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
4234 prefixes['Webkit' + styleProp] = 'webkit' + eventName;
4235 prefixes['Moz' + styleProp] = 'moz' + eventName;
4236 prefixes['ms' + styleProp] = 'MS' + eventName;
4237 prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();
4238
4239 return prefixes;
4240}
4241
4242/**
4243 * A list of event names to a configurable list of vendor prefixes.
4244 */
4245var vendorPrefixes = {
4246 animationend: makePrefixMap('Animation', 'AnimationEnd'),
4247 animationiteration: makePrefixMap('Animation', 'AnimationIteration'),
4248 animationstart: makePrefixMap('Animation', 'AnimationStart'),
4249 transitionend: makePrefixMap('Transition', 'TransitionEnd')
4250};
4251
4252/**
4253 * Event names that have already been detected and prefixed (if applicable).
4254 */
4255var prefixedEventNames = {};
4256
4257/**
4258 * Element to check for prefixes on.
4259 */
4260var style = {};
4261
4262/**
4263 * Bootstrap if a DOM exists.
4264 */
4265if (ExecutionEnvironment_1.canUseDOM) {
4266 style = document.createElement('div').style;
4267
4268 // On some platforms, in particular some releases of Android 4.x,
4269 // the un-prefixed "animation" and "transition" properties are defined on the
4270 // style object but the events that fire will still be prefixed, so we need
4271 // to check if the un-prefixed events are usable, and if not remove them from the map.
4272 if (!('AnimationEvent' in window)) {
4273 delete vendorPrefixes.animationend.animation;
4274 delete vendorPrefixes.animationiteration.animation;
4275 delete vendorPrefixes.animationstart.animation;
4276 }
4277
4278 // Same as above
4279 if (!('TransitionEvent' in window)) {
4280 delete vendorPrefixes.transitionend.transition;
4281 }
4282}
4283
4284/**
4285 * Attempts to determine the correct vendor prefixed event name.
4286 *
4287 * @param {string} eventName
4288 * @returns {string}
4289 */
4290function getVendorPrefixedEventName(eventName) {
4291 if (prefixedEventNames[eventName]) {
4292 return prefixedEventNames[eventName];
4293 } else if (!vendorPrefixes[eventName]) {
4294 return eventName;
4295 }
4296
4297 var prefixMap = vendorPrefixes[eventName];
4298
4299 for (var styleProp in prefixMap) {
4300 if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {
4301 return prefixedEventNames[eventName] = prefixMap[styleProp];
4302 }
4303 }
4304
4305 return eventName;
4306}
4307
4308/**
4309 * Types of raw signals from the browser caught at the top level.
4310 *
4311 * For events like 'submit' which don't consistently bubble (which we
4312 * trap at a lower node than `document`), binding at `document` would
4313 * cause duplicate events so we don't include them here.
4314 */
4315var topLevelTypes$1 = {
4316 topAbort: 'abort',
4317 topAnimationEnd: getVendorPrefixedEventName('animationend'),
4318 topAnimationIteration: getVendorPrefixedEventName('animationiteration'),
4319 topAnimationStart: getVendorPrefixedEventName('animationstart'),
4320 topBlur: 'blur',
4321 topCancel: 'cancel',
4322 topCanPlay: 'canplay',
4323 topCanPlayThrough: 'canplaythrough',
4324 topChange: 'change',
4325 topClick: 'click',
4326 topClose: 'close',
4327 topCompositionEnd: 'compositionend',
4328 topCompositionStart: 'compositionstart',
4329 topCompositionUpdate: 'compositionupdate',
4330 topContextMenu: 'contextmenu',
4331 topCopy: 'copy',
4332 topCut: 'cut',
4333 topDoubleClick: 'dblclick',
4334 topDrag: 'drag',
4335 topDragEnd: 'dragend',
4336 topDragEnter: 'dragenter',
4337 topDragExit: 'dragexit',
4338 topDragLeave: 'dragleave',
4339 topDragOver: 'dragover',
4340 topDragStart: 'dragstart',
4341 topDrop: 'drop',
4342 topDurationChange: 'durationchange',
4343 topEmptied: 'emptied',
4344 topEncrypted: 'encrypted',
4345 topEnded: 'ended',
4346 topError: 'error',
4347 topFocus: 'focus',
4348 topInput: 'input',
4349 topKeyDown: 'keydown',
4350 topKeyPress: 'keypress',
4351 topKeyUp: 'keyup',
4352 topLoadedData: 'loadeddata',
4353 topLoad: 'load',
4354 topLoadedMetadata: 'loadedmetadata',
4355 topLoadStart: 'loadstart',
4356 topMouseDown: 'mousedown',
4357 topMouseMove: 'mousemove',
4358 topMouseOut: 'mouseout',
4359 topMouseOver: 'mouseover',
4360 topMouseUp: 'mouseup',
4361 topPaste: 'paste',
4362 topPause: 'pause',
4363 topPlay: 'play',
4364 topPlaying: 'playing',
4365 topProgress: 'progress',
4366 topRateChange: 'ratechange',
4367 topScroll: 'scroll',
4368 topSeeked: 'seeked',
4369 topSeeking: 'seeking',
4370 topSelectionChange: 'selectionchange',
4371 topStalled: 'stalled',
4372 topSuspend: 'suspend',
4373 topTextInput: 'textInput',
4374 topTimeUpdate: 'timeupdate',
4375 topToggle: 'toggle',
4376 topTouchCancel: 'touchcancel',
4377 topTouchEnd: 'touchend',
4378 topTouchMove: 'touchmove',
4379 topTouchStart: 'touchstart',
4380 topTransitionEnd: getVendorPrefixedEventName('transitionend'),
4381 topVolumeChange: 'volumechange',
4382 topWaiting: 'waiting',
4383 topWheel: 'wheel'
4384};
4385
4386var BrowserEventConstants = {
4387 topLevelTypes: topLevelTypes$1
4388};
4389
4390var topLevelTypes = BrowserEventConstants.topLevelTypes;
4391
4392/**
4393 * Summary of `ReactBrowserEventEmitter` event handling:
4394 *
4395 * - Top-level delegation is used to trap most native browser events. This
4396 * may only occur in the main thread and is the responsibility of
4397 * ReactDOMEventListener, which is injected and can therefore support
4398 * pluggable event sources. This is the only work that occurs in the main
4399 * thread.
4400 *
4401 * - We normalize and de-duplicate events to account for browser quirks. This
4402 * may be done in the worker thread.
4403 *
4404 * - Forward these native events (with the associated top-level type used to
4405 * trap it) to `EventPluginHub`, which in turn will ask plugins if they want
4406 * to extract any synthetic events.
4407 *
4408 * - The `EventPluginHub` will then process each event by annotating them with
4409 * "dispatches", a sequence of listeners and IDs that care about that event.
4410 *
4411 * - The `EventPluginHub` then dispatches the events.
4412 *
4413 * Overview of React and the event system:
4414 *
4415 * +------------+ .
4416 * | DOM | .
4417 * +------------+ .
4418 * | .
4419 * v .
4420 * +------------+ .
4421 * | ReactEvent | .
4422 * | Listener | .
4423 * +------------+ . +-----------+
4424 * | . +--------+|SimpleEvent|
4425 * | . | |Plugin |
4426 * +-----|------+ . v +-----------+
4427 * | | | . +--------------+ +------------+
4428 * | +-----------.--->|EventPluginHub| | Event |
4429 * | | . | | +-----------+ | Propagators|
4430 * | ReactEvent | . | | |TapEvent | |------------|
4431 * | Emitter | . | |<---+|Plugin | |other plugin|
4432 * | | . | | +-----------+ | utilities |
4433 * | +-----------.--->| | +------------+
4434 * | | | . +--------------+
4435 * +-----|------+ . ^ +-----------+
4436 * | . | |Enter/Leave|
4437 * + . +-------+|Plugin |
4438 * +-------------+ . +-----------+
4439 * | application | .
4440 * |-------------| .
4441 * | | .
4442 * | | .
4443 * +-------------+ .
4444 * .
4445 * React Core . General Purpose Event Plugin System
4446 */
4447
4448var alreadyListeningTo = {};
4449var reactTopListenersCounter = 0;
4450
4451/**
4452 * To ensure no conflicts with other potential React instances on the page
4453 */
4454var topListenersIDKey = '_reactListenersID' + ('' + Math.random()).slice(2);
4455
4456function getListeningForDocument(mountAt) {
4457 // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
4458 // directly.
4459 if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
4460 mountAt[topListenersIDKey] = reactTopListenersCounter++;
4461 alreadyListeningTo[mountAt[topListenersIDKey]] = {};
4462 }
4463 return alreadyListeningTo[mountAt[topListenersIDKey]];
4464}
4465
4466/**
4467 * We listen for bubbled touch events on the document object.
4468 *
4469 * Firefox v8.01 (and possibly others) exhibited strange behavior when
4470 * mounting `onmousemove` events at some node that was not the document
4471 * element. The symptoms were that if your mouse is not moving over something
4472 * contained within that mount point (for example on the background) the
4473 * top-level listeners for `onmousemove` won't be called. However, if you
4474 * register the `mousemove` on the document object, then it will of course
4475 * catch all `mousemove`s. This along with iOS quirks, justifies restricting
4476 * top-level listeners to the document object only, at least for these
4477 * movement types of events and possibly all events.
4478 *
4479 * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
4480 *
4481 * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
4482 * they bubble to document.
4483 *
4484 * @param {string} registrationName Name of listener (e.g. `onClick`).
4485 * @param {object} contentDocumentHandle Document which owns the container
4486 */
4487function listenTo(registrationName, contentDocumentHandle) {
4488 var mountAt = contentDocumentHandle;
4489 var isListening = getListeningForDocument(mountAt);
4490 var dependencies = registrationNameDependencies[registrationName];
4491
4492 for (var i = 0; i < dependencies.length; i++) {
4493 var dependency = dependencies[i];
4494 if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
4495 if (dependency === 'topScroll') {
4496 trapCapturedEvent('topScroll', 'scroll', mountAt);
4497 } else if (dependency === 'topFocus' || dependency === 'topBlur') {
4498 trapCapturedEvent('topFocus', 'focus', mountAt);
4499 trapCapturedEvent('topBlur', 'blur', mountAt);
4500
4501 // to make sure blur and focus event listeners are only attached once
4502 isListening.topBlur = true;
4503 isListening.topFocus = true;
4504 } else if (dependency === 'topCancel') {
4505 if (isEventSupported('cancel', true)) {
4506 trapCapturedEvent('topCancel', 'cancel', mountAt);
4507 }
4508 isListening.topCancel = true;
4509 } else if (dependency === 'topClose') {
4510 if (isEventSupported('close', true)) {
4511 trapCapturedEvent('topClose', 'close', mountAt);
4512 }
4513 isListening.topClose = true;
4514 } else if (topLevelTypes.hasOwnProperty(dependency)) {
4515 trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt);
4516 }
4517
4518 isListening[dependency] = true;
4519 }
4520 }
4521}
4522
4523function isListeningToAllDependencies(registrationName, mountAt) {
4524 var isListening = getListeningForDocument(mountAt);
4525 var dependencies = registrationNameDependencies[registrationName];
4526 for (var i = 0; i < dependencies.length; i++) {
4527 var dependency = dependencies[i];
4528 if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
4529 return false;
4530 }
4531 }
4532 return true;
4533}
4534
4535/**
4536 * Copyright (c) 2013-present, Facebook, Inc.
4537 *
4538 * This source code is licensed under the MIT license found in the
4539 * LICENSE file in the root directory of this source tree.
4540 *
4541 * @typechecks
4542 */
4543
4544/**
4545 * @param {*} object The object to check.
4546 * @return {boolean} Whether or not the object is a DOM node.
4547 */
4548function isNode(object) {
4549 var doc = object ? object.ownerDocument || object : document;
4550 var defaultView = doc.defaultView || window;
4551 return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
4552}
4553
4554var isNode_1 = isNode;
4555
4556/**
4557 * Copyright (c) 2013-present, Facebook, Inc.
4558 *
4559 * This source code is licensed under the MIT license found in the
4560 * LICENSE file in the root directory of this source tree.
4561 *
4562 * @typechecks
4563 */
4564
4565
4566
4567/**
4568 * @param {*} object The object to check.
4569 * @return {boolean} Whether or not the object is a DOM text node.
4570 */
4571function isTextNode(object) {
4572 return isNode_1(object) && object.nodeType == 3;
4573}
4574
4575var isTextNode_1 = isTextNode;
4576
4577/**
4578 * Copyright (c) 2013-present, Facebook, Inc.
4579 *
4580 * This source code is licensed under the MIT license found in the
4581 * LICENSE file in the root directory of this source tree.
4582 *
4583 *
4584 */
4585
4586
4587
4588/*eslint-disable no-bitwise */
4589
4590/**
4591 * Checks if a given DOM node contains or is another DOM node.
4592 */
4593function containsNode(outerNode, innerNode) {
4594 if (!outerNode || !innerNode) {
4595 return false;
4596 } else if (outerNode === innerNode) {
4597 return true;
4598 } else if (isTextNode_1(outerNode)) {
4599 return false;
4600 } else if (isTextNode_1(innerNode)) {
4601 return containsNode(outerNode, innerNode.parentNode);
4602 } else if ('contains' in outerNode) {
4603 return outerNode.contains(innerNode);
4604 } else if (outerNode.compareDocumentPosition) {
4605 return !!(outerNode.compareDocumentPosition(innerNode) & 16);
4606 } else {
4607 return false;
4608 }
4609}
4610
4611var containsNode_1 = containsNode;
4612
4613/**
4614 * Given any node return the first leaf node without children.
4615 *
4616 * @param {DOMElement|DOMTextNode} node
4617 * @return {DOMElement|DOMTextNode}
4618 */
4619function getLeafNode(node) {
4620 while (node && node.firstChild) {
4621 node = node.firstChild;
4622 }
4623 return node;
4624}
4625
4626/**
4627 * Get the next sibling within a container. This will walk up the
4628 * DOM if a node's siblings have been exhausted.
4629 *
4630 * @param {DOMElement|DOMTextNode} node
4631 * @return {?DOMElement|DOMTextNode}
4632 */
4633function getSiblingNode(node) {
4634 while (node) {
4635 if (node.nextSibling) {
4636 return node.nextSibling;
4637 }
4638 node = node.parentNode;
4639 }
4640}
4641
4642/**
4643 * Get object describing the nodes which contain characters at offset.
4644 *
4645 * @param {DOMElement|DOMTextNode} root
4646 * @param {number} offset
4647 * @return {?object}
4648 */
4649function getNodeForCharacterOffset(root, offset) {
4650 var node = getLeafNode(root);
4651 var nodeStart = 0;
4652 var nodeEnd = 0;
4653
4654 while (node) {
4655 if (node.nodeType === TEXT_NODE) {
4656 nodeEnd = nodeStart + node.textContent.length;
4657
4658 if (nodeStart <= offset && nodeEnd >= offset) {
4659 return {
4660 node: node,
4661 offset: offset - nodeStart
4662 };
4663 }
4664
4665 nodeStart = nodeEnd;
4666 }
4667
4668 node = getLeafNode(getSiblingNode(node));
4669 }
4670}
4671
4672/**
4673 * @param {DOMElement} outerNode
4674 * @return {?object}
4675 */
4676function getOffsets(outerNode) {
4677 var selection = window.getSelection && window.getSelection();
4678
4679 if (!selection || selection.rangeCount === 0) {
4680 return null;
4681 }
4682
4683 var anchorNode = selection.anchorNode,
4684 anchorOffset = selection.anchorOffset,
4685 focusNode = selection.focusNode,
4686 focusOffset = selection.focusOffset;
4687
4688 // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the
4689 // up/down buttons on an <input type="number">. Anonymous divs do not seem to
4690 // expose properties, triggering a "Permission denied error" if any of its
4691 // properties are accessed. The only seemingly possible way to avoid erroring
4692 // is to access a property that typically works for non-anonymous divs and
4693 // catch any error that may otherwise arise. See
4694 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
4695
4696 try {
4697 /* eslint-disable no-unused-expressions */
4698 anchorNode.nodeType;
4699 focusNode.nodeType;
4700 /* eslint-enable no-unused-expressions */
4701 } catch (e) {
4702 return null;
4703 }
4704
4705 return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset);
4706}
4707
4708/**
4709 * Returns {start, end} where `start` is the character/codepoint index of
4710 * (anchorNode, anchorOffset) within the textContent of `outerNode`, and
4711 * `end` is the index of (focusNode, focusOffset).
4712 *
4713 * Returns null if you pass in garbage input but we should probably just crash.
4714 *
4715 * Exported only for testing.
4716 */
4717function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) {
4718 var length = 0;
4719 var start = -1;
4720 var end = -1;
4721 var indexWithinAnchor = 0;
4722 var indexWithinFocus = 0;
4723 var node = outerNode;
4724 var parentNode = null;
4725
4726 outer: while (true) {
4727 var next = null;
4728
4729 while (true) {
4730 if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) {
4731 start = length + anchorOffset;
4732 }
4733 if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) {
4734 end = length + focusOffset;
4735 }
4736
4737 if (node.nodeType === TEXT_NODE) {
4738 length += node.nodeValue.length;
4739 }
4740
4741 if ((next = node.firstChild) === null) {
4742 break;
4743 }
4744 // Moving from `node` to its first child `next`.
4745 parentNode = node;
4746 node = next;
4747 }
4748
4749 while (true) {
4750 if (node === outerNode) {
4751 // If `outerNode` has children, this is always the second time visiting
4752 // it. If it has no children, this is still the first loop, and the only
4753 // valid selection is anchorNode and focusNode both equal to this node
4754 // and both offsets 0, in which case we will have handled above.
4755 break outer;
4756 }
4757 if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) {
4758 start = length;
4759 }
4760 if (parentNode === focusNode && ++indexWithinFocus === focusOffset) {
4761 end = length;
4762 }
4763 if ((next = node.nextSibling) !== null) {
4764 break;
4765 }
4766 node = parentNode;
4767 parentNode = node.parentNode;
4768 }
4769
4770 // Moving from `node` to its next sibling `next`.
4771 node = next;
4772 }
4773
4774 if (start === -1 || end === -1) {
4775 // This should never happen. (Would happen if the anchor/focus nodes aren't
4776 // actually inside the passed-in node.)
4777 return null;
4778 }
4779
4780 return {
4781 start: start,
4782 end: end
4783 };
4784}
4785
4786/**
4787 * In modern non-IE browsers, we can support both forward and backward
4788 * selections.
4789 *
4790 * Note: IE10+ supports the Selection object, but it does not support
4791 * the `extend` method, which means that even in modern IE, it's not possible
4792 * to programmatically create a backward selection. Thus, for all IE
4793 * versions, we use the old IE API to create our selections.
4794 *
4795 * @param {DOMElement|DOMTextNode} node
4796 * @param {object} offsets
4797 */
4798function setOffsets(node, offsets) {
4799 if (!window.getSelection) {
4800 return;
4801 }
4802
4803 var selection = window.getSelection();
4804 var length = node[getTextContentAccessor()].length;
4805 var start = Math.min(offsets.start, length);
4806 var end = offsets.end === undefined ? start : Math.min(offsets.end, length);
4807
4808 // IE 11 uses modern selection, but doesn't support the extend method.
4809 // Flip backward selections, so we can set with a single range.
4810 if (!selection.extend && start > end) {
4811 var temp = end;
4812 end = start;
4813 start = temp;
4814 }
4815
4816 var startMarker = getNodeForCharacterOffset(node, start);
4817 var endMarker = getNodeForCharacterOffset(node, end);
4818
4819 if (startMarker && endMarker) {
4820 if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) {
4821 return;
4822 }
4823 var range = document.createRange();
4824 range.setStart(startMarker.node, startMarker.offset);
4825 selection.removeAllRanges();
4826
4827 if (start > end) {
4828 selection.addRange(range);
4829 selection.extend(endMarker.node, endMarker.offset);
4830 } else {
4831 range.setEnd(endMarker.node, endMarker.offset);
4832 selection.addRange(range);
4833 }
4834 }
4835}
4836
4837function isInDocument(node) {
4838 return containsNode_1(document.documentElement, node);
4839}
4840
4841/**
4842 * @ReactInputSelection: React input selection module. Based on Selection.js,
4843 * but modified to be suitable for react and has a couple of bug fixes (doesn't
4844 * assume buttons have range selections allowed).
4845 * Input selection module for React.
4846 */
4847
4848function hasSelectionCapabilities(elem) {
4849 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
4850 return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');
4851}
4852
4853function getSelectionInformation() {
4854 var focusedElem = getActiveElement_1();
4855 return {
4856 focusedElem: focusedElem,
4857 selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection$1(focusedElem) : null
4858 };
4859}
4860
4861/**
4862 * @restoreSelection: If any selection information was potentially lost,
4863 * restore it. This is useful when performing operations that could remove dom
4864 * nodes and place them back in, resulting in focus being lost.
4865 */
4866function restoreSelection(priorSelectionInformation) {
4867 var curFocusedElem = getActiveElement_1();
4868 var priorFocusedElem = priorSelectionInformation.focusedElem;
4869 var priorSelectionRange = priorSelectionInformation.selectionRange;
4870 if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
4871 if (hasSelectionCapabilities(priorFocusedElem)) {
4872 setSelection(priorFocusedElem, priorSelectionRange);
4873 }
4874
4875 // Focusing a node can change the scroll position, which is undesirable
4876 var ancestors = [];
4877 var ancestor = priorFocusedElem;
4878 while (ancestor = ancestor.parentNode) {
4879 if (ancestor.nodeType === ELEMENT_NODE) {
4880 ancestors.push({
4881 element: ancestor,
4882 left: ancestor.scrollLeft,
4883 top: ancestor.scrollTop
4884 });
4885 }
4886 }
4887
4888 priorFocusedElem.focus();
4889
4890 for (var i = 0; i < ancestors.length; i++) {
4891 var info = ancestors[i];
4892 info.element.scrollLeft = info.left;
4893 info.element.scrollTop = info.top;
4894 }
4895 }
4896}
4897
4898/**
4899 * @getSelection: Gets the selection bounds of a focused textarea, input or
4900 * contentEditable node.
4901 * -@input: Look up selection bounds of this input
4902 * -@return {start: selectionStart, end: selectionEnd}
4903 */
4904function getSelection$1(input) {
4905 var selection = void 0;
4906
4907 if ('selectionStart' in input) {
4908 // Modern browser with input or textarea.
4909 selection = {
4910 start: input.selectionStart,
4911 end: input.selectionEnd
4912 };
4913 } else {
4914 // Content editable or old IE textarea.
4915 selection = getOffsets(input);
4916 }
4917
4918 return selection || { start: 0, end: 0 };
4919}
4920
4921/**
4922 * @setSelection: Sets the selection bounds of a textarea or input and focuses
4923 * the input.
4924 * -@input Set selection bounds of this input or textarea
4925 * -@offsets Object of same form that is returned from get*
4926 */
4927function setSelection(input, offsets) {
4928 var start = offsets.start,
4929 end = offsets.end;
4930
4931 if (end === undefined) {
4932 end = start;
4933 }
4934
4935 if ('selectionStart' in input) {
4936 input.selectionStart = start;
4937 input.selectionEnd = Math.min(end, input.value.length);
4938 } else {
4939 setOffsets(input, offsets);
4940 }
4941}
4942
4943var skipSelectionChangeEvent = ExecutionEnvironment_1.canUseDOM && 'documentMode' in document && document.documentMode <= 11;
4944
4945var eventTypes$3 = {
4946 select: {
4947 phasedRegistrationNames: {
4948 bubbled: 'onSelect',
4949 captured: 'onSelectCapture'
4950 },
4951 dependencies: ['topBlur', 'topContextMenu', 'topFocus', 'topKeyDown', 'topKeyUp', 'topMouseDown', 'topMouseUp', 'topSelectionChange']
4952 }
4953};
4954
4955var activeElement$1 = null;
4956var activeElementInst$1 = null;
4957var lastSelection = null;
4958var mouseDown = false;
4959
4960/**
4961 * Get an object which is a unique representation of the current selection.
4962 *
4963 * The return value will not be consistent across nodes or browsers, but
4964 * two identical selections on the same node will return identical objects.
4965 *
4966 * @param {DOMElement} node
4967 * @return {object}
4968 */
4969function getSelection(node) {
4970 if ('selectionStart' in node && hasSelectionCapabilities(node)) {
4971 return {
4972 start: node.selectionStart,
4973 end: node.selectionEnd
4974 };
4975 } else if (window.getSelection) {
4976 var selection = window.getSelection();
4977 return {
4978 anchorNode: selection.anchorNode,
4979 anchorOffset: selection.anchorOffset,
4980 focusNode: selection.focusNode,
4981 focusOffset: selection.focusOffset
4982 };
4983 }
4984}
4985
4986/**
4987 * Poll selection to see whether it's changed.
4988 *
4989 * @param {object} nativeEvent
4990 * @return {?SyntheticEvent}
4991 */
4992function constructSelectEvent(nativeEvent, nativeEventTarget) {
4993 // Ensure we have the right element, and that the user is not dragging a
4994 // selection (this matches native `select` event behavior). In HTML5, select
4995 // fires only on input and textarea thus if there's no focused element we
4996 // won't dispatch.
4997 if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement_1()) {
4998 return null;
4999 }
5000
5001 // Only fire when selection has actually changed.
5002 var currentSelection = getSelection(activeElement$1);
5003 if (!lastSelection || !shallowEqual_1(lastSelection, currentSelection)) {
5004 lastSelection = currentSelection;
5005
5006 var syntheticEvent = SyntheticEvent$1.getPooled(eventTypes$3.select, activeElementInst$1, nativeEvent, nativeEventTarget);
5007
5008 syntheticEvent.type = 'select';
5009 syntheticEvent.target = activeElement$1;
5010
5011 accumulateTwoPhaseDispatches(syntheticEvent);
5012
5013 return syntheticEvent;
5014 }
5015
5016 return null;
5017}
5018
5019/**
5020 * This plugin creates an `onSelect` event that normalizes select events
5021 * across form elements.
5022 *
5023 * Supported elements are:
5024 * - input (see `isTextInputElement`)
5025 * - textarea
5026 * - contentEditable
5027 *
5028 * This differs from native browser implementations in the following ways:
5029 * - Fires on contentEditable fields as well as inputs.
5030 * - Fires for collapsed selection.
5031 * - Fires after user input.
5032 */
5033var SelectEventPlugin = {
5034 eventTypes: eventTypes$3,
5035
5036 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
5037 var doc = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget.document : nativeEventTarget.nodeType === DOCUMENT_NODE ? nativeEventTarget : nativeEventTarget.ownerDocument;
5038 // Track whether all listeners exists for this plugin. If none exist, we do
5039 // not extract events. See #3639.
5040 if (!doc || !isListeningToAllDependencies('onSelect', doc)) {
5041 return null;
5042 }
5043
5044 var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
5045
5046 switch (topLevelType) {
5047 // Track the input node that has focus.
5048 case 'topFocus':
5049 if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {
5050 activeElement$1 = targetNode;
5051 activeElementInst$1 = targetInst;
5052 lastSelection = null;
5053 }
5054 break;
5055 case 'topBlur':
5056 activeElement$1 = null;
5057 activeElementInst$1 = null;
5058 lastSelection = null;
5059 break;
5060 // Don't fire the event while the user is dragging. This matches the
5061 // semantics of the native select event.
5062 case 'topMouseDown':
5063 mouseDown = true;
5064 break;
5065 case 'topContextMenu':
5066 case 'topMouseUp':
5067 mouseDown = false;
5068 return constructSelectEvent(nativeEvent, nativeEventTarget);
5069 // Chrome and IE fire non-standard event when selection is changed (and
5070 // sometimes when it hasn't). IE's event fires out of order with respect
5071 // to key and input events on deletion, so we discard it.
5072 //
5073 // Firefox doesn't support selectionchange, so check selection status
5074 // after each key entry. The selection changes after keydown and before
5075 // keyup, but we check on keydown as well in the case of holding down a
5076 // key, when multiple keydown events are fired but only one keyup is.
5077 // This is also our approach for IE handling, for the reason above.
5078 case 'topSelectionChange':
5079 if (skipSelectionChangeEvent) {
5080 break;
5081 }
5082 // falls through
5083 case 'topKeyDown':
5084 case 'topKeyUp':
5085 return constructSelectEvent(nativeEvent, nativeEventTarget);
5086 }
5087
5088 return null;
5089 }
5090};
5091
5092/**
5093 * @interface Event
5094 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
5095 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
5096 */
5097var SyntheticAnimationEvent = SyntheticEvent$1.extend({
5098 animationName: null,
5099 elapsedTime: null,
5100 pseudoElement: null
5101});
5102
5103/**
5104 * @interface Event
5105 * @see http://www.w3.org/TR/clipboard-apis/
5106 */
5107var SyntheticClipboardEvent = SyntheticEvent$1.extend({
5108 clipboardData: function (event) {
5109 return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
5110 }
5111});
5112
5113/**
5114 * @interface FocusEvent
5115 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5116 */
5117var SyntheticFocusEvent = SyntheticUIEvent.extend({
5118 relatedTarget: null
5119});
5120
5121/**
5122 * `charCode` represents the actual "character code" and is safe to use with
5123 * `String.fromCharCode`. As such, only keys that correspond to printable
5124 * characters produce a valid `charCode`, the only exception to this is Enter.
5125 * The Tab-key is considered non-printable and does not have a `charCode`,
5126 * presumably because it does not produce a tab-character in browsers.
5127 *
5128 * @param {object} nativeEvent Native browser event.
5129 * @return {number} Normalized `charCode` property.
5130 */
5131function getEventCharCode(nativeEvent) {
5132 var charCode = void 0;
5133 var keyCode = nativeEvent.keyCode;
5134
5135 if ('charCode' in nativeEvent) {
5136 charCode = nativeEvent.charCode;
5137
5138 // FF does not set `charCode` for the Enter-key, check against `keyCode`.
5139 if (charCode === 0 && keyCode === 13) {
5140 charCode = 13;
5141 }
5142 } else {
5143 // IE8 does not implement `charCode`, but `keyCode` has the correct value.
5144 charCode = keyCode;
5145 }
5146
5147 // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux)
5148 // report Enter as charCode 10 when ctrl is pressed.
5149 if (charCode === 10) {
5150 charCode = 13;
5151 }
5152
5153 // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
5154 // Must not discard the (non-)printable Enter-key.
5155 if (charCode >= 32 || charCode === 13) {
5156 return charCode;
5157 }
5158
5159 return 0;
5160}
5161
5162/**
5163 * Normalization of deprecated HTML5 `key` values
5164 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
5165 */
5166var normalizeKey = {
5167 Esc: 'Escape',
5168 Spacebar: ' ',
5169 Left: 'ArrowLeft',
5170 Up: 'ArrowUp',
5171 Right: 'ArrowRight',
5172 Down: 'ArrowDown',
5173 Del: 'Delete',
5174 Win: 'OS',
5175 Menu: 'ContextMenu',
5176 Apps: 'ContextMenu',
5177 Scroll: 'ScrollLock',
5178 MozPrintableKey: 'Unidentified'
5179};
5180
5181/**
5182 * Translation from legacy `keyCode` to HTML5 `key`
5183 * Only special keys supported, all others depend on keyboard layout or browser
5184 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
5185 */
5186var translateToKey = {
5187 '8': 'Backspace',
5188 '9': 'Tab',
5189 '12': 'Clear',
5190 '13': 'Enter',
5191 '16': 'Shift',
5192 '17': 'Control',
5193 '18': 'Alt',
5194 '19': 'Pause',
5195 '20': 'CapsLock',
5196 '27': 'Escape',
5197 '32': ' ',
5198 '33': 'PageUp',
5199 '34': 'PageDown',
5200 '35': 'End',
5201 '36': 'Home',
5202 '37': 'ArrowLeft',
5203 '38': 'ArrowUp',
5204 '39': 'ArrowRight',
5205 '40': 'ArrowDown',
5206 '45': 'Insert',
5207 '46': 'Delete',
5208 '112': 'F1',
5209 '113': 'F2',
5210 '114': 'F3',
5211 '115': 'F4',
5212 '116': 'F5',
5213 '117': 'F6',
5214 '118': 'F7',
5215 '119': 'F8',
5216 '120': 'F9',
5217 '121': 'F10',
5218 '122': 'F11',
5219 '123': 'F12',
5220 '144': 'NumLock',
5221 '145': 'ScrollLock',
5222 '224': 'Meta'
5223};
5224
5225/**
5226 * @param {object} nativeEvent Native browser event.
5227 * @return {string} Normalized `key` property.
5228 */
5229function getEventKey(nativeEvent) {
5230 if (nativeEvent.key) {
5231 // Normalize inconsistent values reported by browsers due to
5232 // implementations of a working draft specification.
5233
5234 // FireFox implements `key` but returns `MozPrintableKey` for all
5235 // printable characters (normalized to `Unidentified`), ignore it.
5236 var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
5237 if (key !== 'Unidentified') {
5238 return key;
5239 }
5240 }
5241
5242 // Browser does not implement `key`, polyfill as much of it as we can.
5243 if (nativeEvent.type === 'keypress') {
5244 var charCode = getEventCharCode(nativeEvent);
5245
5246 // The enter-key is technically both printable and non-printable and can
5247 // thus be captured by `keypress`, no other non-printable key should.
5248 return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
5249 }
5250 if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
5251 // While user keyboard layout determines the actual meaning of each
5252 // `keyCode` value, almost all function keys have a universal value.
5253 return translateToKey[nativeEvent.keyCode] || 'Unidentified';
5254 }
5255 return '';
5256}
5257
5258/**
5259 * @interface KeyboardEvent
5260 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5261 */
5262var SyntheticKeyboardEvent = SyntheticUIEvent.extend({
5263 key: getEventKey,
5264 location: null,
5265 ctrlKey: null,
5266 shiftKey: null,
5267 altKey: null,
5268 metaKey: null,
5269 repeat: null,
5270 locale: null,
5271 getModifierState: getEventModifierState,
5272 // Legacy Interface
5273 charCode: function (event) {
5274 // `charCode` is the result of a KeyPress event and represents the value of
5275 // the actual printable character.
5276
5277 // KeyPress is deprecated, but its replacement is not yet final and not
5278 // implemented in any major browser. Only KeyPress has charCode.
5279 if (event.type === 'keypress') {
5280 return getEventCharCode(event);
5281 }
5282 return 0;
5283 },
5284 keyCode: function (event) {
5285 // `keyCode` is the result of a KeyDown/Up event and represents the value of
5286 // physical keyboard key.
5287
5288 // The actual meaning of the value depends on the users' keyboard layout
5289 // which cannot be detected. Assuming that it is a US keyboard layout
5290 // provides a surprisingly accurate mapping for US and European users.
5291 // Due to this, it is left to the user to implement at this time.
5292 if (event.type === 'keydown' || event.type === 'keyup') {
5293 return event.keyCode;
5294 }
5295 return 0;
5296 },
5297 which: function (event) {
5298 // `which` is an alias for either `keyCode` or `charCode` depending on the
5299 // type of the event.
5300 if (event.type === 'keypress') {
5301 return getEventCharCode(event);
5302 }
5303 if (event.type === 'keydown' || event.type === 'keyup') {
5304 return event.keyCode;
5305 }
5306 return 0;
5307 }
5308});
5309
5310/**
5311 * @interface DragEvent
5312 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5313 */
5314var SyntheticDragEvent = SyntheticMouseEvent.extend({
5315 dataTransfer: null
5316});
5317
5318/**
5319 * @interface TouchEvent
5320 * @see http://www.w3.org/TR/touch-events/
5321 */
5322var SyntheticTouchEvent = SyntheticUIEvent.extend({
5323 touches: null,
5324 targetTouches: null,
5325 changedTouches: null,
5326 altKey: null,
5327 metaKey: null,
5328 ctrlKey: null,
5329 shiftKey: null,
5330 getModifierState: getEventModifierState
5331});
5332
5333/**
5334 * @interface Event
5335 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
5336 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
5337 */
5338var SyntheticTransitionEvent = SyntheticEvent$1.extend({
5339 propertyName: null,
5340 elapsedTime: null,
5341 pseudoElement: null
5342});
5343
5344/**
5345 * @interface WheelEvent
5346 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5347 */
5348var SyntheticWheelEvent = SyntheticMouseEvent.extend({
5349 deltaX: function (event) {
5350 return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
5351 'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
5352 },
5353 deltaY: function (event) {
5354 return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
5355 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
5356 'wheelDelta' in event ? -event.wheelDelta : 0;
5357 },
5358
5359 deltaZ: null,
5360
5361 // Browsers without "deltaMode" is reporting in raw wheel delta where one
5362 // notch on the scroll is always +/- 120, roughly equivalent to pixels.
5363 // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
5364 // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
5365 deltaMode: null
5366});
5367
5368/**
5369 * Turns
5370 * ['abort', ...]
5371 * into
5372 * eventTypes = {
5373 * 'abort': {
5374 * phasedRegistrationNames: {
5375 * bubbled: 'onAbort',
5376 * captured: 'onAbortCapture',
5377 * },
5378 * dependencies: ['topAbort'],
5379 * },
5380 * ...
5381 * };
5382 * topLevelEventsToDispatchConfig = {
5383 * 'topAbort': { sameConfig }
5384 * };
5385 */
5386var eventTypes$4 = {};
5387var topLevelEventsToDispatchConfig = {};
5388['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) {
5389 var capitalizedEvent = event[0].toUpperCase() + event.slice(1);
5390 var onEvent = 'on' + capitalizedEvent;
5391 var topEvent = 'top' + capitalizedEvent;
5392
5393 var type = {
5394 phasedRegistrationNames: {
5395 bubbled: onEvent,
5396 captured: onEvent + 'Capture'
5397 },
5398 dependencies: [topEvent]
5399 };
5400 eventTypes$4[event] = type;
5401 topLevelEventsToDispatchConfig[topEvent] = type;
5402});
5403
5404// Only used in DEV for exhaustiveness validation.
5405var 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'];
5406
5407var SimpleEventPlugin = {
5408 eventTypes: eventTypes$4,
5409
5410 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
5411 var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
5412 if (!dispatchConfig) {
5413 return null;
5414 }
5415 var EventConstructor = void 0;
5416 switch (topLevelType) {
5417 case 'topKeyPress':
5418 // Firefox creates a keypress event for function keys too. This removes
5419 // the unwanted keypress events. Enter is however both printable and
5420 // non-printable. One would expect Tab to be as well (but it isn't).
5421 if (getEventCharCode(nativeEvent) === 0) {
5422 return null;
5423 }
5424 /* falls through */
5425 case 'topKeyDown':
5426 case 'topKeyUp':
5427 EventConstructor = SyntheticKeyboardEvent;
5428 break;
5429 case 'topBlur':
5430 case 'topFocus':
5431 EventConstructor = SyntheticFocusEvent;
5432 break;
5433 case 'topClick':
5434 // Firefox creates a click event on right mouse clicks. This removes the
5435 // unwanted click events.
5436 if (nativeEvent.button === 2) {
5437 return null;
5438 }
5439 /* falls through */
5440 case 'topDoubleClick':
5441 case 'topMouseDown':
5442 case 'topMouseMove':
5443 case 'topMouseUp':
5444 // TODO: Disabled elements should not respond to mouse events
5445 /* falls through */
5446 case 'topMouseOut':
5447 case 'topMouseOver':
5448 case 'topContextMenu':
5449 EventConstructor = SyntheticMouseEvent;
5450 break;
5451 case 'topDrag':
5452 case 'topDragEnd':
5453 case 'topDragEnter':
5454 case 'topDragExit':
5455 case 'topDragLeave':
5456 case 'topDragOver':
5457 case 'topDragStart':
5458 case 'topDrop':
5459 EventConstructor = SyntheticDragEvent;
5460 break;
5461 case 'topTouchCancel':
5462 case 'topTouchEnd':
5463 case 'topTouchMove':
5464 case 'topTouchStart':
5465 EventConstructor = SyntheticTouchEvent;
5466 break;
5467 case 'topAnimationEnd':
5468 case 'topAnimationIteration':
5469 case 'topAnimationStart':
5470 EventConstructor = SyntheticAnimationEvent;
5471 break;
5472 case 'topTransitionEnd':
5473 EventConstructor = SyntheticTransitionEvent;
5474 break;
5475 case 'topScroll':
5476 EventConstructor = SyntheticUIEvent;
5477 break;
5478 case 'topWheel':
5479 EventConstructor = SyntheticWheelEvent;
5480 break;
5481 case 'topCopy':
5482 case 'topCut':
5483 case 'topPaste':
5484 EventConstructor = SyntheticClipboardEvent;
5485 break;
5486 default:
5487 {
5488 if (knownHTMLTopLevelTypes.indexOf(topLevelType) === -1) {
5489 warning_1(false, 'SimpleEventPlugin: Unhandled event type, `%s`. This warning ' + 'is likely caused by a bug in React. Please file an issue.', topLevelType);
5490 }
5491 }
5492 // HTML Events
5493 // @see http://www.w3.org/TR/html5/index.html#events-0
5494 EventConstructor = SyntheticEvent$1;
5495 break;
5496 }
5497 var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
5498 accumulateTwoPhaseDispatches(event);
5499 return event;
5500 }
5501};
5502
5503/**
5504 * Inject modules for resolving DOM hierarchy and plugin ordering.
5505 */
5506injection.injectEventPluginOrder(DOMEventPluginOrder);
5507injection$1.injectComponentTree(ReactDOMComponentTree);
5508
5509/**
5510 * Some important event plugins included by default (without having to require
5511 * them).
5512 */
5513injection.injectEventPluginsByName({
5514 SimpleEventPlugin: SimpleEventPlugin,
5515 EnterLeaveEventPlugin: EnterLeaveEventPlugin,
5516 ChangeEventPlugin: ChangeEventPlugin,
5517 SelectEventPlugin: SelectEventPlugin,
5518 BeforeInputEventPlugin: BeforeInputEventPlugin
5519});
5520
5521/**
5522 * Copyright (c) 2013-present, Facebook, Inc.
5523 *
5524 * This source code is licensed under the MIT license found in the
5525 * LICENSE file in the root directory of this source tree.
5526 *
5527 */
5528
5529
5530
5531var emptyObject = {};
5532
5533{
5534 Object.freeze(emptyObject);
5535}
5536
5537var emptyObject_1 = emptyObject;
5538
5539var valueStack = [];
5540
5541var fiberStack = void 0;
5542
5543{
5544 fiberStack = [];
5545}
5546
5547var index = -1;
5548
5549function createCursor(defaultValue) {
5550 return {
5551 current: defaultValue
5552 };
5553}
5554
5555
5556
5557function pop(cursor, fiber) {
5558 if (index < 0) {
5559 {
5560 warning_1(false, 'Unexpected pop.');
5561 }
5562 return;
5563 }
5564
5565 {
5566 if (fiber !== fiberStack[index]) {
5567 warning_1(false, 'Unexpected Fiber popped.');
5568 }
5569 }
5570
5571 cursor.current = valueStack[index];
5572
5573 valueStack[index] = null;
5574
5575 {
5576 fiberStack[index] = null;
5577 }
5578
5579 index--;
5580}
5581
5582function push(cursor, value, fiber) {
5583 index++;
5584
5585 valueStack[index] = cursor.current;
5586
5587 {
5588 fiberStack[index] = fiber;
5589 }
5590
5591 cursor.current = value;
5592}
5593
5594function reset$1() {
5595 while (index > -1) {
5596 valueStack[index] = null;
5597
5598 {
5599 fiberStack[index] = null;
5600 }
5601
5602 index--;
5603 }
5604}
5605
5606var enableAsyncSubtreeAPI = true;
5607var enableAsyncSchedulingByDefaultInReactDOM = false;
5608// Exports ReactDOM.createRoot
5609var enableCreateRoot = false;
5610var enableUserTimingAPI = true;
5611
5612// Mutating mode (React DOM, React ART, React Native):
5613var enableMutatingReconciler = true;
5614// Experimental noop mode (currently unused):
5615var enableNoopReconciler = false;
5616// Experimental persistent mode (CS):
5617var enablePersistentReconciler = false;
5618
5619// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
5620var debugRenderPhaseSideEffects = false;
5621
5622// Only used in www builds.
5623
5624// Prefix measurements so that it's possible to filter them.
5625// Longer prefixes are hard to read in DevTools.
5626var reactEmoji = '\u269B';
5627var warningEmoji = '\u26D4';
5628var supportsUserTiming = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function';
5629
5630// Keep track of current fiber so that we know the path to unwind on pause.
5631// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them?
5632var currentFiber = null;
5633// If we're in the middle of user code, which fiber and method is it?
5634// Reusing `currentFiber` would be confusing for this because user code fiber
5635// can change during commit phase too, but we don't need to unwind it (since
5636// lifecycles in the commit phase don't resemble a tree).
5637var currentPhase = null;
5638var currentPhaseFiber = null;
5639// Did lifecycle hook schedule an update? This is often a performance problem,
5640// so we will keep track of it, and include it in the report.
5641// Track commits caused by cascading updates.
5642var isCommitting = false;
5643var hasScheduledUpdateInCurrentCommit = false;
5644var hasScheduledUpdateInCurrentPhase = false;
5645var commitCountInCurrentWorkLoop = 0;
5646var effectCountInCurrentCommit = 0;
5647var isWaitingForCallback = false;
5648// During commits, we only show a measurement once per method name
5649// to avoid stretch the commit phase with measurement overhead.
5650var labelsInCurrentCommit = new Set();
5651
5652var formatMarkName = function (markName) {
5653 return reactEmoji + ' ' + markName;
5654};
5655
5656var formatLabel = function (label, warning) {
5657 var prefix = warning ? warningEmoji + ' ' : reactEmoji + ' ';
5658 var suffix = warning ? ' Warning: ' + warning : '';
5659 return '' + prefix + label + suffix;
5660};
5661
5662var beginMark = function (markName) {
5663 performance.mark(formatMarkName(markName));
5664};
5665
5666var clearMark = function (markName) {
5667 performance.clearMarks(formatMarkName(markName));
5668};
5669
5670var endMark = function (label, markName, warning) {
5671 var formattedMarkName = formatMarkName(markName);
5672 var formattedLabel = formatLabel(label, warning);
5673 try {
5674 performance.measure(formattedLabel, formattedMarkName);
5675 } catch (err) {}
5676 // If previous mark was missing for some reason, this will throw.
5677 // This could only happen if React crashed in an unexpected place earlier.
5678 // Don't pile on with more errors.
5679
5680 // Clear marks immediately to avoid growing buffer.
5681 performance.clearMarks(formattedMarkName);
5682 performance.clearMeasures(formattedLabel);
5683};
5684
5685var getFiberMarkName = function (label, debugID) {
5686 return label + ' (#' + debugID + ')';
5687};
5688
5689var getFiberLabel = function (componentName, isMounted, phase) {
5690 if (phase === null) {
5691 // These are composite component total time measurements.
5692 return componentName + ' [' + (isMounted ? 'update' : 'mount') + ']';
5693 } else {
5694 // Composite component methods.
5695 return componentName + '.' + phase;
5696 }
5697};
5698
5699var beginFiberMark = function (fiber, phase) {
5700 var componentName = getComponentName(fiber) || 'Unknown';
5701 var debugID = fiber._debugID;
5702 var isMounted = fiber.alternate !== null;
5703 var label = getFiberLabel(componentName, isMounted, phase);
5704
5705 if (isCommitting && labelsInCurrentCommit.has(label)) {
5706 // During the commit phase, we don't show duplicate labels because
5707 // there is a fixed overhead for every measurement, and we don't
5708 // want to stretch the commit phase beyond necessary.
5709 return false;
5710 }
5711 labelsInCurrentCommit.add(label);
5712
5713 var markName = getFiberMarkName(label, debugID);
5714 beginMark(markName);
5715 return true;
5716};
5717
5718var clearFiberMark = function (fiber, phase) {
5719 var componentName = getComponentName(fiber) || 'Unknown';
5720 var debugID = fiber._debugID;
5721 var isMounted = fiber.alternate !== null;
5722 var label = getFiberLabel(componentName, isMounted, phase);
5723 var markName = getFiberMarkName(label, debugID);
5724 clearMark(markName);
5725};
5726
5727var endFiberMark = function (fiber, phase, warning) {
5728 var componentName = getComponentName(fiber) || 'Unknown';
5729 var debugID = fiber._debugID;
5730 var isMounted = fiber.alternate !== null;
5731 var label = getFiberLabel(componentName, isMounted, phase);
5732 var markName = getFiberMarkName(label, debugID);
5733 endMark(label, markName, warning);
5734};
5735
5736var shouldIgnoreFiber = function (fiber) {
5737 // Host components should be skipped in the timeline.
5738 // We could check typeof fiber.type, but does this work with RN?
5739 switch (fiber.tag) {
5740 case HostRoot:
5741 case HostComponent:
5742 case HostText:
5743 case HostPortal:
5744 case CallComponent:
5745 case ReturnComponent:
5746 case Fragment:
5747 return true;
5748 default:
5749 return false;
5750 }
5751};
5752
5753var clearPendingPhaseMeasurement = function () {
5754 if (currentPhase !== null && currentPhaseFiber !== null) {
5755 clearFiberMark(currentPhaseFiber, currentPhase);
5756 }
5757 currentPhaseFiber = null;
5758 currentPhase = null;
5759 hasScheduledUpdateInCurrentPhase = false;
5760};
5761
5762var pauseTimers = function () {
5763 // Stops all currently active measurements so that they can be resumed
5764 // if we continue in a later deferred loop from the same unit of work.
5765 var fiber = currentFiber;
5766 while (fiber) {
5767 if (fiber._debugIsCurrentlyTiming) {
5768 endFiberMark(fiber, null, null);
5769 }
5770 fiber = fiber['return'];
5771 }
5772};
5773
5774var resumeTimersRecursively = function (fiber) {
5775 if (fiber['return'] !== null) {
5776 resumeTimersRecursively(fiber['return']);
5777 }
5778 if (fiber._debugIsCurrentlyTiming) {
5779 beginFiberMark(fiber, null);
5780 }
5781};
5782
5783var resumeTimers = function () {
5784 // Resumes all measurements that were active during the last deferred loop.
5785 if (currentFiber !== null) {
5786 resumeTimersRecursively(currentFiber);
5787 }
5788};
5789
5790function recordEffect() {
5791 if (enableUserTimingAPI) {
5792 effectCountInCurrentCommit++;
5793 }
5794}
5795
5796function recordScheduleUpdate() {
5797 if (enableUserTimingAPI) {
5798 if (isCommitting) {
5799 hasScheduledUpdateInCurrentCommit = true;
5800 }
5801 if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') {
5802 hasScheduledUpdateInCurrentPhase = true;
5803 }
5804 }
5805}
5806
5807function startRequestCallbackTimer() {
5808 if (enableUserTimingAPI) {
5809 if (supportsUserTiming && !isWaitingForCallback) {
5810 isWaitingForCallback = true;
5811 beginMark('(Waiting for async callback...)');
5812 }
5813 }
5814}
5815
5816function stopRequestCallbackTimer(didExpire) {
5817 if (enableUserTimingAPI) {
5818 if (supportsUserTiming) {
5819 isWaitingForCallback = false;
5820 var warning = didExpire ? 'React was blocked by main thread' : null;
5821 endMark('(Waiting for async callback...)', '(Waiting for async callback...)', warning);
5822 }
5823 }
5824}
5825
5826function startWorkTimer(fiber) {
5827 if (enableUserTimingAPI) {
5828 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5829 return;
5830 }
5831 // If we pause, this is the fiber to unwind from.
5832 currentFiber = fiber;
5833 if (!beginFiberMark(fiber, null)) {
5834 return;
5835 }
5836 fiber._debugIsCurrentlyTiming = true;
5837 }
5838}
5839
5840function cancelWorkTimer(fiber) {
5841 if (enableUserTimingAPI) {
5842 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5843 return;
5844 }
5845 // Remember we shouldn't complete measurement for this fiber.
5846 // Otherwise flamechart will be deep even for small updates.
5847 fiber._debugIsCurrentlyTiming = false;
5848 clearFiberMark(fiber, null);
5849 }
5850}
5851
5852function stopWorkTimer(fiber) {
5853 if (enableUserTimingAPI) {
5854 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5855 return;
5856 }
5857 // If we pause, its parent is the fiber to unwind from.
5858 currentFiber = fiber['return'];
5859 if (!fiber._debugIsCurrentlyTiming) {
5860 return;
5861 }
5862 fiber._debugIsCurrentlyTiming = false;
5863 endFiberMark(fiber, null, null);
5864 }
5865}
5866
5867function stopFailedWorkTimer(fiber) {
5868 if (enableUserTimingAPI) {
5869 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5870 return;
5871 }
5872 // If we pause, its parent is the fiber to unwind from.
5873 currentFiber = fiber['return'];
5874 if (!fiber._debugIsCurrentlyTiming) {
5875 return;
5876 }
5877 fiber._debugIsCurrentlyTiming = false;
5878 var warning = 'An error was thrown inside this error boundary';
5879 endFiberMark(fiber, null, warning);
5880 }
5881}
5882
5883function startPhaseTimer(fiber, phase) {
5884 if (enableUserTimingAPI) {
5885 if (!supportsUserTiming) {
5886 return;
5887 }
5888 clearPendingPhaseMeasurement();
5889 if (!beginFiberMark(fiber, phase)) {
5890 return;
5891 }
5892 currentPhaseFiber = fiber;
5893 currentPhase = phase;
5894 }
5895}
5896
5897function stopPhaseTimer() {
5898 if (enableUserTimingAPI) {
5899 if (!supportsUserTiming) {
5900 return;
5901 }
5902 if (currentPhase !== null && currentPhaseFiber !== null) {
5903 var warning = hasScheduledUpdateInCurrentPhase ? 'Scheduled a cascading update' : null;
5904 endFiberMark(currentPhaseFiber, currentPhase, warning);
5905 }
5906 currentPhase = null;
5907 currentPhaseFiber = null;
5908 }
5909}
5910
5911function startWorkLoopTimer(nextUnitOfWork) {
5912 if (enableUserTimingAPI) {
5913 currentFiber = nextUnitOfWork;
5914 if (!supportsUserTiming) {
5915 return;
5916 }
5917 commitCountInCurrentWorkLoop = 0;
5918 // This is top level call.
5919 // Any other measurements are performed within.
5920 beginMark('(React Tree Reconciliation)');
5921 // Resume any measurements that were in progress during the last loop.
5922 resumeTimers();
5923 }
5924}
5925
5926function stopWorkLoopTimer(interruptedBy) {
5927 if (enableUserTimingAPI) {
5928 if (!supportsUserTiming) {
5929 return;
5930 }
5931 var warning = null;
5932 if (interruptedBy !== null) {
5933 if (interruptedBy.tag === HostRoot) {
5934 warning = 'A top-level update interrupted the previous render';
5935 } else {
5936 var componentName = getComponentName(interruptedBy) || 'Unknown';
5937 warning = 'An update to ' + componentName + ' interrupted the previous render';
5938 }
5939 } else if (commitCountInCurrentWorkLoop > 1) {
5940 warning = 'There were cascading updates';
5941 }
5942 commitCountInCurrentWorkLoop = 0;
5943 // Pause any measurements until the next loop.
5944 pauseTimers();
5945 endMark('(React Tree Reconciliation)', '(React Tree Reconciliation)', warning);
5946 }
5947}
5948
5949function startCommitTimer() {
5950 if (enableUserTimingAPI) {
5951 if (!supportsUserTiming) {
5952 return;
5953 }
5954 isCommitting = true;
5955 hasScheduledUpdateInCurrentCommit = false;
5956 labelsInCurrentCommit.clear();
5957 beginMark('(Committing Changes)');
5958 }
5959}
5960
5961function stopCommitTimer() {
5962 if (enableUserTimingAPI) {
5963 if (!supportsUserTiming) {
5964 return;
5965 }
5966
5967 var warning = null;
5968 if (hasScheduledUpdateInCurrentCommit) {
5969 warning = 'Lifecycle hook scheduled a cascading update';
5970 } else if (commitCountInCurrentWorkLoop > 0) {
5971 warning = 'Caused by a cascading update in earlier commit';
5972 }
5973 hasScheduledUpdateInCurrentCommit = false;
5974 commitCountInCurrentWorkLoop++;
5975 isCommitting = false;
5976 labelsInCurrentCommit.clear();
5977
5978 endMark('(Committing Changes)', '(Committing Changes)', warning);
5979 }
5980}
5981
5982function startCommitHostEffectsTimer() {
5983 if (enableUserTimingAPI) {
5984 if (!supportsUserTiming) {
5985 return;
5986 }
5987 effectCountInCurrentCommit = 0;
5988 beginMark('(Committing Host Effects)');
5989 }
5990}
5991
5992function stopCommitHostEffectsTimer() {
5993 if (enableUserTimingAPI) {
5994 if (!supportsUserTiming) {
5995 return;
5996 }
5997 var count = effectCountInCurrentCommit;
5998 effectCountInCurrentCommit = 0;
5999 endMark('(Committing Host Effects: ' + count + ' Total)', '(Committing Host Effects)', null);
6000 }
6001}
6002
6003function startCommitLifeCyclesTimer() {
6004 if (enableUserTimingAPI) {
6005 if (!supportsUserTiming) {
6006 return;
6007 }
6008 effectCountInCurrentCommit = 0;
6009 beginMark('(Calling Lifecycle Methods)');
6010 }
6011}
6012
6013function stopCommitLifeCyclesTimer() {
6014 if (enableUserTimingAPI) {
6015 if (!supportsUserTiming) {
6016 return;
6017 }
6018 var count = effectCountInCurrentCommit;
6019 effectCountInCurrentCommit = 0;
6020 endMark('(Calling Lifecycle Methods: ' + count + ' Total)', '(Calling Lifecycle Methods)', null);
6021 }
6022}
6023
6024var warnedAboutMissingGetChildContext = void 0;
6025
6026{
6027 warnedAboutMissingGetChildContext = {};
6028}
6029
6030// A cursor to the current merged context object on the stack.
6031var contextStackCursor = createCursor(emptyObject_1);
6032// A cursor to a boolean indicating whether the context has changed.
6033var didPerformWorkStackCursor = createCursor(false);
6034// Keep track of the previous context object that was on the stack.
6035// We use this to get access to the parent context after we have already
6036// pushed the next context provider, and now need to merge their contexts.
6037var previousContext = emptyObject_1;
6038
6039function getUnmaskedContext(workInProgress) {
6040 var hasOwnContext = isContextProvider(workInProgress);
6041 if (hasOwnContext) {
6042 // If the fiber is a context provider itself, when we read its context
6043 // we have already pushed its own child context on the stack. A context
6044 // provider should not "see" its own child context. Therefore we read the
6045 // previous (parent) context instead for a context provider.
6046 return previousContext;
6047 }
6048 return contextStackCursor.current;
6049}
6050
6051function cacheContext(workInProgress, unmaskedContext, maskedContext) {
6052 var instance = workInProgress.stateNode;
6053 instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
6054 instance.__reactInternalMemoizedMaskedChildContext = maskedContext;
6055}
6056
6057function getMaskedContext(workInProgress, unmaskedContext) {
6058 var type = workInProgress.type;
6059 var contextTypes = type.contextTypes;
6060 if (!contextTypes) {
6061 return emptyObject_1;
6062 }
6063
6064 // Avoid recreating masked context unless unmasked context has changed.
6065 // Failing to do this will result in unnecessary calls to componentWillReceiveProps.
6066 // This may trigger infinite loops if componentWillReceiveProps calls setState.
6067 var instance = workInProgress.stateNode;
6068 if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) {
6069 return instance.__reactInternalMemoizedMaskedChildContext;
6070 }
6071
6072 var context = {};
6073 for (var key in contextTypes) {
6074 context[key] = unmaskedContext[key];
6075 }
6076
6077 {
6078 var name = getComponentName(workInProgress) || 'Unknown';
6079 checkPropTypes_1(contextTypes, context, 'context', name, ReactDebugCurrentFiber.getCurrentFiberStackAddendum);
6080 }
6081
6082 // Cache unmasked context so we can avoid recreating masked context unless necessary.
6083 // Context is created before the class component is instantiated so check for instance.
6084 if (instance) {
6085 cacheContext(workInProgress, unmaskedContext, context);
6086 }
6087
6088 return context;
6089}
6090
6091function hasContextChanged() {
6092 return didPerformWorkStackCursor.current;
6093}
6094
6095function isContextConsumer(fiber) {
6096 return fiber.tag === ClassComponent && fiber.type.contextTypes != null;
6097}
6098
6099function isContextProvider(fiber) {
6100 return fiber.tag === ClassComponent && fiber.type.childContextTypes != null;
6101}
6102
6103function popContextProvider(fiber) {
6104 if (!isContextProvider(fiber)) {
6105 return;
6106 }
6107
6108 pop(didPerformWorkStackCursor, fiber);
6109 pop(contextStackCursor, fiber);
6110}
6111
6112function popTopLevelContextObject(fiber) {
6113 pop(didPerformWorkStackCursor, fiber);
6114 pop(contextStackCursor, fiber);
6115}
6116
6117function pushTopLevelContextObject(fiber, context, didChange) {
6118 !(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;
6119
6120 push(contextStackCursor, context, fiber);
6121 push(didPerformWorkStackCursor, didChange, fiber);
6122}
6123
6124function processChildContext(fiber, parentContext) {
6125 var instance = fiber.stateNode;
6126 var childContextTypes = fiber.type.childContextTypes;
6127
6128 // TODO (bvaughn) Replace this behavior with an invariant() in the future.
6129 // It has only been added in Fiber to match the (unintentional) behavior in Stack.
6130 if (typeof instance.getChildContext !== 'function') {
6131 {
6132 var componentName = getComponentName(fiber) || 'Unknown';
6133
6134 if (!warnedAboutMissingGetChildContext[componentName]) {
6135 warnedAboutMissingGetChildContext[componentName] = true;
6136 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);
6137 }
6138 }
6139 return parentContext;
6140 }
6141
6142 var childContext = void 0;
6143 {
6144 ReactDebugCurrentFiber.setCurrentPhase('getChildContext');
6145 }
6146 startPhaseTimer(fiber, 'getChildContext');
6147 childContext = instance.getChildContext();
6148 stopPhaseTimer();
6149 {
6150 ReactDebugCurrentFiber.setCurrentPhase(null);
6151 }
6152 for (var contextKey in childContext) {
6153 !(contextKey in childContextTypes) ? invariant_1(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', getComponentName(fiber) || 'Unknown', contextKey) : void 0;
6154 }
6155 {
6156 var name = getComponentName(fiber) || 'Unknown';
6157 checkPropTypes_1(childContextTypes, childContext, 'child context', name,
6158 // In practice, there is one case in which we won't get a stack. It's when
6159 // somebody calls unstable_renderSubtreeIntoContainer() and we process
6160 // context from the parent component instance. The stack will be missing
6161 // because it's outside of the reconciliation, and so the pointer has not
6162 // been set. This is rare and doesn't matter. We'll also remove that API.
6163 ReactDebugCurrentFiber.getCurrentFiberStackAddendum);
6164 }
6165
6166 return _assign({}, parentContext, childContext);
6167}
6168
6169function pushContextProvider(workInProgress) {
6170 if (!isContextProvider(workInProgress)) {
6171 return false;
6172 }
6173
6174 var instance = workInProgress.stateNode;
6175 // We push the context as early as possible to ensure stack integrity.
6176 // If the instance does not exist yet, we will push null at first,
6177 // and replace it on the stack later when invalidating the context.
6178 var memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyObject_1;
6179
6180 // Remember the parent context so we can merge with it later.
6181 // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates.
6182 previousContext = contextStackCursor.current;
6183 push(contextStackCursor, memoizedMergedChildContext, workInProgress);
6184 push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress);
6185
6186 return true;
6187}
6188
6189function invalidateContextProvider(workInProgress, didChange) {
6190 var instance = workInProgress.stateNode;
6191 !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;
6192
6193 if (didChange) {
6194 // Merge parent and own context.
6195 // Skip this if we're not updating due to sCU.
6196 // This avoids unnecessarily recomputing memoized values.
6197 var mergedContext = processChildContext(workInProgress, previousContext);
6198 instance.__reactInternalMemoizedMergedChildContext = mergedContext;
6199
6200 // Replace the old (or empty) context with the new one.
6201 // It is important to unwind the context in the reverse order.
6202 pop(didPerformWorkStackCursor, workInProgress);
6203 pop(contextStackCursor, workInProgress);
6204 // Now push the new context and mark that it has changed.
6205 push(contextStackCursor, mergedContext, workInProgress);
6206 push(didPerformWorkStackCursor, didChange, workInProgress);
6207 } else {
6208 pop(didPerformWorkStackCursor, workInProgress);
6209 push(didPerformWorkStackCursor, didChange, workInProgress);
6210 }
6211}
6212
6213function resetContext() {
6214 previousContext = emptyObject_1;
6215 contextStackCursor.current = emptyObject_1;
6216 didPerformWorkStackCursor.current = false;
6217}
6218
6219function findCurrentUnmaskedContext(fiber) {
6220 // Currently this is only used with renderSubtreeIntoContainer; not sure if it
6221 // makes sense elsewhere
6222 !(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;
6223
6224 var node = fiber;
6225 while (node.tag !== HostRoot) {
6226 if (isContextProvider(node)) {
6227 return node.stateNode.__reactInternalMemoizedMergedChildContext;
6228 }
6229 var parent = node['return'];
6230 !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;
6231 node = parent;
6232 }
6233 return node.stateNode.context;
6234}
6235
6236var NoWork = 0; // TODO: Use an opaque type once ESLint et al support the syntax
6237
6238var Sync = 1;
6239var Never = 2147483647; // Max int32: Math.pow(2, 31) - 1
6240
6241var UNIT_SIZE = 10;
6242var MAGIC_NUMBER_OFFSET = 2;
6243
6244// 1 unit of expiration time represents 10ms.
6245function msToExpirationTime(ms) {
6246 // Always add an offset so that we don't clash with the magic number for NoWork.
6247 return (ms / UNIT_SIZE | 0) + MAGIC_NUMBER_OFFSET;
6248}
6249
6250function expirationTimeToMs(expirationTime) {
6251 return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
6252}
6253
6254function ceiling(num, precision) {
6255 return ((num / precision | 0) + 1) * precision;
6256}
6257
6258function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) {
6259 return ceiling(currentTime + expirationInMs / UNIT_SIZE, bucketSizeMs / UNIT_SIZE);
6260}
6261
6262var NoContext = 0;
6263var AsyncUpdates = 1;
6264
6265var hasBadMapPolyfill = void 0;
6266
6267{
6268 hasBadMapPolyfill = false;
6269 try {
6270 var nonExtensibleObject = Object.preventExtensions({});
6271 var testMap = new Map([[nonExtensibleObject, null]]);
6272 var testSet = new Set([nonExtensibleObject]);
6273 // This is necessary for Rollup to not consider these unused.
6274 // https://github.com/rollup/rollup/issues/1771
6275 // TODO: we can remove these if Rollup fixes the bug.
6276 testMap.set(0, 0);
6277 testSet.add(0);
6278 } catch (e) {
6279 // TODO: Consider warning about bad polyfills
6280 hasBadMapPolyfill = true;
6281 }
6282}
6283
6284// A Fiber is work on a Component that needs to be done or was done. There can
6285// be more than one per component.
6286
6287
6288var debugCounter = void 0;
6289
6290{
6291 debugCounter = 1;
6292}
6293
6294function FiberNode(tag, pendingProps, key, internalContextTag) {
6295 // Instance
6296 this.tag = tag;
6297 this.key = key;
6298 this.type = null;
6299 this.stateNode = null;
6300
6301 // Fiber
6302 this['return'] = null;
6303 this.child = null;
6304 this.sibling = null;
6305 this.index = 0;
6306
6307 this.ref = null;
6308
6309 this.pendingProps = pendingProps;
6310 this.memoizedProps = null;
6311 this.updateQueue = null;
6312 this.memoizedState = null;
6313
6314 this.internalContextTag = internalContextTag;
6315
6316 // Effects
6317 this.effectTag = NoEffect;
6318 this.nextEffect = null;
6319
6320 this.firstEffect = null;
6321 this.lastEffect = null;
6322
6323 this.expirationTime = NoWork;
6324
6325 this.alternate = null;
6326
6327 {
6328 this._debugID = debugCounter++;
6329 this._debugSource = null;
6330 this._debugOwner = null;
6331 this._debugIsCurrentlyTiming = false;
6332 if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
6333 Object.preventExtensions(this);
6334 }
6335 }
6336}
6337
6338// This is a constructor function, rather than a POJO constructor, still
6339// please ensure we do the following:
6340// 1) Nobody should add any instance methods on this. Instance methods can be
6341// more difficult to predict when they get optimized and they are almost
6342// never inlined properly in static compilers.
6343// 2) Nobody should rely on `instanceof Fiber` for type testing. We should
6344// always know when it is a fiber.
6345// 3) We might want to experiment with using numeric keys since they are easier
6346// to optimize in a non-JIT environment.
6347// 4) We can easily go from a constructor to a createFiber object literal if that
6348// is faster.
6349// 5) It should be easy to port this to a C struct and keep a C implementation
6350// compatible.
6351var createFiber = function (tag, pendingProps, key, internalContextTag) {
6352 // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
6353 return new FiberNode(tag, pendingProps, key, internalContextTag);
6354};
6355
6356function shouldConstruct(Component) {
6357 return !!(Component.prototype && Component.prototype.isReactComponent);
6358}
6359
6360// This is used to create an alternate fiber to do work on.
6361function createWorkInProgress(current, pendingProps, expirationTime) {
6362 var workInProgress = current.alternate;
6363 if (workInProgress === null) {
6364 // We use a double buffering pooling technique because we know that we'll
6365 // only ever need at most two versions of a tree. We pool the "other" unused
6366 // node that we're free to reuse. This is lazily created to avoid allocating
6367 // extra objects for things that are never updated. It also allow us to
6368 // reclaim the extra memory if needed.
6369 workInProgress = createFiber(current.tag, pendingProps, current.key, current.internalContextTag);
6370 workInProgress.type = current.type;
6371 workInProgress.stateNode = current.stateNode;
6372
6373 {
6374 // DEV-only fields
6375 workInProgress._debugID = current._debugID;
6376 workInProgress._debugSource = current._debugSource;
6377 workInProgress._debugOwner = current._debugOwner;
6378 }
6379
6380 workInProgress.alternate = current;
6381 current.alternate = workInProgress;
6382 } else {
6383 workInProgress.pendingProps = pendingProps;
6384
6385 // We already have an alternate.
6386 // Reset the effect tag.
6387 workInProgress.effectTag = NoEffect;
6388
6389 // The effect list is no longer valid.
6390 workInProgress.nextEffect = null;
6391 workInProgress.firstEffect = null;
6392 workInProgress.lastEffect = null;
6393 }
6394
6395 workInProgress.expirationTime = expirationTime;
6396
6397 workInProgress.child = current.child;
6398 workInProgress.memoizedProps = current.memoizedProps;
6399 workInProgress.memoizedState = current.memoizedState;
6400 workInProgress.updateQueue = current.updateQueue;
6401
6402 // These will be overridden during the parent's reconciliation
6403 workInProgress.sibling = current.sibling;
6404 workInProgress.index = current.index;
6405 workInProgress.ref = current.ref;
6406
6407 return workInProgress;
6408}
6409
6410function createHostRootFiber(isAsync) {
6411 var internalContextTag = isAsync ? AsyncUpdates : NoContext;
6412 return createFiber(HostRoot, null, null, internalContextTag);
6413}
6414
6415function createFiberFromElement(element, internalContextTag, expirationTime) {
6416 var owner = null;
6417 {
6418 owner = element._owner;
6419 }
6420
6421 var fiber = void 0;
6422 var type = element.type;
6423 var key = element.key;
6424 var pendingProps = element.props;
6425 if (typeof type === 'function') {
6426 fiber = shouldConstruct(type) ? createFiber(ClassComponent, pendingProps, key, internalContextTag) : createFiber(IndeterminateComponent, pendingProps, key, internalContextTag);
6427 fiber.type = type;
6428 } else if (typeof type === 'string') {
6429 fiber = createFiber(HostComponent, pendingProps, key, internalContextTag);
6430 fiber.type = type;
6431 } else {
6432 switch (type) {
6433 case REACT_FRAGMENT_TYPE:
6434 return createFiberFromFragment(pendingProps.children, internalContextTag, expirationTime, key);
6435 case REACT_CALL_TYPE:
6436 fiber = createFiber(CallComponent, pendingProps, key, internalContextTag);
6437 fiber.type = REACT_CALL_TYPE;
6438 break;
6439 case REACT_RETURN_TYPE:
6440 fiber = createFiber(ReturnComponent, pendingProps, key, internalContextTag);
6441 fiber.type = REACT_RETURN_TYPE;
6442 break;
6443 default:
6444 {
6445 if (typeof type === 'object' && type !== null && typeof type.tag === 'number') {
6446 // Currently assumed to be a continuation and therefore is a
6447 // fiber already.
6448 // TODO: The yield system is currently broken for updates in some
6449 // cases. The reified yield stores a fiber, but we don't know which
6450 // fiber that is; the current or a workInProgress? When the
6451 // continuation gets rendered here we don't know if we can reuse that
6452 // fiber or if we need to clone it. There is probably a clever way to
6453 // restructure this.
6454 fiber = type;
6455 fiber.pendingProps = pendingProps;
6456 } else {
6457 var info = '';
6458 {
6459 if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
6460 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.';
6461 }
6462 var ownerName = owner ? getComponentName(owner) : null;
6463 if (ownerName) {
6464 info += '\n\nCheck the render method of `' + ownerName + '`.';
6465 }
6466 }
6467 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);
6468 }
6469 }
6470 }
6471 }
6472
6473 {
6474 fiber._debugSource = element._source;
6475 fiber._debugOwner = element._owner;
6476 }
6477
6478 fiber.expirationTime = expirationTime;
6479
6480 return fiber;
6481}
6482
6483function createFiberFromFragment(elements, internalContextTag, expirationTime, key) {
6484 var fiber = createFiber(Fragment, elements, key, internalContextTag);
6485 fiber.expirationTime = expirationTime;
6486 return fiber;
6487}
6488
6489function createFiberFromText(content, internalContextTag, expirationTime) {
6490 var fiber = createFiber(HostText, content, null, internalContextTag);
6491 fiber.expirationTime = expirationTime;
6492 return fiber;
6493}
6494
6495function createFiberFromHostInstanceForDeletion() {
6496 var fiber = createFiber(HostComponent, null, null, NoContext);
6497 fiber.type = 'DELETED';
6498 return fiber;
6499}
6500
6501function createFiberFromPortal(portal, internalContextTag, expirationTime) {
6502 var pendingProps = portal.children !== null ? portal.children : [];
6503 var fiber = createFiber(HostPortal, pendingProps, portal.key, internalContextTag);
6504 fiber.expirationTime = expirationTime;
6505 fiber.stateNode = {
6506 containerInfo: portal.containerInfo,
6507 pendingChildren: null, // Used by persistent updates
6508 implementation: portal.implementation
6509 };
6510 return fiber;
6511}
6512
6513// TODO: This should be lifted into the renderer.
6514
6515
6516function createFiberRoot(containerInfo, isAsync, hydrate) {
6517 // Cyclic construction. This cheats the type system right now because
6518 // stateNode is any.
6519 var uninitializedFiber = createHostRootFiber(isAsync);
6520 var root = {
6521 current: uninitializedFiber,
6522 containerInfo: containerInfo,
6523 pendingChildren: null,
6524 remainingExpirationTime: NoWork,
6525 isReadyForCommit: false,
6526 finishedWork: null,
6527 context: null,
6528 pendingContext: null,
6529 hydrate: hydrate,
6530 firstBatch: null,
6531 nextScheduledRoot: null
6532 };
6533 uninitializedFiber.stateNode = root;
6534 return root;
6535}
6536
6537var onCommitFiberRoot = null;
6538var onCommitFiberUnmount = null;
6539var hasLoggedError = false;
6540
6541function catchErrors(fn) {
6542 return function (arg) {
6543 try {
6544 return fn(arg);
6545 } catch (err) {
6546 if (true && !hasLoggedError) {
6547 hasLoggedError = true;
6548 warning_1(false, 'React DevTools encountered an error: %s', err);
6549 }
6550 }
6551 };
6552}
6553
6554function injectInternals(internals) {
6555 if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
6556 // No DevTools
6557 return false;
6558 }
6559 var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;
6560 if (hook.isDisabled) {
6561 // This isn't a real property on the hook, but it can be set to opt out
6562 // of DevTools integration and associated warnings and logs.
6563 // https://github.com/facebook/react/issues/3877
6564 return true;
6565 }
6566 if (!hook.supportsFiber) {
6567 {
6568 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');
6569 }
6570 // DevTools exists, even though it doesn't support Fiber.
6571 return true;
6572 }
6573 try {
6574 var rendererID = hook.inject(internals);
6575 // We have successfully injected, so now it is safe to set up hooks.
6576 onCommitFiberRoot = catchErrors(function (root) {
6577 return hook.onCommitFiberRoot(rendererID, root);
6578 });
6579 onCommitFiberUnmount = catchErrors(function (fiber) {
6580 return hook.onCommitFiberUnmount(rendererID, fiber);
6581 });
6582 } catch (err) {
6583 // Catch all errors because it is unsafe to throw during initialization.
6584 {
6585 warning_1(false, 'React DevTools encountered an error: %s.', err);
6586 }
6587 }
6588 // DevTools exists
6589 return true;
6590}
6591
6592function onCommitRoot(root) {
6593 if (typeof onCommitFiberRoot === 'function') {
6594 onCommitFiberRoot(root);
6595 }
6596}
6597
6598function onCommitUnmount(fiber) {
6599 if (typeof onCommitFiberUnmount === 'function') {
6600 onCommitFiberUnmount(fiber);
6601 }
6602}
6603
6604var didWarnUpdateInsideUpdate = void 0;
6605
6606{
6607 didWarnUpdateInsideUpdate = false;
6608}
6609
6610// Callbacks are not validated until invocation
6611
6612
6613// Singly linked-list of updates. When an update is scheduled, it is added to
6614// the queue of the current fiber and the work-in-progress fiber. The two queues
6615// are separate but they share a persistent structure.
6616//
6617// During reconciliation, updates are removed from the work-in-progress fiber,
6618// but they remain on the current fiber. That ensures that if a work-in-progress
6619// is aborted, the aborted updates are recovered by cloning from current.
6620//
6621// The work-in-progress queue is always a subset of the current queue.
6622//
6623// When the tree is committed, the work-in-progress becomes the current.
6624
6625
6626function createUpdateQueue(baseState) {
6627 var queue = {
6628 baseState: baseState,
6629 expirationTime: NoWork,
6630 first: null,
6631 last: null,
6632 callbackList: null,
6633 hasForceUpdate: false,
6634 isInitialized: false
6635 };
6636 {
6637 queue.isProcessing = false;
6638 }
6639 return queue;
6640}
6641
6642function insertUpdateIntoQueue(queue, update) {
6643 // Append the update to the end of the list.
6644 if (queue.last === null) {
6645 // Queue is empty
6646 queue.first = queue.last = update;
6647 } else {
6648 queue.last.next = update;
6649 queue.last = update;
6650 }
6651 if (queue.expirationTime === NoWork || queue.expirationTime > update.expirationTime) {
6652 queue.expirationTime = update.expirationTime;
6653 }
6654}
6655
6656function insertUpdateIntoFiber(fiber, update) {
6657 // We'll have at least one and at most two distinct update queues.
6658 var alternateFiber = fiber.alternate;
6659 var queue1 = fiber.updateQueue;
6660 if (queue1 === null) {
6661 // TODO: We don't know what the base state will be until we begin work.
6662 // It depends on which fiber is the next current. Initialize with an empty
6663 // base state, then set to the memoizedState when rendering. Not super
6664 // happy with this approach.
6665 queue1 = fiber.updateQueue = createUpdateQueue(null);
6666 }
6667
6668 var queue2 = void 0;
6669 if (alternateFiber !== null) {
6670 queue2 = alternateFiber.updateQueue;
6671 if (queue2 === null) {
6672 queue2 = alternateFiber.updateQueue = createUpdateQueue(null);
6673 }
6674 } else {
6675 queue2 = null;
6676 }
6677 queue2 = queue2 !== queue1 ? queue2 : null;
6678
6679 // Warn if an update is scheduled from inside an updater function.
6680 {
6681 if ((queue1.isProcessing || queue2 !== null && queue2.isProcessing) && !didWarnUpdateInsideUpdate) {
6682 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.');
6683 didWarnUpdateInsideUpdate = true;
6684 }
6685 }
6686
6687 // If there's only one queue, add the update to that queue and exit.
6688 if (queue2 === null) {
6689 insertUpdateIntoQueue(queue1, update);
6690 return;
6691 }
6692
6693 // If either queue is empty, we need to add to both queues.
6694 if (queue1.last === null || queue2.last === null) {
6695 insertUpdateIntoQueue(queue1, update);
6696 insertUpdateIntoQueue(queue2, update);
6697 return;
6698 }
6699
6700 // If both lists are not empty, the last update is the same for both lists
6701 // because of structural sharing. So, we should only append to one of
6702 // the lists.
6703 insertUpdateIntoQueue(queue1, update);
6704 // But we still need to update the `last` pointer of queue2.
6705 queue2.last = update;
6706}
6707
6708function getUpdateExpirationTime(fiber) {
6709 if (fiber.tag !== ClassComponent && fiber.tag !== HostRoot) {
6710 return NoWork;
6711 }
6712 var updateQueue = fiber.updateQueue;
6713 if (updateQueue === null) {
6714 return NoWork;
6715 }
6716 return updateQueue.expirationTime;
6717}
6718
6719function getStateFromUpdate(update, instance, prevState, props) {
6720 var partialState = update.partialState;
6721 if (typeof partialState === 'function') {
6722 var updateFn = partialState;
6723
6724 // Invoke setState callback an extra time to help detect side-effects.
6725 if (debugRenderPhaseSideEffects) {
6726 updateFn.call(instance, prevState, props);
6727 }
6728
6729 return updateFn.call(instance, prevState, props);
6730 } else {
6731 return partialState;
6732 }
6733}
6734
6735function processUpdateQueue(current, workInProgress, queue, instance, props, renderExpirationTime) {
6736 if (current !== null && current.updateQueue === queue) {
6737 // We need to create a work-in-progress queue, by cloning the current queue.
6738 var currentQueue = queue;
6739 queue = workInProgress.updateQueue = {
6740 baseState: currentQueue.baseState,
6741 expirationTime: currentQueue.expirationTime,
6742 first: currentQueue.first,
6743 last: currentQueue.last,
6744 isInitialized: currentQueue.isInitialized,
6745 // These fields are no longer valid because they were already committed.
6746 // Reset them.
6747 callbackList: null,
6748 hasForceUpdate: false
6749 };
6750 }
6751
6752 {
6753 // Set this flag so we can warn if setState is called inside the update
6754 // function of another setState.
6755 queue.isProcessing = true;
6756 }
6757
6758 // Reset the remaining expiration time. If we skip over any updates, we'll
6759 // increase this accordingly.
6760 queue.expirationTime = NoWork;
6761
6762 // TODO: We don't know what the base state will be until we begin work.
6763 // It depends on which fiber is the next current. Initialize with an empty
6764 // base state, then set to the memoizedState when rendering. Not super
6765 // happy with this approach.
6766 var state = void 0;
6767 if (queue.isInitialized) {
6768 state = queue.baseState;
6769 } else {
6770 state = queue.baseState = workInProgress.memoizedState;
6771 queue.isInitialized = true;
6772 }
6773 var dontMutatePrevState = true;
6774 var update = queue.first;
6775 var didSkip = false;
6776 while (update !== null) {
6777 var updateExpirationTime = update.expirationTime;
6778 if (updateExpirationTime > renderExpirationTime) {
6779 // This update does not have sufficient priority. Skip it.
6780 var remainingExpirationTime = queue.expirationTime;
6781 if (remainingExpirationTime === NoWork || remainingExpirationTime > updateExpirationTime) {
6782 // Update the remaining expiration time.
6783 queue.expirationTime = updateExpirationTime;
6784 }
6785 if (!didSkip) {
6786 didSkip = true;
6787 queue.baseState = state;
6788 }
6789 // Continue to the next update.
6790 update = update.next;
6791 continue;
6792 }
6793
6794 // This update does have sufficient priority.
6795
6796 // If no previous updates were skipped, drop this update from the queue by
6797 // advancing the head of the list.
6798 if (!didSkip) {
6799 queue.first = update.next;
6800 if (queue.first === null) {
6801 queue.last = null;
6802 }
6803 }
6804
6805 // Process the update
6806 var _partialState = void 0;
6807 if (update.isReplace) {
6808 state = getStateFromUpdate(update, instance, state, props);
6809 dontMutatePrevState = true;
6810 } else {
6811 _partialState = getStateFromUpdate(update, instance, state, props);
6812 if (_partialState) {
6813 if (dontMutatePrevState) {
6814 // $FlowFixMe: Idk how to type this properly.
6815 state = _assign({}, state, _partialState);
6816 } else {
6817 state = _assign(state, _partialState);
6818 }
6819 dontMutatePrevState = false;
6820 }
6821 }
6822 if (update.isForced) {
6823 queue.hasForceUpdate = true;
6824 }
6825 if (update.callback !== null) {
6826 // Append to list of callbacks.
6827 var _callbackList = queue.callbackList;
6828 if (_callbackList === null) {
6829 _callbackList = queue.callbackList = [];
6830 }
6831 _callbackList.push(update);
6832 }
6833 update = update.next;
6834 }
6835
6836 if (queue.callbackList !== null) {
6837 workInProgress.effectTag |= Callback;
6838 } else if (queue.first === null && !queue.hasForceUpdate) {
6839 // The queue is empty. We can reset it.
6840 workInProgress.updateQueue = null;
6841 }
6842
6843 if (!didSkip) {
6844 didSkip = true;
6845 queue.baseState = state;
6846 }
6847
6848 {
6849 // No longer processing.
6850 queue.isProcessing = false;
6851 }
6852
6853 return state;
6854}
6855
6856function commitCallbacks(queue, context) {
6857 var callbackList = queue.callbackList;
6858 if (callbackList === null) {
6859 return;
6860 }
6861 // Set the list to null to make sure they don't get called more than once.
6862 queue.callbackList = null;
6863 for (var i = 0; i < callbackList.length; i++) {
6864 var update = callbackList[i];
6865 var _callback = update.callback;
6866 // This update might be processed again. Clear the callback so it's only
6867 // called once.
6868 update.callback = null;
6869 !(typeof _callback === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback) : void 0;
6870 _callback.call(context);
6871 }
6872}
6873
6874var fakeInternalInstance = {};
6875var isArray = Array.isArray;
6876
6877var didWarnAboutStateAssignmentForComponent = void 0;
6878var warnOnInvalidCallback$1 = void 0;
6879
6880{
6881 var didWarnOnInvalidCallback = {};
6882 didWarnAboutStateAssignmentForComponent = {};
6883
6884 warnOnInvalidCallback$1 = function (callback, callerName) {
6885 if (callback === null || typeof callback === 'function') {
6886 return;
6887 }
6888 var key = callerName + '_' + callback;
6889 if (!didWarnOnInvalidCallback[key]) {
6890 warning_1(false, '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
6891 didWarnOnInvalidCallback[key] = true;
6892 }
6893 };
6894
6895 // This is so gross but it's at least non-critical and can be removed if
6896 // it causes problems. This is meant to give a nicer error message for
6897 // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component,
6898 // ...)) which otherwise throws a "_processChildContext is not a function"
6899 // exception.
6900 Object.defineProperty(fakeInternalInstance, '_processChildContext', {
6901 enumerable: false,
6902 value: function () {
6903 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).');
6904 }
6905 });
6906 Object.freeze(fakeInternalInstance);
6907}
6908
6909var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState) {
6910 // Class component state updater
6911 var updater = {
6912 isMounted: isMounted,
6913 enqueueSetState: function (instance, partialState, callback) {
6914 var fiber = get(instance);
6915 callback = callback === undefined ? null : callback;
6916 {
6917 warnOnInvalidCallback$1(callback, 'setState');
6918 }
6919 var expirationTime = computeExpirationForFiber(fiber);
6920 var update = {
6921 expirationTime: expirationTime,
6922 partialState: partialState,
6923 callback: callback,
6924 isReplace: false,
6925 isForced: false,
6926 nextCallback: null,
6927 next: null
6928 };
6929 insertUpdateIntoFiber(fiber, update);
6930 scheduleWork(fiber, expirationTime);
6931 },
6932 enqueueReplaceState: function (instance, state, callback) {
6933 var fiber = get(instance);
6934 callback = callback === undefined ? null : callback;
6935 {
6936 warnOnInvalidCallback$1(callback, 'replaceState');
6937 }
6938 var expirationTime = computeExpirationForFiber(fiber);
6939 var update = {
6940 expirationTime: expirationTime,
6941 partialState: state,
6942 callback: callback,
6943 isReplace: true,
6944 isForced: false,
6945 nextCallback: null,
6946 next: null
6947 };
6948 insertUpdateIntoFiber(fiber, update);
6949 scheduleWork(fiber, expirationTime);
6950 },
6951 enqueueForceUpdate: function (instance, callback) {
6952 var fiber = get(instance);
6953 callback = callback === undefined ? null : callback;
6954 {
6955 warnOnInvalidCallback$1(callback, 'forceUpdate');
6956 }
6957 var expirationTime = computeExpirationForFiber(fiber);
6958 var update = {
6959 expirationTime: expirationTime,
6960 partialState: null,
6961 callback: callback,
6962 isReplace: false,
6963 isForced: true,
6964 nextCallback: null,
6965 next: null
6966 };
6967 insertUpdateIntoFiber(fiber, update);
6968 scheduleWork(fiber, expirationTime);
6969 }
6970 };
6971
6972 function checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext) {
6973 if (oldProps === null || workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate) {
6974 // If the workInProgress already has an Update effect, return true
6975 return true;
6976 }
6977
6978 var instance = workInProgress.stateNode;
6979 var type = workInProgress.type;
6980 if (typeof instance.shouldComponentUpdate === 'function') {
6981 startPhaseTimer(workInProgress, 'shouldComponentUpdate');
6982 var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, newContext);
6983 stopPhaseTimer();
6984
6985 // Simulate an async bailout/interruption by invoking lifecycle twice.
6986 if (debugRenderPhaseSideEffects) {
6987 instance.shouldComponentUpdate(newProps, newState, newContext);
6988 }
6989
6990 {
6991 warning_1(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentName(workInProgress) || 'Unknown');
6992 }
6993
6994 return shouldUpdate;
6995 }
6996
6997 if (type.prototype && type.prototype.isPureReactComponent) {
6998 return !shallowEqual_1(oldProps, newProps) || !shallowEqual_1(oldState, newState);
6999 }
7000
7001 return true;
7002 }
7003
7004 function checkClassInstance(workInProgress) {
7005 var instance = workInProgress.stateNode;
7006 var type = workInProgress.type;
7007 {
7008 var name = getComponentName(workInProgress);
7009 var renderPresent = instance.render;
7010
7011 if (!renderPresent) {
7012 if (type.prototype && typeof type.prototype.render === 'function') {
7013 warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name);
7014 } else {
7015 warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name);
7016 }
7017 }
7018
7019 var noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state;
7020 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);
7021 var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved;
7022 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);
7023 var noInstancePropTypes = !instance.propTypes;
7024 warning_1(noInstancePropTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name);
7025 var noInstanceContextTypes = !instance.contextTypes;
7026 warning_1(noInstanceContextTypes, 'contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name);
7027 var noComponentShouldUpdate = typeof instance.componentShouldUpdate !== 'function';
7028 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);
7029 if (type.prototype && type.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') {
7030 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');
7031 }
7032 var noComponentDidUnmount = typeof instance.componentDidUnmount !== 'function';
7033 warning_1(noComponentDidUnmount, '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name);
7034 var noComponentDidReceiveProps = typeof instance.componentDidReceiveProps !== 'function';
7035 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);
7036 var noComponentWillRecieveProps = typeof instance.componentWillRecieveProps !== 'function';
7037 warning_1(noComponentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name);
7038 var hasMutatedProps = instance.props !== workInProgress.pendingProps;
7039 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);
7040 var noInstanceDefaultProps = !instance.defaultProps;
7041 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);
7042 }
7043
7044 var state = instance.state;
7045 if (state && (typeof state !== 'object' || isArray(state))) {
7046 warning_1(false, '%s.state: must be set to an object or null', getComponentName(workInProgress));
7047 }
7048 if (typeof instance.getChildContext === 'function') {
7049 warning_1(typeof workInProgress.type.childContextTypes === 'object', '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', getComponentName(workInProgress));
7050 }
7051 }
7052
7053 function resetInputPointers(workInProgress, instance) {
7054 instance.props = workInProgress.memoizedProps;
7055 instance.state = workInProgress.memoizedState;
7056 }
7057
7058 function adoptClassInstance(workInProgress, instance) {
7059 instance.updater = updater;
7060 workInProgress.stateNode = instance;
7061 // The instance needs access to the fiber so that it can schedule updates
7062 set(instance, workInProgress);
7063 {
7064 instance._reactInternalInstance = fakeInternalInstance;
7065 }
7066 }
7067
7068 function constructClassInstance(workInProgress, props) {
7069 var ctor = workInProgress.type;
7070 var unmaskedContext = getUnmaskedContext(workInProgress);
7071 var needsContext = isContextConsumer(workInProgress);
7072 var context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject_1;
7073 var instance = new ctor(props, context);
7074 adoptClassInstance(workInProgress, instance);
7075
7076 // Cache unmasked context so we can avoid recreating masked context unless necessary.
7077 // ReactFiberContext usually updates this cache but can't for newly-created instances.
7078 if (needsContext) {
7079 cacheContext(workInProgress, unmaskedContext, context);
7080 }
7081
7082 return instance;
7083 }
7084
7085 function callComponentWillMount(workInProgress, instance) {
7086 startPhaseTimer(workInProgress, 'componentWillMount');
7087 var oldState = instance.state;
7088 instance.componentWillMount();
7089 stopPhaseTimer();
7090
7091 if (oldState !== instance.state) {
7092 {
7093 warning_1(false, '%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentName(workInProgress));
7094 }
7095 updater.enqueueReplaceState(instance, instance.state, null);
7096 }
7097 }
7098
7099 function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) {
7100 startPhaseTimer(workInProgress, 'componentWillReceiveProps');
7101 var oldState = instance.state;
7102 instance.componentWillReceiveProps(newProps, newContext);
7103 stopPhaseTimer();
7104
7105 // Simulate an async bailout/interruption by invoking lifecycle twice.
7106 if (debugRenderPhaseSideEffects) {
7107 instance.componentWillReceiveProps(newProps, newContext);
7108 }
7109
7110 if (instance.state !== oldState) {
7111 {
7112 var componentName = getComponentName(workInProgress) || 'Component';
7113 if (!didWarnAboutStateAssignmentForComponent[componentName]) {
7114 warning_1(false, '%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', componentName);
7115 didWarnAboutStateAssignmentForComponent[componentName] = true;
7116 }
7117 }
7118 updater.enqueueReplaceState(instance, instance.state, null);
7119 }
7120 }
7121
7122 // Invokes the mount life-cycles on a previously never rendered instance.
7123 function mountClassInstance(workInProgress, renderExpirationTime) {
7124 var current = workInProgress.alternate;
7125
7126 {
7127 checkClassInstance(workInProgress);
7128 }
7129
7130 var instance = workInProgress.stateNode;
7131 var state = instance.state || null;
7132 var props = workInProgress.pendingProps;
7133 var unmaskedContext = getUnmaskedContext(workInProgress);
7134
7135 instance.props = props;
7136 instance.state = workInProgress.memoizedState = state;
7137 instance.refs = emptyObject_1;
7138 instance.context = getMaskedContext(workInProgress, unmaskedContext);
7139
7140 if (enableAsyncSubtreeAPI && workInProgress.type != null && workInProgress.type.prototype != null && workInProgress.type.prototype.unstable_isAsyncReactComponent === true) {
7141 workInProgress.internalContextTag |= AsyncUpdates;
7142 }
7143
7144 if (typeof instance.componentWillMount === 'function') {
7145 callComponentWillMount(workInProgress, instance);
7146 // If we had additional state updates during this life-cycle, let's
7147 // process them now.
7148 var updateQueue = workInProgress.updateQueue;
7149 if (updateQueue !== null) {
7150 instance.state = processUpdateQueue(current, workInProgress, updateQueue, instance, props, renderExpirationTime);
7151 }
7152 }
7153 if (typeof instance.componentDidMount === 'function') {
7154 workInProgress.effectTag |= Update;
7155 }
7156 }
7157
7158 // Called on a preexisting class instance. Returns false if a resumed render
7159 // could be reused.
7160 // function resumeMountClassInstance(
7161 // workInProgress: Fiber,
7162 // priorityLevel: PriorityLevel,
7163 // ): boolean {
7164 // const instance = workInProgress.stateNode;
7165 // resetInputPointers(workInProgress, instance);
7166
7167 // let newState = workInProgress.memoizedState;
7168 // let newProps = workInProgress.pendingProps;
7169 // if (!newProps) {
7170 // // If there isn't any new props, then we'll reuse the memoized props.
7171 // // This could be from already completed work.
7172 // newProps = workInProgress.memoizedProps;
7173 // invariant(
7174 // newProps != null,
7175 // 'There should always be pending or memoized props. This error is ' +
7176 // 'likely caused by a bug in React. Please file an issue.',
7177 // );
7178 // }
7179 // const newUnmaskedContext = getUnmaskedContext(workInProgress);
7180 // const newContext = getMaskedContext(workInProgress, newUnmaskedContext);
7181
7182 // const oldContext = instance.context;
7183 // const oldProps = workInProgress.memoizedProps;
7184
7185 // if (
7186 // typeof instance.componentWillReceiveProps === 'function' &&
7187 // (oldProps !== newProps || oldContext !== newContext)
7188 // ) {
7189 // callComponentWillReceiveProps(
7190 // workInProgress,
7191 // instance,
7192 // newProps,
7193 // newContext,
7194 // );
7195 // }
7196
7197 // // Process the update queue before calling shouldComponentUpdate
7198 // const updateQueue = workInProgress.updateQueue;
7199 // if (updateQueue !== null) {
7200 // newState = processUpdateQueue(
7201 // workInProgress,
7202 // updateQueue,
7203 // instance,
7204 // newState,
7205 // newProps,
7206 // priorityLevel,
7207 // );
7208 // }
7209
7210 // // TODO: Should we deal with a setState that happened after the last
7211 // // componentWillMount and before this componentWillMount? Probably
7212 // // unsupported anyway.
7213
7214 // if (
7215 // !checkShouldComponentUpdate(
7216 // workInProgress,
7217 // workInProgress.memoizedProps,
7218 // newProps,
7219 // workInProgress.memoizedState,
7220 // newState,
7221 // newContext,
7222 // )
7223 // ) {
7224 // // Update the existing instance's state, props, and context pointers even
7225 // // though we're bailing out.
7226 // instance.props = newProps;
7227 // instance.state = newState;
7228 // instance.context = newContext;
7229 // return false;
7230 // }
7231
7232 // // Update the input pointers now so that they are correct when we call
7233 // // componentWillMount
7234 // instance.props = newProps;
7235 // instance.state = newState;
7236 // instance.context = newContext;
7237
7238 // if (typeof instance.componentWillMount === 'function') {
7239 // callComponentWillMount(workInProgress, instance);
7240 // // componentWillMount may have called setState. Process the update queue.
7241 // const newUpdateQueue = workInProgress.updateQueue;
7242 // if (newUpdateQueue !== null) {
7243 // newState = processUpdateQueue(
7244 // workInProgress,
7245 // newUpdateQueue,
7246 // instance,
7247 // newState,
7248 // newProps,
7249 // priorityLevel,
7250 // );
7251 // }
7252 // }
7253
7254 // if (typeof instance.componentDidMount === 'function') {
7255 // workInProgress.effectTag |= Update;
7256 // }
7257
7258 // instance.state = newState;
7259
7260 // return true;
7261 // }
7262
7263 // Invokes the update life-cycles and returns false if it shouldn't rerender.
7264 function updateClassInstance(current, workInProgress, renderExpirationTime) {
7265 var instance = workInProgress.stateNode;
7266 resetInputPointers(workInProgress, instance);
7267
7268 var oldProps = workInProgress.memoizedProps;
7269 var newProps = workInProgress.pendingProps;
7270 var oldContext = instance.context;
7271 var newUnmaskedContext = getUnmaskedContext(workInProgress);
7272 var newContext = getMaskedContext(workInProgress, newUnmaskedContext);
7273
7274 // Note: During these life-cycles, instance.props/instance.state are what
7275 // ever the previously attempted to render - not the "current". However,
7276 // during componentDidUpdate we pass the "current" props.
7277
7278 if (typeof instance.componentWillReceiveProps === 'function' && (oldProps !== newProps || oldContext !== newContext)) {
7279 callComponentWillReceiveProps(workInProgress, instance, newProps, newContext);
7280 }
7281
7282 // Compute the next state using the memoized state and the update queue.
7283 var oldState = workInProgress.memoizedState;
7284 // TODO: Previous state can be null.
7285 var newState = void 0;
7286 if (workInProgress.updateQueue !== null) {
7287 newState = processUpdateQueue(current, workInProgress, workInProgress.updateQueue, instance, newProps, renderExpirationTime);
7288 } else {
7289 newState = oldState;
7290 }
7291
7292 if (oldProps === newProps && oldState === newState && !hasContextChanged() && !(workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate)) {
7293 // If an update was already in progress, we should schedule an Update
7294 // effect even though we're bailing out, so that cWU/cDU are called.
7295 if (typeof instance.componentDidUpdate === 'function') {
7296 if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
7297 workInProgress.effectTag |= Update;
7298 }
7299 }
7300 return false;
7301 }
7302
7303 var shouldUpdate = checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext);
7304
7305 if (shouldUpdate) {
7306 if (typeof instance.componentWillUpdate === 'function') {
7307 startPhaseTimer(workInProgress, 'componentWillUpdate');
7308 instance.componentWillUpdate(newProps, newState, newContext);
7309 stopPhaseTimer();
7310
7311 // Simulate an async bailout/interruption by invoking lifecycle twice.
7312 if (debugRenderPhaseSideEffects) {
7313 instance.componentWillUpdate(newProps, newState, newContext);
7314 }
7315 }
7316 if (typeof instance.componentDidUpdate === 'function') {
7317 workInProgress.effectTag |= Update;
7318 }
7319 } else {
7320 // If an update was already in progress, we should schedule an Update
7321 // effect even though we're bailing out, so that cWU/cDU are called.
7322 if (typeof instance.componentDidUpdate === 'function') {
7323 if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
7324 workInProgress.effectTag |= Update;
7325 }
7326 }
7327
7328 // If shouldComponentUpdate returned false, we should still update the
7329 // memoized props/state to indicate that this work can be reused.
7330 memoizeProps(workInProgress, newProps);
7331 memoizeState(workInProgress, newState);
7332 }
7333
7334 // Update the existing instance's state, props, and context pointers even
7335 // if shouldComponentUpdate returns false.
7336 instance.props = newProps;
7337 instance.state = newState;
7338 instance.context = newContext;
7339
7340 return shouldUpdate;
7341 }
7342
7343 return {
7344 adoptClassInstance: adoptClassInstance,
7345 constructClassInstance: constructClassInstance,
7346 mountClassInstance: mountClassInstance,
7347 // resumeMountClassInstance,
7348 updateClassInstance: updateClassInstance
7349 };
7350};
7351
7352var getCurrentFiberStackAddendum$2 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
7353
7354
7355var didWarnAboutMaps = void 0;
7356var ownerHasKeyUseWarning = void 0;
7357var ownerHasFunctionTypeWarning = void 0;
7358var warnForMissingKey = function (child) {};
7359
7360{
7361 didWarnAboutMaps = false;
7362 /**
7363 * Warn if there's no key explicitly set on dynamic arrays of children or
7364 * object keys are not valid. This allows us to keep track of children between
7365 * updates.
7366 */
7367 ownerHasKeyUseWarning = {};
7368 ownerHasFunctionTypeWarning = {};
7369
7370 warnForMissingKey = function (child) {
7371 if (child === null || typeof child !== 'object') {
7372 return;
7373 }
7374 if (!child._store || child._store.validated || child.key != null) {
7375 return;
7376 }
7377 !(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;
7378 child._store.validated = true;
7379
7380 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() || '');
7381 if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
7382 return;
7383 }
7384 ownerHasKeyUseWarning[currentComponentErrorInfo] = true;
7385
7386 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());
7387 };
7388}
7389
7390var isArray$1 = Array.isArray;
7391
7392function coerceRef(current, element) {
7393 var mixedRef = element.ref;
7394 if (mixedRef !== null && typeof mixedRef !== 'function') {
7395 if (element._owner) {
7396 var owner = element._owner;
7397 var inst = void 0;
7398 if (owner) {
7399 var ownerFiber = owner;
7400 !(ownerFiber.tag === ClassComponent) ? invariant_1(false, 'Stateless function components cannot have refs.') : void 0;
7401 inst = ownerFiber.stateNode;
7402 }
7403 !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;
7404 var stringRef = '' + mixedRef;
7405 // Check if previous string ref matches new string ref
7406 if (current !== null && current.ref !== null && current.ref._stringRef === stringRef) {
7407 return current.ref;
7408 }
7409 var ref = function (value) {
7410 var refs = inst.refs === emptyObject_1 ? inst.refs = {} : inst.refs;
7411 if (value === null) {
7412 delete refs[stringRef];
7413 } else {
7414 refs[stringRef] = value;
7415 }
7416 };
7417 ref._stringRef = stringRef;
7418 return ref;
7419 } else {
7420 !(typeof mixedRef === 'string') ? invariant_1(false, 'Expected ref to be a function or a string.') : void 0;
7421 !element._owner ? invariant_1(false, 'Element ref was specified as a string (%s) but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a functional component\n2. You may be adding a ref to a component that was not created inside a component\'s render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information.', mixedRef) : void 0;
7422 }
7423 }
7424 return mixedRef;
7425}
7426
7427function throwOnInvalidObjectType(returnFiber, newChild) {
7428 if (returnFiber.type !== 'textarea') {
7429 var addendum = '';
7430 {
7431 addendum = ' If you meant to render a collection of children, use an array ' + 'instead.' + (getCurrentFiberStackAddendum$2() || '');
7432 }
7433 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);
7434 }
7435}
7436
7437function warnOnFunctionType() {
7438 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() || '');
7439
7440 if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) {
7441 return;
7442 }
7443 ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true;
7444
7445 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() || '');
7446}
7447
7448// This wrapper function exists because I expect to clone the code in each path
7449// to be able to optimize each path individually by branching early. This needs
7450// a compiler or we can do it manually. Helpers that don't need this branching
7451// live outside of this function.
7452function ChildReconciler(shouldTrackSideEffects) {
7453 function deleteChild(returnFiber, childToDelete) {
7454 if (!shouldTrackSideEffects) {
7455 // Noop.
7456 return;
7457 }
7458 // Deletions are added in reversed order so we add it to the front.
7459 // At this point, the return fiber's effect list is empty except for
7460 // deletions, so we can just append the deletion to the list. The remaining
7461 // effects aren't added until the complete phase. Once we implement
7462 // resuming, this may not be true.
7463 var last = returnFiber.lastEffect;
7464 if (last !== null) {
7465 last.nextEffect = childToDelete;
7466 returnFiber.lastEffect = childToDelete;
7467 } else {
7468 returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
7469 }
7470 childToDelete.nextEffect = null;
7471 childToDelete.effectTag = Deletion;
7472 }
7473
7474 function deleteRemainingChildren(returnFiber, currentFirstChild) {
7475 if (!shouldTrackSideEffects) {
7476 // Noop.
7477 return null;
7478 }
7479
7480 // TODO: For the shouldClone case, this could be micro-optimized a bit by
7481 // assuming that after the first child we've already added everything.
7482 var childToDelete = currentFirstChild;
7483 while (childToDelete !== null) {
7484 deleteChild(returnFiber, childToDelete);
7485 childToDelete = childToDelete.sibling;
7486 }
7487 return null;
7488 }
7489
7490 function mapRemainingChildren(returnFiber, currentFirstChild) {
7491 // Add the remaining children to a temporary map so that we can find them by
7492 // keys quickly. Implicit (null) keys get added to this set with their index
7493 var existingChildren = new Map();
7494
7495 var existingChild = currentFirstChild;
7496 while (existingChild !== null) {
7497 if (existingChild.key !== null) {
7498 existingChildren.set(existingChild.key, existingChild);
7499 } else {
7500 existingChildren.set(existingChild.index, existingChild);
7501 }
7502 existingChild = existingChild.sibling;
7503 }
7504 return existingChildren;
7505 }
7506
7507 function useFiber(fiber, pendingProps, expirationTime) {
7508 // We currently set sibling to null and index to 0 here because it is easy
7509 // to forget to do before returning it. E.g. for the single child case.
7510 var clone = createWorkInProgress(fiber, pendingProps, expirationTime);
7511 clone.index = 0;
7512 clone.sibling = null;
7513 return clone;
7514 }
7515
7516 function placeChild(newFiber, lastPlacedIndex, newIndex) {
7517 newFiber.index = newIndex;
7518 if (!shouldTrackSideEffects) {
7519 // Noop.
7520 return lastPlacedIndex;
7521 }
7522 var current = newFiber.alternate;
7523 if (current !== null) {
7524 var oldIndex = current.index;
7525 if (oldIndex < lastPlacedIndex) {
7526 // This is a move.
7527 newFiber.effectTag = Placement;
7528 return lastPlacedIndex;
7529 } else {
7530 // This item can stay in place.
7531 return oldIndex;
7532 }
7533 } else {
7534 // This is an insertion.
7535 newFiber.effectTag = Placement;
7536 return lastPlacedIndex;
7537 }
7538 }
7539
7540 function placeSingleChild(newFiber) {
7541 // This is simpler for the single child case. We only need to do a
7542 // placement for inserting new children.
7543 if (shouldTrackSideEffects && newFiber.alternate === null) {
7544 newFiber.effectTag = Placement;
7545 }
7546 return newFiber;
7547 }
7548
7549 function updateTextNode(returnFiber, current, textContent, expirationTime) {
7550 if (current === null || current.tag !== HostText) {
7551 // Insert
7552 var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime);
7553 created['return'] = returnFiber;
7554 return created;
7555 } else {
7556 // Update
7557 var existing = useFiber(current, textContent, expirationTime);
7558 existing['return'] = returnFiber;
7559 return existing;
7560 }
7561 }
7562
7563 function updateElement(returnFiber, current, element, expirationTime) {
7564 if (current !== null && current.type === element.type) {
7565 // Move based on index
7566 var existing = useFiber(current, element.props, expirationTime);
7567 existing.ref = coerceRef(current, element);
7568 existing['return'] = returnFiber;
7569 {
7570 existing._debugSource = element._source;
7571 existing._debugOwner = element._owner;
7572 }
7573 return existing;
7574 } else {
7575 // Insert
7576 var created = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime);
7577 created.ref = coerceRef(current, element);
7578 created['return'] = returnFiber;
7579 return created;
7580 }
7581 }
7582
7583 function updatePortal(returnFiber, current, portal, expirationTime) {
7584 if (current === null || current.tag !== HostPortal || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) {
7585 // Insert
7586 var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime);
7587 created['return'] = returnFiber;
7588 return created;
7589 } else {
7590 // Update
7591 var existing = useFiber(current, portal.children || [], expirationTime);
7592 existing['return'] = returnFiber;
7593 return existing;
7594 }
7595 }
7596
7597 function updateFragment(returnFiber, current, fragment, expirationTime, key) {
7598 if (current === null || current.tag !== Fragment) {
7599 // Insert
7600 var created = createFiberFromFragment(fragment, returnFiber.internalContextTag, expirationTime, key);
7601 created['return'] = returnFiber;
7602 return created;
7603 } else {
7604 // Update
7605 var existing = useFiber(current, fragment, expirationTime);
7606 existing['return'] = returnFiber;
7607 return existing;
7608 }
7609 }
7610
7611 function createChild(returnFiber, newChild, expirationTime) {
7612 if (typeof newChild === 'string' || typeof newChild === 'number') {
7613 // Text nodes don't have keys. If the previous node is implicitly keyed
7614 // we can continue to replace it without aborting even if it is not a text
7615 // node.
7616 var created = createFiberFromText('' + newChild, returnFiber.internalContextTag, expirationTime);
7617 created['return'] = returnFiber;
7618 return created;
7619 }
7620
7621 if (typeof newChild === 'object' && newChild !== null) {
7622 switch (newChild.$$typeof) {
7623 case REACT_ELEMENT_TYPE:
7624 {
7625 var _created = createFiberFromElement(newChild, returnFiber.internalContextTag, expirationTime);
7626 _created.ref = coerceRef(null, newChild);
7627 _created['return'] = returnFiber;
7628 return _created;
7629 }
7630 case REACT_PORTAL_TYPE:
7631 {
7632 var _created2 = createFiberFromPortal(newChild, returnFiber.internalContextTag, expirationTime);
7633 _created2['return'] = returnFiber;
7634 return _created2;
7635 }
7636 }
7637
7638 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7639 var _created3 = createFiberFromFragment(newChild, returnFiber.internalContextTag, expirationTime, null);
7640 _created3['return'] = returnFiber;
7641 return _created3;
7642 }
7643
7644 throwOnInvalidObjectType(returnFiber, newChild);
7645 }
7646
7647 {
7648 if (typeof newChild === 'function') {
7649 warnOnFunctionType();
7650 }
7651 }
7652
7653 return null;
7654 }
7655
7656 function updateSlot(returnFiber, oldFiber, newChild, expirationTime) {
7657 // Update the fiber if the keys match, otherwise return null.
7658
7659 var key = oldFiber !== null ? oldFiber.key : null;
7660
7661 if (typeof newChild === 'string' || typeof newChild === 'number') {
7662 // Text nodes don't have keys. If the previous node is implicitly keyed
7663 // we can continue to replace it without aborting even if it is not a text
7664 // node.
7665 if (key !== null) {
7666 return null;
7667 }
7668 return updateTextNode(returnFiber, oldFiber, '' + newChild, expirationTime);
7669 }
7670
7671 if (typeof newChild === 'object' && newChild !== null) {
7672 switch (newChild.$$typeof) {
7673 case REACT_ELEMENT_TYPE:
7674 {
7675 if (newChild.key === key) {
7676 if (newChild.type === REACT_FRAGMENT_TYPE) {
7677 return updateFragment(returnFiber, oldFiber, newChild.props.children, expirationTime, key);
7678 }
7679 return updateElement(returnFiber, oldFiber, newChild, expirationTime);
7680 } else {
7681 return null;
7682 }
7683 }
7684 case REACT_PORTAL_TYPE:
7685 {
7686 if (newChild.key === key) {
7687 return updatePortal(returnFiber, oldFiber, newChild, expirationTime);
7688 } else {
7689 return null;
7690 }
7691 }
7692 }
7693
7694 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7695 if (key !== null) {
7696 return null;
7697 }
7698
7699 return updateFragment(returnFiber, oldFiber, newChild, expirationTime, null);
7700 }
7701
7702 throwOnInvalidObjectType(returnFiber, newChild);
7703 }
7704
7705 {
7706 if (typeof newChild === 'function') {
7707 warnOnFunctionType();
7708 }
7709 }
7710
7711 return null;
7712 }
7713
7714 function updateFromMap(existingChildren, returnFiber, newIdx, newChild, expirationTime) {
7715 if (typeof newChild === 'string' || typeof newChild === 'number') {
7716 // Text nodes don't have keys, so we neither have to check the old nor
7717 // new node for the key. If both are text nodes, they match.
7718 var matchedFiber = existingChildren.get(newIdx) || null;
7719 return updateTextNode(returnFiber, matchedFiber, '' + newChild, expirationTime);
7720 }
7721
7722 if (typeof newChild === 'object' && newChild !== null) {
7723 switch (newChild.$$typeof) {
7724 case REACT_ELEMENT_TYPE:
7725 {
7726 var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
7727 if (newChild.type === REACT_FRAGMENT_TYPE) {
7728 return updateFragment(returnFiber, _matchedFiber, newChild.props.children, expirationTime, newChild.key);
7729 }
7730 return updateElement(returnFiber, _matchedFiber, newChild, expirationTime);
7731 }
7732 case REACT_PORTAL_TYPE:
7733 {
7734 var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
7735 return updatePortal(returnFiber, _matchedFiber2, newChild, expirationTime);
7736 }
7737 }
7738
7739 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7740 var _matchedFiber3 = existingChildren.get(newIdx) || null;
7741 return updateFragment(returnFiber, _matchedFiber3, newChild, expirationTime, null);
7742 }
7743
7744 throwOnInvalidObjectType(returnFiber, newChild);
7745 }
7746
7747 {
7748 if (typeof newChild === 'function') {
7749 warnOnFunctionType();
7750 }
7751 }
7752
7753 return null;
7754 }
7755
7756 /**
7757 * Warns if there is a duplicate or missing key
7758 */
7759 function warnOnInvalidKey(child, knownKeys) {
7760 {
7761 if (typeof child !== 'object' || child === null) {
7762 return knownKeys;
7763 }
7764 switch (child.$$typeof) {
7765 case REACT_ELEMENT_TYPE:
7766 case REACT_PORTAL_TYPE:
7767 warnForMissingKey(child);
7768 var key = child.key;
7769 if (typeof key !== 'string') {
7770 break;
7771 }
7772 if (knownKeys === null) {
7773 knownKeys = new Set();
7774 knownKeys.add(key);
7775 break;
7776 }
7777 if (!knownKeys.has(key)) {
7778 knownKeys.add(key);
7779 break;
7780 }
7781 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());
7782 break;
7783 default:
7784 break;
7785 }
7786 }
7787 return knownKeys;
7788 }
7789
7790 function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, expirationTime) {
7791 // This algorithm can't optimize by searching from boths ends since we
7792 // don't have backpointers on fibers. I'm trying to see how far we can get
7793 // with that model. If it ends up not being worth the tradeoffs, we can
7794 // add it later.
7795
7796 // Even with a two ended optimization, we'd want to optimize for the case
7797 // where there are few changes and brute force the comparison instead of
7798 // going for the Map. It'd like to explore hitting that path first in
7799 // forward-only mode and only go for the Map once we notice that we need
7800 // lots of look ahead. This doesn't handle reversal as well as two ended
7801 // search but that's unusual. Besides, for the two ended optimization to
7802 // work on Iterables, we'd need to copy the whole set.
7803
7804 // In this first iteration, we'll just live with hitting the bad case
7805 // (adding everything to a Map) in for every insert/move.
7806
7807 // If you change this code, also update reconcileChildrenIterator() which
7808 // uses the same algorithm.
7809
7810 {
7811 // First, validate keys.
7812 var knownKeys = null;
7813 for (var i = 0; i < newChildren.length; i++) {
7814 var child = newChildren[i];
7815 knownKeys = warnOnInvalidKey(child, knownKeys);
7816 }
7817 }
7818
7819 var resultingFirstChild = null;
7820 var previousNewFiber = null;
7821
7822 var oldFiber = currentFirstChild;
7823 var lastPlacedIndex = 0;
7824 var newIdx = 0;
7825 var nextOldFiber = null;
7826 for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) {
7827 if (oldFiber.index > newIdx) {
7828 nextOldFiber = oldFiber;
7829 oldFiber = null;
7830 } else {
7831 nextOldFiber = oldFiber.sibling;
7832 }
7833 var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], expirationTime);
7834 if (newFiber === null) {
7835 // TODO: This breaks on empty slots like null children. That's
7836 // unfortunate because it triggers the slow path all the time. We need
7837 // a better way to communicate whether this was a miss or null,
7838 // boolean, undefined, etc.
7839 if (oldFiber === null) {
7840 oldFiber = nextOldFiber;
7841 }
7842 break;
7843 }
7844 if (shouldTrackSideEffects) {
7845 if (oldFiber && newFiber.alternate === null) {
7846 // We matched the slot, but we didn't reuse the existing fiber, so we
7847 // need to delete the existing child.
7848 deleteChild(returnFiber, oldFiber);
7849 }
7850 }
7851 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
7852 if (previousNewFiber === null) {
7853 // TODO: Move out of the loop. This only happens for the first run.
7854 resultingFirstChild = newFiber;
7855 } else {
7856 // TODO: Defer siblings if we're not at the right index for this slot.
7857 // I.e. if we had null values before, then we want to defer this
7858 // for each null value. However, we also don't want to call updateSlot
7859 // with the previous one.
7860 previousNewFiber.sibling = newFiber;
7861 }
7862 previousNewFiber = newFiber;
7863 oldFiber = nextOldFiber;
7864 }
7865
7866 if (newIdx === newChildren.length) {
7867 // We've reached the end of the new children. We can delete the rest.
7868 deleteRemainingChildren(returnFiber, oldFiber);
7869 return resultingFirstChild;
7870 }
7871
7872 if (oldFiber === null) {
7873 // If we don't have any more existing children we can choose a fast path
7874 // since the rest will all be insertions.
7875 for (; newIdx < newChildren.length; newIdx++) {
7876 var _newFiber = createChild(returnFiber, newChildren[newIdx], expirationTime);
7877 if (!_newFiber) {
7878 continue;
7879 }
7880 lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx);
7881 if (previousNewFiber === null) {
7882 // TODO: Move out of the loop. This only happens for the first run.
7883 resultingFirstChild = _newFiber;
7884 } else {
7885 previousNewFiber.sibling = _newFiber;
7886 }
7887 previousNewFiber = _newFiber;
7888 }
7889 return resultingFirstChild;
7890 }
7891
7892 // Add all children to a key map for quick lookups.
7893 var existingChildren = mapRemainingChildren(returnFiber, oldFiber);
7894
7895 // Keep scanning and use the map to restore deleted items as moves.
7896 for (; newIdx < newChildren.length; newIdx++) {
7897 var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], expirationTime);
7898 if (_newFiber2) {
7899 if (shouldTrackSideEffects) {
7900 if (_newFiber2.alternate !== null) {
7901 // The new fiber is a work in progress, but if there exists a
7902 // current, that means that we reused the fiber. We need to delete
7903 // it from the child list so that we don't add it to the deletion
7904 // list.
7905 existingChildren['delete'](_newFiber2.key === null ? newIdx : _newFiber2.key);
7906 }
7907 }
7908 lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx);
7909 if (previousNewFiber === null) {
7910 resultingFirstChild = _newFiber2;
7911 } else {
7912 previousNewFiber.sibling = _newFiber2;
7913 }
7914 previousNewFiber = _newFiber2;
7915 }
7916 }
7917
7918 if (shouldTrackSideEffects) {
7919 // Any existing children that weren't consumed above were deleted. We need
7920 // to add them to the deletion list.
7921 existingChildren.forEach(function (child) {
7922 return deleteChild(returnFiber, child);
7923 });
7924 }
7925
7926 return resultingFirstChild;
7927 }
7928
7929 function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, expirationTime) {
7930 // This is the same implementation as reconcileChildrenArray(),
7931 // but using the iterator instead.
7932
7933 var iteratorFn = getIteratorFn(newChildrenIterable);
7934 !(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;
7935
7936 {
7937 // Warn about using Maps as children
7938 if (typeof newChildrenIterable.entries === 'function') {
7939 var possibleMap = newChildrenIterable;
7940 if (possibleMap.entries === iteratorFn) {
7941 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());
7942 didWarnAboutMaps = true;
7943 }
7944 }
7945
7946 // First, validate keys.
7947 // We'll get a different iterator later for the main pass.
7948 var _newChildren = iteratorFn.call(newChildrenIterable);
7949 if (_newChildren) {
7950 var knownKeys = null;
7951 var _step = _newChildren.next();
7952 for (; !_step.done; _step = _newChildren.next()) {
7953 var child = _step.value;
7954 knownKeys = warnOnInvalidKey(child, knownKeys);
7955 }
7956 }
7957 }
7958
7959 var newChildren = iteratorFn.call(newChildrenIterable);
7960 !(newChildren != null) ? invariant_1(false, 'An iterable object provided no iterator.') : void 0;
7961
7962 var resultingFirstChild = null;
7963 var previousNewFiber = null;
7964
7965 var oldFiber = currentFirstChild;
7966 var lastPlacedIndex = 0;
7967 var newIdx = 0;
7968 var nextOldFiber = null;
7969
7970 var step = newChildren.next();
7971 for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) {
7972 if (oldFiber.index > newIdx) {
7973 nextOldFiber = oldFiber;
7974 oldFiber = null;
7975 } else {
7976 nextOldFiber = oldFiber.sibling;
7977 }
7978 var newFiber = updateSlot(returnFiber, oldFiber, step.value, expirationTime);
7979 if (newFiber === null) {
7980 // TODO: This breaks on empty slots like null children. That's
7981 // unfortunate because it triggers the slow path all the time. We need
7982 // a better way to communicate whether this was a miss or null,
7983 // boolean, undefined, etc.
7984 if (!oldFiber) {
7985 oldFiber = nextOldFiber;
7986 }
7987 break;
7988 }
7989 if (shouldTrackSideEffects) {
7990 if (oldFiber && newFiber.alternate === null) {
7991 // We matched the slot, but we didn't reuse the existing fiber, so we
7992 // need to delete the existing child.
7993 deleteChild(returnFiber, oldFiber);
7994 }
7995 }
7996 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
7997 if (previousNewFiber === null) {
7998 // TODO: Move out of the loop. This only happens for the first run.
7999 resultingFirstChild = newFiber;
8000 } else {
8001 // TODO: Defer siblings if we're not at the right index for this slot.
8002 // I.e. if we had null values before, then we want to defer this
8003 // for each null value. However, we also don't want to call updateSlot
8004 // with the previous one.
8005 previousNewFiber.sibling = newFiber;
8006 }
8007 previousNewFiber = newFiber;
8008 oldFiber = nextOldFiber;
8009 }
8010
8011 if (step.done) {
8012 // We've reached the end of the new children. We can delete the rest.
8013 deleteRemainingChildren(returnFiber, oldFiber);
8014 return resultingFirstChild;
8015 }
8016
8017 if (oldFiber === null) {
8018 // If we don't have any more existing children we can choose a fast path
8019 // since the rest will all be insertions.
8020 for (; !step.done; newIdx++, step = newChildren.next()) {
8021 var _newFiber3 = createChild(returnFiber, step.value, expirationTime);
8022 if (_newFiber3 === null) {
8023 continue;
8024 }
8025 lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx);
8026 if (previousNewFiber === null) {
8027 // TODO: Move out of the loop. This only happens for the first run.
8028 resultingFirstChild = _newFiber3;
8029 } else {
8030 previousNewFiber.sibling = _newFiber3;
8031 }
8032 previousNewFiber = _newFiber3;
8033 }
8034 return resultingFirstChild;
8035 }
8036
8037 // Add all children to a key map for quick lookups.
8038 var existingChildren = mapRemainingChildren(returnFiber, oldFiber);
8039
8040 // Keep scanning and use the map to restore deleted items as moves.
8041 for (; !step.done; newIdx++, step = newChildren.next()) {
8042 var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, expirationTime);
8043 if (_newFiber4 !== null) {
8044 if (shouldTrackSideEffects) {
8045 if (_newFiber4.alternate !== null) {
8046 // The new fiber is a work in progress, but if there exists a
8047 // current, that means that we reused the fiber. We need to delete
8048 // it from the child list so that we don't add it to the deletion
8049 // list.
8050 existingChildren['delete'](_newFiber4.key === null ? newIdx : _newFiber4.key);
8051 }
8052 }
8053 lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx);
8054 if (previousNewFiber === null) {
8055 resultingFirstChild = _newFiber4;
8056 } else {
8057 previousNewFiber.sibling = _newFiber4;
8058 }
8059 previousNewFiber = _newFiber4;
8060 }
8061 }
8062
8063 if (shouldTrackSideEffects) {
8064 // Any existing children that weren't consumed above were deleted. We need
8065 // to add them to the deletion list.
8066 existingChildren.forEach(function (child) {
8067 return deleteChild(returnFiber, child);
8068 });
8069 }
8070
8071 return resultingFirstChild;
8072 }
8073
8074 function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, expirationTime) {
8075 // There's no need to check for keys on text nodes since we don't have a
8076 // way to define them.
8077 if (currentFirstChild !== null && currentFirstChild.tag === HostText) {
8078 // We already have an existing node so let's just update it and delete
8079 // the rest.
8080 deleteRemainingChildren(returnFiber, currentFirstChild.sibling);
8081 var existing = useFiber(currentFirstChild, textContent, expirationTime);
8082 existing['return'] = returnFiber;
8083 return existing;
8084 }
8085 // The existing first child is not a text node so we need to create one
8086 // and delete the existing ones.
8087 deleteRemainingChildren(returnFiber, currentFirstChild);
8088 var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime);
8089 created['return'] = returnFiber;
8090 return created;
8091 }
8092
8093 function reconcileSingleElement(returnFiber, currentFirstChild, element, expirationTime) {
8094 var key = element.key;
8095 var child = currentFirstChild;
8096 while (child !== null) {
8097 // TODO: If key === null and child.key === null, then this only applies to
8098 // the first item in the list.
8099 if (child.key === key) {
8100 if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.type === element.type) {
8101 deleteRemainingChildren(returnFiber, child.sibling);
8102 var existing = useFiber(child, element.type === REACT_FRAGMENT_TYPE ? element.props.children : element.props, expirationTime);
8103 existing.ref = coerceRef(child, element);
8104 existing['return'] = returnFiber;
8105 {
8106 existing._debugSource = element._source;
8107 existing._debugOwner = element._owner;
8108 }
8109 return existing;
8110 } else {
8111 deleteRemainingChildren(returnFiber, child);
8112 break;
8113 }
8114 } else {
8115 deleteChild(returnFiber, child);
8116 }
8117 child = child.sibling;
8118 }
8119
8120 if (element.type === REACT_FRAGMENT_TYPE) {
8121 var created = createFiberFromFragment(element.props.children, returnFiber.internalContextTag, expirationTime, element.key);
8122 created['return'] = returnFiber;
8123 return created;
8124 } else {
8125 var _created4 = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime);
8126 _created4.ref = coerceRef(currentFirstChild, element);
8127 _created4['return'] = returnFiber;
8128 return _created4;
8129 }
8130 }
8131
8132 function reconcileSinglePortal(returnFiber, currentFirstChild, portal, expirationTime) {
8133 var key = portal.key;
8134 var child = currentFirstChild;
8135 while (child !== null) {
8136 // TODO: If key === null and child.key === null, then this only applies to
8137 // the first item in the list.
8138 if (child.key === key) {
8139 if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) {
8140 deleteRemainingChildren(returnFiber, child.sibling);
8141 var existing = useFiber(child, portal.children || [], expirationTime);
8142 existing['return'] = returnFiber;
8143 return existing;
8144 } else {
8145 deleteRemainingChildren(returnFiber, child);
8146 break;
8147 }
8148 } else {
8149 deleteChild(returnFiber, child);
8150 }
8151 child = child.sibling;
8152 }
8153
8154 var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime);
8155 created['return'] = returnFiber;
8156 return created;
8157 }
8158
8159 // This API will tag the children with the side-effect of the reconciliation
8160 // itself. They will be added to the side-effect list as we pass through the
8161 // children and the parent.
8162 function reconcileChildFibers(returnFiber, currentFirstChild, newChild, expirationTime) {
8163 // This function is not recursive.
8164 // If the top level item is an array, we treat it as a set of children,
8165 // not as a fragment. Nested arrays on the other hand will be treated as
8166 // fragment nodes. Recursion happens at the normal flow.
8167
8168 // Handle top level unkeyed fragments as if they were arrays.
8169 // This leads to an ambiguity between <>{[...]}</> and <>...</>.
8170 // We treat the ambiguous cases above the same.
8171 if (typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null) {
8172 newChild = newChild.props.children;
8173 }
8174
8175 // Handle object types
8176 var isObject = typeof newChild === 'object' && newChild !== null;
8177
8178 if (isObject) {
8179 switch (newChild.$$typeof) {
8180 case REACT_ELEMENT_TYPE:
8181 return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, expirationTime));
8182 case REACT_PORTAL_TYPE:
8183 return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, expirationTime));
8184 }
8185 }
8186
8187 if (typeof newChild === 'string' || typeof newChild === 'number') {
8188 return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, expirationTime));
8189 }
8190
8191 if (isArray$1(newChild)) {
8192 return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, expirationTime);
8193 }
8194
8195 if (getIteratorFn(newChild)) {
8196 return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, expirationTime);
8197 }
8198
8199 if (isObject) {
8200 throwOnInvalidObjectType(returnFiber, newChild);
8201 }
8202
8203 {
8204 if (typeof newChild === 'function') {
8205 warnOnFunctionType();
8206 }
8207 }
8208 if (typeof newChild === 'undefined') {
8209 // If the new child is undefined, and the return fiber is a composite
8210 // component, throw an error. If Fiber return types are disabled,
8211 // we already threw above.
8212 switch (returnFiber.tag) {
8213 case ClassComponent:
8214 {
8215 {
8216 var instance = returnFiber.stateNode;
8217 if (instance.render._isMockFunction) {
8218 // We allow auto-mocks to proceed as if they're returning null.
8219 break;
8220 }
8221 }
8222 }
8223 // Intentionally fall through to the next case, which handles both
8224 // functions and classes
8225 // eslint-disable-next-lined no-fallthrough
8226 case FunctionalComponent:
8227 {
8228 var Component = returnFiber.type;
8229 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');
8230 }
8231 }
8232 }
8233
8234 // Remaining cases are all treated as empty.
8235 return deleteRemainingChildren(returnFiber, currentFirstChild);
8236 }
8237
8238 return reconcileChildFibers;
8239}
8240
8241var reconcileChildFibers = ChildReconciler(true);
8242var mountChildFibers = ChildReconciler(false);
8243
8244function cloneChildFibers(current, workInProgress) {
8245 !(current === null || workInProgress.child === current.child) ? invariant_1(false, 'Resuming work not yet implemented.') : void 0;
8246
8247 if (workInProgress.child === null) {
8248 return;
8249 }
8250
8251 var currentChild = workInProgress.child;
8252 var newChild = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
8253 workInProgress.child = newChild;
8254
8255 newChild['return'] = workInProgress;
8256 while (currentChild.sibling !== null) {
8257 currentChild = currentChild.sibling;
8258 newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
8259 newChild['return'] = workInProgress;
8260 }
8261 newChild.sibling = null;
8262}
8263
8264var warnedAboutStatelessRefs = void 0;
8265
8266{
8267 warnedAboutStatelessRefs = {};
8268}
8269
8270var ReactFiberBeginWork = function (config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber) {
8271 var shouldSetTextContent = config.shouldSetTextContent,
8272 useSyncScheduling = config.useSyncScheduling,
8273 shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree;
8274 var pushHostContext = hostContext.pushHostContext,
8275 pushHostContainer = hostContext.pushHostContainer;
8276 var enterHydrationState = hydrationContext.enterHydrationState,
8277 resetHydrationState = hydrationContext.resetHydrationState,
8278 tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance;
8279
8280 var _ReactFiberClassCompo = ReactFiberClassComponent(scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState),
8281 adoptClassInstance = _ReactFiberClassCompo.adoptClassInstance,
8282 constructClassInstance = _ReactFiberClassCompo.constructClassInstance,
8283 mountClassInstance = _ReactFiberClassCompo.mountClassInstance,
8284 updateClassInstance = _ReactFiberClassCompo.updateClassInstance;
8285
8286 // TODO: Remove this and use reconcileChildrenAtExpirationTime directly.
8287
8288
8289 function reconcileChildren(current, workInProgress, nextChildren) {
8290 reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, workInProgress.expirationTime);
8291 }
8292
8293 function reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, renderExpirationTime) {
8294 if (current === null) {
8295 // If this is a fresh new component that hasn't been rendered yet, we
8296 // won't update its child set by applying minimal side-effects. Instead,
8297 // we will add them all to the child before it gets rendered. That means
8298 // we can optimize this reconciliation pass by not tracking side-effects.
8299 workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
8300 } else {
8301 // If the current child is the same as the work in progress, it means that
8302 // we haven't yet started any work on these children. Therefore, we use
8303 // the clone algorithm to create a copy of all the current children.
8304
8305 // If we had any progressed work already, that is invalid at this point so
8306 // let's throw it out.
8307 workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderExpirationTime);
8308 }
8309 }
8310
8311 function updateFragment(current, workInProgress) {
8312 var nextChildren = workInProgress.pendingProps;
8313 if (hasContextChanged()) {
8314 // Normally we can bail out on props equality but if context has changed
8315 // we don't do the bailout and we have to reuse existing props instead.
8316 } else if (nextChildren === null || workInProgress.memoizedProps === nextChildren) {
8317 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8318 }
8319 reconcileChildren(current, workInProgress, nextChildren);
8320 memoizeProps(workInProgress, nextChildren);
8321 return workInProgress.child;
8322 }
8323
8324 function markRef(current, workInProgress) {
8325 var ref = workInProgress.ref;
8326 if (ref !== null && (!current || current.ref !== ref)) {
8327 // Schedule a Ref effect
8328 workInProgress.effectTag |= Ref;
8329 }
8330 }
8331
8332 function updateFunctionalComponent(current, workInProgress) {
8333 var fn = workInProgress.type;
8334 var nextProps = workInProgress.pendingProps;
8335
8336 if (hasContextChanged()) {
8337 // Normally we can bail out on props equality but if context has changed
8338 // we don't do the bailout and we have to reuse existing props instead.
8339 } else {
8340 if (workInProgress.memoizedProps === nextProps) {
8341 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8342 }
8343 // TODO: consider bringing fn.shouldComponentUpdate() back.
8344 // It used to be here.
8345 }
8346
8347 var unmaskedContext = getUnmaskedContext(workInProgress);
8348 var context = getMaskedContext(workInProgress, unmaskedContext);
8349
8350 var nextChildren = void 0;
8351
8352 {
8353 ReactCurrentOwner.current = workInProgress;
8354 ReactDebugCurrentFiber.setCurrentPhase('render');
8355 nextChildren = fn(nextProps, context);
8356 ReactDebugCurrentFiber.setCurrentPhase(null);
8357 }
8358 // React DevTools reads this flag.
8359 workInProgress.effectTag |= PerformedWork;
8360 reconcileChildren(current, workInProgress, nextChildren);
8361 memoizeProps(workInProgress, nextProps);
8362 return workInProgress.child;
8363 }
8364
8365 function updateClassComponent(current, workInProgress, renderExpirationTime) {
8366 // Push context providers early to prevent context stack mismatches.
8367 // During mounting we don't know the child context yet as the instance doesn't exist.
8368 // We will invalidate the child context in finishClassComponent() right after rendering.
8369 var hasContext = pushContextProvider(workInProgress);
8370
8371 var shouldUpdate = void 0;
8372 if (current === null) {
8373 if (!workInProgress.stateNode) {
8374 // In the initial pass we might need to construct the instance.
8375 constructClassInstance(workInProgress, workInProgress.pendingProps);
8376 mountClassInstance(workInProgress, renderExpirationTime);
8377
8378 // Simulate an async bailout/interruption by invoking lifecycle twice.
8379 // We do this here rather than inside of ReactFiberClassComponent,
8380 // To more realistically simulate the interruption behavior of async,
8381 // Which would never call componentWillMount() twice on the same instance.
8382 if (debugRenderPhaseSideEffects) {
8383 constructClassInstance(workInProgress, workInProgress.pendingProps);
8384 mountClassInstance(workInProgress, renderExpirationTime);
8385 }
8386
8387 shouldUpdate = true;
8388 } else {
8389 invariant_1(false, 'Resuming work not yet implemented.');
8390 // In a resume, we'll already have an instance we can reuse.
8391 // shouldUpdate = resumeMountClassInstance(workInProgress, renderExpirationTime);
8392 }
8393 } else {
8394 shouldUpdate = updateClassInstance(current, workInProgress, renderExpirationTime);
8395 }
8396 return finishClassComponent(current, workInProgress, shouldUpdate, hasContext);
8397 }
8398
8399 function finishClassComponent(current, workInProgress, shouldUpdate, hasContext) {
8400 // Refs should update even if shouldComponentUpdate returns false
8401 markRef(current, workInProgress);
8402
8403 if (!shouldUpdate) {
8404 // Context providers should defer to sCU for rendering
8405 if (hasContext) {
8406 invalidateContextProvider(workInProgress, false);
8407 }
8408
8409 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8410 }
8411
8412 var instance = workInProgress.stateNode;
8413
8414 // Rerender
8415 ReactCurrentOwner.current = workInProgress;
8416 var nextChildren = void 0;
8417 {
8418 ReactDebugCurrentFiber.setCurrentPhase('render');
8419 nextChildren = instance.render();
8420 if (debugRenderPhaseSideEffects) {
8421 instance.render();
8422 }
8423 ReactDebugCurrentFiber.setCurrentPhase(null);
8424 }
8425 // React DevTools reads this flag.
8426 workInProgress.effectTag |= PerformedWork;
8427 reconcileChildren(current, workInProgress, nextChildren);
8428 // Memoize props and state using the values we just used to render.
8429 // TODO: Restructure so we never read values from the instance.
8430 memoizeState(workInProgress, instance.state);
8431 memoizeProps(workInProgress, instance.props);
8432
8433 // The context might have changed so we need to recalculate it.
8434 if (hasContext) {
8435 invalidateContextProvider(workInProgress, true);
8436 }
8437
8438 return workInProgress.child;
8439 }
8440
8441 function pushHostRootContext(workInProgress) {
8442 var root = workInProgress.stateNode;
8443 if (root.pendingContext) {
8444 pushTopLevelContextObject(workInProgress, root.pendingContext, root.pendingContext !== root.context);
8445 } else if (root.context) {
8446 // Should always be set
8447 pushTopLevelContextObject(workInProgress, root.context, false);
8448 }
8449 pushHostContainer(workInProgress, root.containerInfo);
8450 }
8451
8452 function updateHostRoot(current, workInProgress, renderExpirationTime) {
8453 pushHostRootContext(workInProgress);
8454 var updateQueue = workInProgress.updateQueue;
8455 if (updateQueue !== null) {
8456 var prevState = workInProgress.memoizedState;
8457 var state = processUpdateQueue(current, workInProgress, updateQueue, null, null, renderExpirationTime);
8458 if (prevState === state) {
8459 // If the state is the same as before, that's a bailout because we had
8460 // no work that expires at this time.
8461 resetHydrationState();
8462 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8463 }
8464 var element = state.element;
8465 var root = workInProgress.stateNode;
8466 if ((current === null || current.child === null) && root.hydrate && enterHydrationState(workInProgress)) {
8467 // If we don't have any current children this might be the first pass.
8468 // We always try to hydrate. If this isn't a hydration pass there won't
8469 // be any children to hydrate which is effectively the same thing as
8470 // not hydrating.
8471
8472 // This is a bit of a hack. We track the host root as a placement to
8473 // know that we're currently in a mounting state. That way isMounted
8474 // works as expected. We must reset this before committing.
8475 // TODO: Delete this when we delete isMounted and findDOMNode.
8476 workInProgress.effectTag |= Placement;
8477
8478 // Ensure that children mount into this root without tracking
8479 // side-effects. This ensures that we don't store Placement effects on
8480 // nodes that will be hydrated.
8481 workInProgress.child = mountChildFibers(workInProgress, null, element, renderExpirationTime);
8482 } else {
8483 // Otherwise reset hydration state in case we aborted and resumed another
8484 // root.
8485 resetHydrationState();
8486 reconcileChildren(current, workInProgress, element);
8487 }
8488 memoizeState(workInProgress, state);
8489 return workInProgress.child;
8490 }
8491 resetHydrationState();
8492 // If there is no update queue, that's a bailout because the root has no props.
8493 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8494 }
8495
8496 function updateHostComponent(current, workInProgress, renderExpirationTime) {
8497 pushHostContext(workInProgress);
8498
8499 if (current === null) {
8500 tryToClaimNextHydratableInstance(workInProgress);
8501 }
8502
8503 var type = workInProgress.type;
8504 var memoizedProps = workInProgress.memoizedProps;
8505 var nextProps = workInProgress.pendingProps;
8506 var prevProps = current !== null ? current.memoizedProps : null;
8507
8508 if (hasContextChanged()) {
8509 // Normally we can bail out on props equality but if context has changed
8510 // we don't do the bailout and we have to reuse existing props instead.
8511 } else if (memoizedProps === nextProps) {
8512 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8513 }
8514
8515 var nextChildren = nextProps.children;
8516 var isDirectTextChild = shouldSetTextContent(type, nextProps);
8517
8518 if (isDirectTextChild) {
8519 // We special case a direct text child of a host node. This is a common
8520 // case. We won't handle it as a reified child. We will instead handle
8521 // this in the host environment that also have access to this prop. That
8522 // avoids allocating another HostText fiber and traversing it.
8523 nextChildren = null;
8524 } else if (prevProps && shouldSetTextContent(type, prevProps)) {
8525 // If we're switching from a direct text child to a normal child, or to
8526 // empty, we need to schedule the text content to be reset.
8527 workInProgress.effectTag |= ContentReset;
8528 }
8529
8530 markRef(current, workInProgress);
8531
8532 // Check the host config to see if the children are offscreen/hidden.
8533 if (renderExpirationTime !== Never && !useSyncScheduling && shouldDeprioritizeSubtree(type, nextProps)) {
8534 // Down-prioritize the children.
8535 workInProgress.expirationTime = Never;
8536 // Bailout and come back to this fiber later.
8537 return null;
8538 }
8539
8540 reconcileChildren(current, workInProgress, nextChildren);
8541 memoizeProps(workInProgress, nextProps);
8542 return workInProgress.child;
8543 }
8544
8545 function updateHostText(current, workInProgress) {
8546 if (current === null) {
8547 tryToClaimNextHydratableInstance(workInProgress);
8548 }
8549 var nextProps = workInProgress.pendingProps;
8550 memoizeProps(workInProgress, nextProps);
8551 // Nothing to do here. This is terminal. We'll do the completion step
8552 // immediately after.
8553 return null;
8554 }
8555
8556 function mountIndeterminateComponent(current, workInProgress, renderExpirationTime) {
8557 !(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;
8558 var fn = workInProgress.type;
8559 var props = workInProgress.pendingProps;
8560 var unmaskedContext = getUnmaskedContext(workInProgress);
8561 var context = getMaskedContext(workInProgress, unmaskedContext);
8562
8563 var value = void 0;
8564
8565 {
8566 if (fn.prototype && typeof fn.prototype.render === 'function') {
8567 var componentName = getComponentName(workInProgress);
8568 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);
8569 }
8570 ReactCurrentOwner.current = workInProgress;
8571 value = fn(props, context);
8572 }
8573 // React DevTools reads this flag.
8574 workInProgress.effectTag |= PerformedWork;
8575
8576 if (typeof value === 'object' && value !== null && typeof value.render === 'function') {
8577 // Proceed under the assumption that this is a class instance
8578 workInProgress.tag = ClassComponent;
8579
8580 // Push context providers early to prevent context stack mismatches.
8581 // During mounting we don't know the child context yet as the instance doesn't exist.
8582 // We will invalidate the child context in finishClassComponent() right after rendering.
8583 var hasContext = pushContextProvider(workInProgress);
8584 adoptClassInstance(workInProgress, value);
8585 mountClassInstance(workInProgress, renderExpirationTime);
8586 return finishClassComponent(current, workInProgress, true, hasContext);
8587 } else {
8588 // Proceed under the assumption that this is a functional component
8589 workInProgress.tag = FunctionalComponent;
8590 {
8591 var Component = workInProgress.type;
8592
8593 if (Component) {
8594 warning_1(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component');
8595 }
8596 if (workInProgress.ref !== null) {
8597 var info = '';
8598 var ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
8599 if (ownerName) {
8600 info += '\n\nCheck the render method of `' + ownerName + '`.';
8601 }
8602
8603 var warningKey = ownerName || workInProgress._debugID || '';
8604 var debugSource = workInProgress._debugSource;
8605 if (debugSource) {
8606 warningKey = debugSource.fileName + ':' + debugSource.lineNumber;
8607 }
8608 if (!warnedAboutStatelessRefs[warningKey]) {
8609 warnedAboutStatelessRefs[warningKey] = true;
8610 warning_1(false, 'Stateless function components cannot be given refs. ' + 'Attempts to access this ref will fail.%s%s', info, ReactDebugCurrentFiber.getCurrentFiberStackAddendum());
8611 }
8612 }
8613 }
8614 reconcileChildren(current, workInProgress, value);
8615 memoizeProps(workInProgress, props);
8616 return workInProgress.child;
8617 }
8618 }
8619
8620 function updateCallComponent(current, workInProgress, renderExpirationTime) {
8621 var nextProps = workInProgress.pendingProps;
8622 if (hasContextChanged()) {
8623 // Normally we can bail out on props equality but if context has changed
8624 // we don't do the bailout and we have to reuse existing props instead.
8625 } else if (workInProgress.memoizedProps === nextProps) {
8626 nextProps = workInProgress.memoizedProps;
8627 // TODO: When bailing out, we might need to return the stateNode instead
8628 // of the child. To check it for work.
8629 // return bailoutOnAlreadyFinishedWork(current, workInProgress);
8630 }
8631
8632 var nextChildren = nextProps.children;
8633
8634 // The following is a fork of reconcileChildrenAtExpirationTime but using
8635 // stateNode to store the child.
8636 if (current === null) {
8637 workInProgress.stateNode = mountChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
8638 } else {
8639 workInProgress.stateNode = reconcileChildFibers(workInProgress, current.stateNode, nextChildren, renderExpirationTime);
8640 }
8641
8642 memoizeProps(workInProgress, nextProps);
8643 // This doesn't take arbitrary time so we could synchronously just begin
8644 // eagerly do the work of workInProgress.child as an optimization.
8645 return workInProgress.stateNode;
8646 }
8647
8648 function updatePortalComponent(current, workInProgress, renderExpirationTime) {
8649 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
8650 var nextChildren = workInProgress.pendingProps;
8651 if (hasContextChanged()) {
8652 // Normally we can bail out on props equality but if context has changed
8653 // we don't do the bailout and we have to reuse existing props instead.
8654 } else if (workInProgress.memoizedProps === nextChildren) {
8655 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8656 }
8657
8658 if (current === null) {
8659 // Portals are special because we don't append the children during mount
8660 // but at commit. Therefore we need to track insertions which the normal
8661 // flow doesn't do during mount. This doesn't happen at the root because
8662 // the root always starts with a "current" with a null child.
8663 // TODO: Consider unifying this with how the root works.
8664 workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
8665 memoizeProps(workInProgress, nextChildren);
8666 } else {
8667 reconcileChildren(current, workInProgress, nextChildren);
8668 memoizeProps(workInProgress, nextChildren);
8669 }
8670 return workInProgress.child;
8671 }
8672
8673 /*
8674 function reuseChildrenEffects(returnFiber : Fiber, firstChild : Fiber) {
8675 let child = firstChild;
8676 do {
8677 // Ensure that the first and last effect of the parent corresponds
8678 // to the children's first and last effect.
8679 if (!returnFiber.firstEffect) {
8680 returnFiber.firstEffect = child.firstEffect;
8681 }
8682 if (child.lastEffect) {
8683 if (returnFiber.lastEffect) {
8684 returnFiber.lastEffect.nextEffect = child.firstEffect;
8685 }
8686 returnFiber.lastEffect = child.lastEffect;
8687 }
8688 } while (child = child.sibling);
8689 }
8690 */
8691
8692 function bailoutOnAlreadyFinishedWork(current, workInProgress) {
8693 cancelWorkTimer(workInProgress);
8694
8695 // TODO: We should ideally be able to bail out early if the children have no
8696 // more work to do. However, since we don't have a separation of this
8697 // Fiber's priority and its children yet - we don't know without doing lots
8698 // of the same work we do anyway. Once we have that separation we can just
8699 // bail out here if the children has no more work at this priority level.
8700 // if (workInProgress.priorityOfChildren <= priorityLevel) {
8701 // // If there are side-effects in these children that have not yet been
8702 // // committed we need to ensure that they get properly transferred up.
8703 // if (current && current.child !== workInProgress.child) {
8704 // reuseChildrenEffects(workInProgress, child);
8705 // }
8706 // return null;
8707 // }
8708
8709 cloneChildFibers(current, workInProgress);
8710 return workInProgress.child;
8711 }
8712
8713 function bailoutOnLowPriority(current, workInProgress) {
8714 cancelWorkTimer(workInProgress);
8715
8716 // TODO: Handle HostComponent tags here as well and call pushHostContext()?
8717 // See PR 8590 discussion for context
8718 switch (workInProgress.tag) {
8719 case HostRoot:
8720 pushHostRootContext(workInProgress);
8721 break;
8722 case ClassComponent:
8723 pushContextProvider(workInProgress);
8724 break;
8725 case HostPortal:
8726 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
8727 break;
8728 }
8729 // TODO: What if this is currently in progress?
8730 // How can that happen? How is this not being cloned?
8731 return null;
8732 }
8733
8734 // TODO: Delete memoizeProps/State and move to reconcile/bailout instead
8735 function memoizeProps(workInProgress, nextProps) {
8736 workInProgress.memoizedProps = nextProps;
8737 }
8738
8739 function memoizeState(workInProgress, nextState) {
8740 workInProgress.memoizedState = nextState;
8741 // Don't reset the updateQueue, in case there are pending updates. Resetting
8742 // is handled by processUpdateQueue.
8743 }
8744
8745 function beginWork(current, workInProgress, renderExpirationTime) {
8746 if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
8747 return bailoutOnLowPriority(current, workInProgress);
8748 }
8749
8750 switch (workInProgress.tag) {
8751 case IndeterminateComponent:
8752 return mountIndeterminateComponent(current, workInProgress, renderExpirationTime);
8753 case FunctionalComponent:
8754 return updateFunctionalComponent(current, workInProgress);
8755 case ClassComponent:
8756 return updateClassComponent(current, workInProgress, renderExpirationTime);
8757 case HostRoot:
8758 return updateHostRoot(current, workInProgress, renderExpirationTime);
8759 case HostComponent:
8760 return updateHostComponent(current, workInProgress, renderExpirationTime);
8761 case HostText:
8762 return updateHostText(current, workInProgress);
8763 case CallHandlerPhase:
8764 // This is a restart. Reset the tag to the initial phase.
8765 workInProgress.tag = CallComponent;
8766 // Intentionally fall through since this is now the same.
8767 case CallComponent:
8768 return updateCallComponent(current, workInProgress, renderExpirationTime);
8769 case ReturnComponent:
8770 // A return component is just a placeholder, we can just run through the
8771 // next one immediately.
8772 return null;
8773 case HostPortal:
8774 return updatePortalComponent(current, workInProgress, renderExpirationTime);
8775 case Fragment:
8776 return updateFragment(current, workInProgress);
8777 default:
8778 invariant_1(false, 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.');
8779 }
8780 }
8781
8782 function beginFailedWork(current, workInProgress, renderExpirationTime) {
8783 // Push context providers here to avoid a push/pop context mismatch.
8784 switch (workInProgress.tag) {
8785 case ClassComponent:
8786 pushContextProvider(workInProgress);
8787 break;
8788 case HostRoot:
8789 pushHostRootContext(workInProgress);
8790 break;
8791 default:
8792 invariant_1(false, 'Invalid type of work. This error is likely caused by a bug in React. Please file an issue.');
8793 }
8794
8795 // Add an error effect so we can handle the error during the commit phase
8796 workInProgress.effectTag |= Err;
8797
8798 // This is a weird case where we do "resume" work ? work that failed on
8799 // our first attempt. Because we no longer have a notion of "progressed
8800 // deletions," reset the child to the current child to make sure we delete
8801 // it again. TODO: Find a better way to handle this, perhaps during a more
8802 // general overhaul of error handling.
8803 if (current === null) {
8804 workInProgress.child = null;
8805 } else if (workInProgress.child !== current.child) {
8806 workInProgress.child = current.child;
8807 }
8808
8809 if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
8810 return bailoutOnLowPriority(current, workInProgress);
8811 }
8812
8813 // If we don't bail out, we're going be recomputing our children so we need
8814 // to drop our effect list.
8815 workInProgress.firstEffect = null;
8816 workInProgress.lastEffect = null;
8817
8818 // Unmount the current children as if the component rendered null
8819 var nextChildren = null;
8820 reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, renderExpirationTime);
8821
8822 if (workInProgress.tag === ClassComponent) {
8823 var instance = workInProgress.stateNode;
8824 workInProgress.memoizedProps = instance.props;
8825 workInProgress.memoizedState = instance.state;
8826 }
8827
8828 return workInProgress.child;
8829 }
8830
8831 return {
8832 beginWork: beginWork,
8833 beginFailedWork: beginFailedWork
8834 };
8835};
8836
8837var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
8838 var createInstance = config.createInstance,
8839 createTextInstance = config.createTextInstance,
8840 appendInitialChild = config.appendInitialChild,
8841 finalizeInitialChildren = config.finalizeInitialChildren,
8842 prepareUpdate = config.prepareUpdate,
8843 mutation = config.mutation,
8844 persistence = config.persistence;
8845 var getRootHostContainer = hostContext.getRootHostContainer,
8846 popHostContext = hostContext.popHostContext,
8847 getHostContext = hostContext.getHostContext,
8848 popHostContainer = hostContext.popHostContainer;
8849 var prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance,
8850 prepareToHydrateHostTextInstance = hydrationContext.prepareToHydrateHostTextInstance,
8851 popHydrationState = hydrationContext.popHydrationState;
8852
8853
8854 function markUpdate(workInProgress) {
8855 // Tag the fiber with an update effect. This turns a Placement into
8856 // an UpdateAndPlacement.
8857 workInProgress.effectTag |= Update;
8858 }
8859
8860 function markRef(workInProgress) {
8861 workInProgress.effectTag |= Ref;
8862 }
8863
8864 function appendAllReturns(returns, workInProgress) {
8865 var node = workInProgress.stateNode;
8866 if (node) {
8867 node['return'] = workInProgress;
8868 }
8869 while (node !== null) {
8870 if (node.tag === HostComponent || node.tag === HostText || node.tag === HostPortal) {
8871 invariant_1(false, 'A call cannot have host component children.');
8872 } else if (node.tag === ReturnComponent) {
8873 returns.push(node.pendingProps.value);
8874 } else if (node.child !== null) {
8875 node.child['return'] = node;
8876 node = node.child;
8877 continue;
8878 }
8879 while (node.sibling === null) {
8880 if (node['return'] === null || node['return'] === workInProgress) {
8881 return;
8882 }
8883 node = node['return'];
8884 }
8885 node.sibling['return'] = node['return'];
8886 node = node.sibling;
8887 }
8888 }
8889
8890 function moveCallToHandlerPhase(current, workInProgress, renderExpirationTime) {
8891 var props = workInProgress.memoizedProps;
8892 !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;
8893
8894 // First step of the call has completed. Now we need to do the second.
8895 // TODO: It would be nice to have a multi stage call represented by a
8896 // single component, or at least tail call optimize nested ones. Currently
8897 // that requires additional fields that we don't want to add to the fiber.
8898 // So this requires nested handlers.
8899 // Note: This doesn't mutate the alternate node. I don't think it needs to
8900 // since this stage is reset for every pass.
8901 workInProgress.tag = CallHandlerPhase;
8902
8903 // Build up the returns.
8904 // TODO: Compare this to a generator or opaque helpers like Children.
8905 var returns = [];
8906 appendAllReturns(returns, workInProgress);
8907 var fn = props.handler;
8908 var childProps = props.props;
8909 var nextChildren = fn(childProps, returns);
8910
8911 var currentFirstChild = current !== null ? current.child : null;
8912 workInProgress.child = reconcileChildFibers(workInProgress, currentFirstChild, nextChildren, renderExpirationTime);
8913 return workInProgress.child;
8914 }
8915
8916 function appendAllChildren(parent, workInProgress) {
8917 // We only have the top Fiber that was created but we need recurse down its
8918 // children to find all the terminal nodes.
8919 var node = workInProgress.child;
8920 while (node !== null) {
8921 if (node.tag === HostComponent || node.tag === HostText) {
8922 appendInitialChild(parent, node.stateNode);
8923 } else if (node.tag === HostPortal) {
8924 // If we have a portal child, then we don't want to traverse
8925 // down its children. Instead, we'll get insertions from each child in
8926 // the portal directly.
8927 } else if (node.child !== null) {
8928 node.child['return'] = node;
8929 node = node.child;
8930 continue;
8931 }
8932 if (node === workInProgress) {
8933 return;
8934 }
8935 while (node.sibling === null) {
8936 if (node['return'] === null || node['return'] === workInProgress) {
8937 return;
8938 }
8939 node = node['return'];
8940 }
8941 node.sibling['return'] = node['return'];
8942 node = node.sibling;
8943 }
8944 }
8945
8946 var updateHostContainer = void 0;
8947 var updateHostComponent = void 0;
8948 var updateHostText = void 0;
8949 if (mutation) {
8950 if (enableMutatingReconciler) {
8951 // Mutation mode
8952 updateHostContainer = function (workInProgress) {
8953 // Noop
8954 };
8955 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance, currentHostContext) {
8956 // TODO: Type this specific to this type of component.
8957 workInProgress.updateQueue = updatePayload;
8958 // If the update payload indicates that there is a change or if there
8959 // is a new ref we mark this as an update. All the work is done in commitWork.
8960 if (updatePayload) {
8961 markUpdate(workInProgress);
8962 }
8963 };
8964 updateHostText = function (current, workInProgress, oldText, newText) {
8965 // If the text differs, mark it as an update. All the work in done in commitWork.
8966 if (oldText !== newText) {
8967 markUpdate(workInProgress);
8968 }
8969 };
8970 } else {
8971 invariant_1(false, 'Mutating reconciler is disabled.');
8972 }
8973 } else if (persistence) {
8974 if (enablePersistentReconciler) {
8975 // Persistent host tree mode
8976 var cloneInstance = persistence.cloneInstance,
8977 createContainerChildSet = persistence.createContainerChildSet,
8978 appendChildToContainerChildSet = persistence.appendChildToContainerChildSet,
8979 finalizeContainerChildren = persistence.finalizeContainerChildren;
8980
8981 // An unfortunate fork of appendAllChildren because we have two different parent types.
8982
8983 var appendAllChildrenToContainer = function (containerChildSet, workInProgress) {
8984 // We only have the top Fiber that was created but we need recurse down its
8985 // children to find all the terminal nodes.
8986 var node = workInProgress.child;
8987 while (node !== null) {
8988 if (node.tag === HostComponent || node.tag === HostText) {
8989 appendChildToContainerChildSet(containerChildSet, node.stateNode);
8990 } else if (node.tag === HostPortal) {
8991 // If we have a portal child, then we don't want to traverse
8992 // down its children. Instead, we'll get insertions from each child in
8993 // the portal directly.
8994 } else if (node.child !== null) {
8995 node.child['return'] = node;
8996 node = node.child;
8997 continue;
8998 }
8999 if (node === workInProgress) {
9000 return;
9001 }
9002 while (node.sibling === null) {
9003 if (node['return'] === null || node['return'] === workInProgress) {
9004 return;
9005 }
9006 node = node['return'];
9007 }
9008 node.sibling['return'] = node['return'];
9009 node = node.sibling;
9010 }
9011 };
9012 updateHostContainer = function (workInProgress) {
9013 var portalOrRoot = workInProgress.stateNode;
9014 var childrenUnchanged = workInProgress.firstEffect === null;
9015 if (childrenUnchanged) {
9016 // No changes, just reuse the existing instance.
9017 } else {
9018 var container = portalOrRoot.containerInfo;
9019 var newChildSet = createContainerChildSet(container);
9020 if (finalizeContainerChildren(container, newChildSet)) {
9021 markUpdate(workInProgress);
9022 }
9023 portalOrRoot.pendingChildren = newChildSet;
9024 // If children might have changed, we have to add them all to the set.
9025 appendAllChildrenToContainer(newChildSet, workInProgress);
9026 // Schedule an update on the container to swap out the container.
9027 markUpdate(workInProgress);
9028 }
9029 };
9030 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance, currentHostContext) {
9031 // If there are no effects associated with this node, then none of our children had any updates.
9032 // This guarantees that we can reuse all of them.
9033 var childrenUnchanged = workInProgress.firstEffect === null;
9034 var currentInstance = current.stateNode;
9035 if (childrenUnchanged && updatePayload === null) {
9036 // No changes, just reuse the existing instance.
9037 // Note that this might release a previous clone.
9038 workInProgress.stateNode = currentInstance;
9039 } else {
9040 var recyclableInstance = workInProgress.stateNode;
9041 var newInstance = cloneInstance(currentInstance, updatePayload, type, oldProps, newProps, workInProgress, childrenUnchanged, recyclableInstance);
9042 if (finalizeInitialChildren(newInstance, type, newProps, rootContainerInstance, currentHostContext)) {
9043 markUpdate(workInProgress);
9044 }
9045 workInProgress.stateNode = newInstance;
9046 if (childrenUnchanged) {
9047 // If there are no other effects in this tree, we need to flag this node as having one.
9048 // Even though we're not going to use it for anything.
9049 // Otherwise parents won't know that there are new children to propagate upwards.
9050 markUpdate(workInProgress);
9051 } else {
9052 // If children might have changed, we have to add them all to the set.
9053 appendAllChildren(newInstance, workInProgress);
9054 }
9055 }
9056 };
9057 updateHostText = function (current, workInProgress, oldText, newText) {
9058 if (oldText !== newText) {
9059 // If the text content differs, we'll create a new text instance for it.
9060 var rootContainerInstance = getRootHostContainer();
9061 var currentHostContext = getHostContext();
9062 workInProgress.stateNode = createTextInstance(newText, rootContainerInstance, currentHostContext, workInProgress);
9063 // We'll have to mark it as having an effect, even though we won't use the effect for anything.
9064 // This lets the parents know that at least one of their children has changed.
9065 markUpdate(workInProgress);
9066 }
9067 };
9068 } else {
9069 invariant_1(false, 'Persistent reconciler is disabled.');
9070 }
9071 } else {
9072 if (enableNoopReconciler) {
9073 // No host operations
9074 updateHostContainer = function (workInProgress) {
9075 // Noop
9076 };
9077 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance, currentHostContext) {
9078 // Noop
9079 };
9080 updateHostText = function (current, workInProgress, oldText, newText) {
9081 // Noop
9082 };
9083 } else {
9084 invariant_1(false, 'Noop reconciler is disabled.');
9085 }
9086 }
9087
9088 function completeWork(current, workInProgress, renderExpirationTime) {
9089 var newProps = workInProgress.pendingProps;
9090 switch (workInProgress.tag) {
9091 case FunctionalComponent:
9092 return null;
9093 case ClassComponent:
9094 {
9095 // We are leaving this subtree, so pop context if any.
9096 popContextProvider(workInProgress);
9097 return null;
9098 }
9099 case HostRoot:
9100 {
9101 popHostContainer(workInProgress);
9102 popTopLevelContextObject(workInProgress);
9103 var fiberRoot = workInProgress.stateNode;
9104 if (fiberRoot.pendingContext) {
9105 fiberRoot.context = fiberRoot.pendingContext;
9106 fiberRoot.pendingContext = null;
9107 }
9108
9109 if (current === null || current.child === null) {
9110 // If we hydrated, pop so that we can delete any remaining children
9111 // that weren't hydrated.
9112 popHydrationState(workInProgress);
9113 // This resets the hacky state to fix isMounted before committing.
9114 // TODO: Delete this when we delete isMounted and findDOMNode.
9115 workInProgress.effectTag &= ~Placement;
9116 }
9117 updateHostContainer(workInProgress);
9118 return null;
9119 }
9120 case HostComponent:
9121 {
9122 popHostContext(workInProgress);
9123 var rootContainerInstance = getRootHostContainer();
9124 var type = workInProgress.type;
9125 if (current !== null && workInProgress.stateNode != null) {
9126 // If we have an alternate, that means this is an update and we need to
9127 // schedule a side-effect to do the updates.
9128 var oldProps = current.memoizedProps;
9129 // If we get updated because one of our children updated, we don't
9130 // have newProps so we'll have to reuse them.
9131 // TODO: Split the update API as separate for the props vs. children.
9132 // Even better would be if children weren't special cased at all tho.
9133 var instance = workInProgress.stateNode;
9134 var currentHostContext = getHostContext();
9135 var updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext);
9136
9137 updateHostComponent(current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance, currentHostContext);
9138
9139 if (current.ref !== workInProgress.ref) {
9140 markRef(workInProgress);
9141 }
9142 } else {
9143 if (!newProps) {
9144 !(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;
9145 // This can happen when we abort work.
9146 return null;
9147 }
9148
9149 var _currentHostContext = getHostContext();
9150 // TODO: Move createInstance to beginWork and keep it on a context
9151 // "stack" as the parent. Then append children as we go in beginWork
9152 // or completeWork depending on we want to add then top->down or
9153 // bottom->up. Top->down is faster in IE11.
9154 var wasHydrated = popHydrationState(workInProgress);
9155 if (wasHydrated) {
9156 // TODO: Move this and createInstance step into the beginPhase
9157 // to consolidate.
9158 if (prepareToHydrateHostInstance(workInProgress, rootContainerInstance, _currentHostContext)) {
9159 // If changes to the hydrated node needs to be applied at the
9160 // commit-phase we mark this as such.
9161 markUpdate(workInProgress);
9162 }
9163 } else {
9164 var _instance = createInstance(type, newProps, rootContainerInstance, _currentHostContext, workInProgress);
9165
9166 appendAllChildren(_instance, workInProgress);
9167
9168 // Certain renderers require commit-time effects for initial mount.
9169 // (eg DOM renderer supports auto-focus for certain elements).
9170 // Make sure such renderers get scheduled for later work.
9171 if (finalizeInitialChildren(_instance, type, newProps, rootContainerInstance, _currentHostContext)) {
9172 markUpdate(workInProgress);
9173 }
9174 workInProgress.stateNode = _instance;
9175 }
9176
9177 if (workInProgress.ref !== null) {
9178 // If there is a ref on a host node we need to schedule a callback
9179 markRef(workInProgress);
9180 }
9181 }
9182 return null;
9183 }
9184 case HostText:
9185 {
9186 var newText = newProps;
9187 if (current && workInProgress.stateNode != null) {
9188 var oldText = current.memoizedProps;
9189 // If we have an alternate, that means this is an update and we need
9190 // to schedule a side-effect to do the updates.
9191 updateHostText(current, workInProgress, oldText, newText);
9192 } else {
9193 if (typeof newText !== 'string') {
9194 !(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;
9195 // This can happen when we abort work.
9196 return null;
9197 }
9198 var _rootContainerInstance = getRootHostContainer();
9199 var _currentHostContext2 = getHostContext();
9200 var _wasHydrated = popHydrationState(workInProgress);
9201 if (_wasHydrated) {
9202 if (prepareToHydrateHostTextInstance(workInProgress)) {
9203 markUpdate(workInProgress);
9204 }
9205 } else {
9206 workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext2, workInProgress);
9207 }
9208 }
9209 return null;
9210 }
9211 case CallComponent:
9212 return moveCallToHandlerPhase(current, workInProgress, renderExpirationTime);
9213 case CallHandlerPhase:
9214 // Reset the tag to now be a first phase call.
9215 workInProgress.tag = CallComponent;
9216 return null;
9217 case ReturnComponent:
9218 // Does nothing.
9219 return null;
9220 case Fragment:
9221 return null;
9222 case HostPortal:
9223 popHostContainer(workInProgress);
9224 updateHostContainer(workInProgress);
9225 return null;
9226 // Error cases
9227 case IndeterminateComponent:
9228 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.');
9229 // eslint-disable-next-line no-fallthrough
9230 default:
9231 invariant_1(false, 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.');
9232 }
9233 }
9234
9235 return {
9236 completeWork: completeWork
9237 };
9238};
9239
9240var invokeGuardedCallback$3 = ReactErrorUtils.invokeGuardedCallback;
9241var hasCaughtError$1 = ReactErrorUtils.hasCaughtError;
9242var clearCaughtError$1 = ReactErrorUtils.clearCaughtError;
9243
9244
9245var ReactFiberCommitWork = function (config, captureError) {
9246 var getPublicInstance = config.getPublicInstance,
9247 mutation = config.mutation,
9248 persistence = config.persistence;
9249
9250
9251 var callComponentWillUnmountWithTimer = function (current, instance) {
9252 startPhaseTimer(current, 'componentWillUnmount');
9253 instance.props = current.memoizedProps;
9254 instance.state = current.memoizedState;
9255 instance.componentWillUnmount();
9256 stopPhaseTimer();
9257 };
9258
9259 // Capture errors so they don't interrupt unmounting.
9260 function safelyCallComponentWillUnmount(current, instance) {
9261 {
9262 invokeGuardedCallback$3(null, callComponentWillUnmountWithTimer, null, current, instance);
9263 if (hasCaughtError$1()) {
9264 var unmountError = clearCaughtError$1();
9265 captureError(current, unmountError);
9266 }
9267 }
9268 }
9269
9270 function safelyDetachRef(current) {
9271 var ref = current.ref;
9272 if (ref !== null) {
9273 {
9274 invokeGuardedCallback$3(null, ref, null, null);
9275 if (hasCaughtError$1()) {
9276 var refError = clearCaughtError$1();
9277 captureError(current, refError);
9278 }
9279 }
9280 }
9281 }
9282
9283 function commitLifeCycles(current, finishedWork) {
9284 switch (finishedWork.tag) {
9285 case ClassComponent:
9286 {
9287 var instance = finishedWork.stateNode;
9288 if (finishedWork.effectTag & Update) {
9289 if (current === null) {
9290 startPhaseTimer(finishedWork, 'componentDidMount');
9291 instance.props = finishedWork.memoizedProps;
9292 instance.state = finishedWork.memoizedState;
9293 instance.componentDidMount();
9294 stopPhaseTimer();
9295 } else {
9296 var prevProps = current.memoizedProps;
9297 var prevState = current.memoizedState;
9298 startPhaseTimer(finishedWork, 'componentDidUpdate');
9299 instance.props = finishedWork.memoizedProps;
9300 instance.state = finishedWork.memoizedState;
9301 instance.componentDidUpdate(prevProps, prevState);
9302 stopPhaseTimer();
9303 }
9304 }
9305 var updateQueue = finishedWork.updateQueue;
9306 if (updateQueue !== null) {
9307 commitCallbacks(updateQueue, instance);
9308 }
9309 return;
9310 }
9311 case HostRoot:
9312 {
9313 var _updateQueue = finishedWork.updateQueue;
9314 if (_updateQueue !== null) {
9315 var _instance = finishedWork.child !== null ? finishedWork.child.stateNode : null;
9316 commitCallbacks(_updateQueue, _instance);
9317 }
9318 return;
9319 }
9320 case HostComponent:
9321 {
9322 var _instance2 = finishedWork.stateNode;
9323
9324 // Renderers may schedule work to be done after host components are mounted
9325 // (eg DOM renderer may schedule auto-focus for inputs and form controls).
9326 // These effects should only be committed when components are first mounted,
9327 // aka when there is no current/alternate.
9328 if (current === null && finishedWork.effectTag & Update) {
9329 var type = finishedWork.type;
9330 var props = finishedWork.memoizedProps;
9331 commitMount(_instance2, type, props, finishedWork);
9332 }
9333
9334 return;
9335 }
9336 case HostText:
9337 {
9338 // We have no life-cycles associated with text.
9339 return;
9340 }
9341 case HostPortal:
9342 {
9343 // We have no life-cycles associated with portals.
9344 return;
9345 }
9346 default:
9347 {
9348 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.');
9349 }
9350 }
9351 }
9352
9353 function commitAttachRef(finishedWork) {
9354 var ref = finishedWork.ref;
9355 if (ref !== null) {
9356 var instance = finishedWork.stateNode;
9357 switch (finishedWork.tag) {
9358 case HostComponent:
9359 ref(getPublicInstance(instance));
9360 break;
9361 default:
9362 ref(instance);
9363 }
9364 }
9365 }
9366
9367 function commitDetachRef(current) {
9368 var currentRef = current.ref;
9369 if (currentRef !== null) {
9370 currentRef(null);
9371 }
9372 }
9373
9374 // User-originating errors (lifecycles and refs) should not interrupt
9375 // deletion, so don't let them throw. Host-originating errors should
9376 // interrupt deletion, so it's okay
9377 function commitUnmount(current) {
9378 if (typeof onCommitUnmount === 'function') {
9379 onCommitUnmount(current);
9380 }
9381
9382 switch (current.tag) {
9383 case ClassComponent:
9384 {
9385 safelyDetachRef(current);
9386 var instance = current.stateNode;
9387 if (typeof instance.componentWillUnmount === 'function') {
9388 safelyCallComponentWillUnmount(current, instance);
9389 }
9390 return;
9391 }
9392 case HostComponent:
9393 {
9394 safelyDetachRef(current);
9395 return;
9396 }
9397 case CallComponent:
9398 {
9399 commitNestedUnmounts(current.stateNode);
9400 return;
9401 }
9402 case HostPortal:
9403 {
9404 // TODO: this is recursive.
9405 // We are also not using this parent because
9406 // the portal will get pushed immediately.
9407 if (enableMutatingReconciler && mutation) {
9408 unmountHostComponents(current);
9409 } else if (enablePersistentReconciler && persistence) {
9410 emptyPortalContainer(current);
9411 }
9412 return;
9413 }
9414 }
9415 }
9416
9417 function commitNestedUnmounts(root) {
9418 // While we're inside a removed host node we don't want to call
9419 // removeChild on the inner nodes because they're removed by the top
9420 // call anyway. We also want to call componentWillUnmount on all
9421 // composites before this host node is removed from the tree. Therefore
9422 var node = root;
9423 while (true) {
9424 commitUnmount(node);
9425 // Visit children because they may contain more composite or host nodes.
9426 // Skip portals because commitUnmount() currently visits them recursively.
9427 if (node.child !== null && (
9428 // If we use mutation we drill down into portals using commitUnmount above.
9429 // If we don't use mutation we drill down into portals here instead.
9430 !mutation || node.tag !== HostPortal)) {
9431 node.child['return'] = node;
9432 node = node.child;
9433 continue;
9434 }
9435 if (node === root) {
9436 return;
9437 }
9438 while (node.sibling === null) {
9439 if (node['return'] === null || node['return'] === root) {
9440 return;
9441 }
9442 node = node['return'];
9443 }
9444 node.sibling['return'] = node['return'];
9445 node = node.sibling;
9446 }
9447 }
9448
9449 function detachFiber(current) {
9450 // Cut off the return pointers to disconnect it from the tree. Ideally, we
9451 // should clear the child pointer of the parent alternate to let this
9452 // get GC:ed but we don't know which for sure which parent is the current
9453 // one so we'll settle for GC:ing the subtree of this child. This child
9454 // itself will be GC:ed when the parent updates the next time.
9455 current['return'] = null;
9456 current.child = null;
9457 if (current.alternate) {
9458 current.alternate.child = null;
9459 current.alternate['return'] = null;
9460 }
9461 }
9462
9463 var emptyPortalContainer = void 0;
9464
9465 if (!mutation) {
9466 var commitContainer = void 0;
9467 if (persistence) {
9468 var replaceContainerChildren = persistence.replaceContainerChildren,
9469 createContainerChildSet = persistence.createContainerChildSet;
9470
9471 emptyPortalContainer = function (current) {
9472 var portal = current.stateNode;
9473 var containerInfo = portal.containerInfo;
9474
9475 var emptyChildSet = createContainerChildSet(containerInfo);
9476 replaceContainerChildren(containerInfo, emptyChildSet);
9477 };
9478 commitContainer = function (finishedWork) {
9479 switch (finishedWork.tag) {
9480 case ClassComponent:
9481 {
9482 return;
9483 }
9484 case HostComponent:
9485 {
9486 return;
9487 }
9488 case HostText:
9489 {
9490 return;
9491 }
9492 case HostRoot:
9493 case HostPortal:
9494 {
9495 var portalOrRoot = finishedWork.stateNode;
9496 var containerInfo = portalOrRoot.containerInfo,
9497 _pendingChildren = portalOrRoot.pendingChildren;
9498
9499 replaceContainerChildren(containerInfo, _pendingChildren);
9500 return;
9501 }
9502 default:
9503 {
9504 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.');
9505 }
9506 }
9507 };
9508 } else {
9509 commitContainer = function (finishedWork) {
9510 // Noop
9511 };
9512 }
9513 if (enablePersistentReconciler || enableNoopReconciler) {
9514 return {
9515 commitResetTextContent: function (finishedWork) {},
9516 commitPlacement: function (finishedWork) {},
9517 commitDeletion: function (current) {
9518 // Detach refs and call componentWillUnmount() on the whole subtree.
9519 commitNestedUnmounts(current);
9520 detachFiber(current);
9521 },
9522 commitWork: function (current, finishedWork) {
9523 commitContainer(finishedWork);
9524 },
9525
9526 commitLifeCycles: commitLifeCycles,
9527 commitAttachRef: commitAttachRef,
9528 commitDetachRef: commitDetachRef
9529 };
9530 } else if (persistence) {
9531 invariant_1(false, 'Persistent reconciler is disabled.');
9532 } else {
9533 invariant_1(false, 'Noop reconciler is disabled.');
9534 }
9535 }
9536 var commitMount = mutation.commitMount,
9537 commitUpdate = mutation.commitUpdate,
9538 resetTextContent = mutation.resetTextContent,
9539 commitTextUpdate = mutation.commitTextUpdate,
9540 appendChild = mutation.appendChild,
9541 appendChildToContainer = mutation.appendChildToContainer,
9542 insertBefore = mutation.insertBefore,
9543 insertInContainerBefore = mutation.insertInContainerBefore,
9544 removeChild = mutation.removeChild,
9545 removeChildFromContainer = mutation.removeChildFromContainer;
9546
9547
9548 function getHostParentFiber(fiber) {
9549 var parent = fiber['return'];
9550 while (parent !== null) {
9551 if (isHostParent(parent)) {
9552 return parent;
9553 }
9554 parent = parent['return'];
9555 }
9556 invariant_1(false, 'Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue.');
9557 }
9558
9559 function isHostParent(fiber) {
9560 return fiber.tag === HostComponent || fiber.tag === HostRoot || fiber.tag === HostPortal;
9561 }
9562
9563 function getHostSibling(fiber) {
9564 // We're going to search forward into the tree until we find a sibling host
9565 // node. Unfortunately, if multiple insertions are done in a row we have to
9566 // search past them. This leads to exponential search for the next sibling.
9567 var node = fiber;
9568 siblings: while (true) {
9569 // If we didn't find anything, let's try the next sibling.
9570 while (node.sibling === null) {
9571 if (node['return'] === null || isHostParent(node['return'])) {
9572 // If we pop out of the root or hit the parent the fiber we are the
9573 // last sibling.
9574 return null;
9575 }
9576 node = node['return'];
9577 }
9578 node.sibling['return'] = node['return'];
9579 node = node.sibling;
9580 while (node.tag !== HostComponent && node.tag !== HostText) {
9581 // If it is not host node and, we might have a host node inside it.
9582 // Try to search down until we find one.
9583 if (node.effectTag & Placement) {
9584 // If we don't have a child, try the siblings instead.
9585 continue siblings;
9586 }
9587 // If we don't have a child, try the siblings instead.
9588 // We also skip portals because they are not part of this host tree.
9589 if (node.child === null || node.tag === HostPortal) {
9590 continue siblings;
9591 } else {
9592 node.child['return'] = node;
9593 node = node.child;
9594 }
9595 }
9596 // Check if this host node is stable or about to be placed.
9597 if (!(node.effectTag & Placement)) {
9598 // Found it!
9599 return node.stateNode;
9600 }
9601 }
9602 }
9603
9604 function commitPlacement(finishedWork) {
9605 // Recursively insert all host nodes into the parent.
9606 var parentFiber = getHostParentFiber(finishedWork);
9607 var parent = void 0;
9608 var isContainer = void 0;
9609 switch (parentFiber.tag) {
9610 case HostComponent:
9611 parent = parentFiber.stateNode;
9612 isContainer = false;
9613 break;
9614 case HostRoot:
9615 parent = parentFiber.stateNode.containerInfo;
9616 isContainer = true;
9617 break;
9618 case HostPortal:
9619 parent = parentFiber.stateNode.containerInfo;
9620 isContainer = true;
9621 break;
9622 default:
9623 invariant_1(false, 'Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue.');
9624 }
9625 if (parentFiber.effectTag & ContentReset) {
9626 // Reset the text content of the parent before doing any insertions
9627 resetTextContent(parent);
9628 // Clear ContentReset from the effect tag
9629 parentFiber.effectTag &= ~ContentReset;
9630 }
9631
9632 var before = getHostSibling(finishedWork);
9633 // We only have the top Fiber that was inserted but we need recurse down its
9634 // children to find all the terminal nodes.
9635 var node = finishedWork;
9636 while (true) {
9637 if (node.tag === HostComponent || node.tag === HostText) {
9638 if (before) {
9639 if (isContainer) {
9640 insertInContainerBefore(parent, node.stateNode, before);
9641 } else {
9642 insertBefore(parent, node.stateNode, before);
9643 }
9644 } else {
9645 if (isContainer) {
9646 appendChildToContainer(parent, node.stateNode);
9647 } else {
9648 appendChild(parent, node.stateNode);
9649 }
9650 }
9651 } else if (node.tag === HostPortal) {
9652 // If the insertion itself is a portal, then we don't want to traverse
9653 // down its children. Instead, we'll get insertions from each child in
9654 // the portal directly.
9655 } else if (node.child !== null) {
9656 node.child['return'] = node;
9657 node = node.child;
9658 continue;
9659 }
9660 if (node === finishedWork) {
9661 return;
9662 }
9663 while (node.sibling === null) {
9664 if (node['return'] === null || node['return'] === finishedWork) {
9665 return;
9666 }
9667 node = node['return'];
9668 }
9669 node.sibling['return'] = node['return'];
9670 node = node.sibling;
9671 }
9672 }
9673
9674 function unmountHostComponents(current) {
9675 // We only have the top Fiber that was inserted but we need recurse down its
9676 var node = current;
9677
9678 // Each iteration, currentParent is populated with node's host parent if not
9679 // currentParentIsValid.
9680 var currentParentIsValid = false;
9681 var currentParent = void 0;
9682 var currentParentIsContainer = void 0;
9683
9684 while (true) {
9685 if (!currentParentIsValid) {
9686 var parent = node['return'];
9687 findParent: while (true) {
9688 !(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;
9689 switch (parent.tag) {
9690 case HostComponent:
9691 currentParent = parent.stateNode;
9692 currentParentIsContainer = false;
9693 break findParent;
9694 case HostRoot:
9695 currentParent = parent.stateNode.containerInfo;
9696 currentParentIsContainer = true;
9697 break findParent;
9698 case HostPortal:
9699 currentParent = parent.stateNode.containerInfo;
9700 currentParentIsContainer = true;
9701 break findParent;
9702 }
9703 parent = parent['return'];
9704 }
9705 currentParentIsValid = true;
9706 }
9707
9708 if (node.tag === HostComponent || node.tag === HostText) {
9709 commitNestedUnmounts(node);
9710 // After all the children have unmounted, it is now safe to remove the
9711 // node from the tree.
9712 if (currentParentIsContainer) {
9713 removeChildFromContainer(currentParent, node.stateNode);
9714 } else {
9715 removeChild(currentParent, node.stateNode);
9716 }
9717 // Don't visit children because we already visited them.
9718 } else if (node.tag === HostPortal) {
9719 // When we go into a portal, it becomes the parent to remove from.
9720 // We will reassign it back when we pop the portal on the way up.
9721 currentParent = node.stateNode.containerInfo;
9722 // Visit children because portals might contain host components.
9723 if (node.child !== null) {
9724 node.child['return'] = node;
9725 node = node.child;
9726 continue;
9727 }
9728 } else {
9729 commitUnmount(node);
9730 // Visit children because we may find more host components below.
9731 if (node.child !== null) {
9732 node.child['return'] = node;
9733 node = node.child;
9734 continue;
9735 }
9736 }
9737 if (node === current) {
9738 return;
9739 }
9740 while (node.sibling === null) {
9741 if (node['return'] === null || node['return'] === current) {
9742 return;
9743 }
9744 node = node['return'];
9745 if (node.tag === HostPortal) {
9746 // When we go out of the portal, we need to restore the parent.
9747 // Since we don't keep a stack of them, we will search for it.
9748 currentParentIsValid = false;
9749 }
9750 }
9751 node.sibling['return'] = node['return'];
9752 node = node.sibling;
9753 }
9754 }
9755
9756 function commitDeletion(current) {
9757 // Recursively delete all host nodes from the parent.
9758 // Detach refs and call componentWillUnmount() on the whole subtree.
9759 unmountHostComponents(current);
9760 detachFiber(current);
9761 }
9762
9763 function commitWork(current, finishedWork) {
9764 switch (finishedWork.tag) {
9765 case ClassComponent:
9766 {
9767 return;
9768 }
9769 case HostComponent:
9770 {
9771 var instance = finishedWork.stateNode;
9772 if (instance != null) {
9773 // Commit the work prepared earlier.
9774 var newProps = finishedWork.memoizedProps;
9775 // For hydration we reuse the update path but we treat the oldProps
9776 // as the newProps. The updatePayload will contain the real change in
9777 // this case.
9778 var oldProps = current !== null ? current.memoizedProps : newProps;
9779 var type = finishedWork.type;
9780 // TODO: Type the updateQueue to be specific to host components.
9781 var updatePayload = finishedWork.updateQueue;
9782 finishedWork.updateQueue = null;
9783 if (updatePayload !== null) {
9784 commitUpdate(instance, updatePayload, type, oldProps, newProps, finishedWork);
9785 }
9786 }
9787 return;
9788 }
9789 case HostText:
9790 {
9791 !(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;
9792 var textInstance = finishedWork.stateNode;
9793 var newText = finishedWork.memoizedProps;
9794 // For hydration we reuse the update path but we treat the oldProps
9795 // as the newProps. The updatePayload will contain the real change in
9796 // this case.
9797 var oldText = current !== null ? current.memoizedProps : newText;
9798 commitTextUpdate(textInstance, oldText, newText);
9799 return;
9800 }
9801 case HostRoot:
9802 {
9803 return;
9804 }
9805 default:
9806 {
9807 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.');
9808 }
9809 }
9810 }
9811
9812 function commitResetTextContent(current) {
9813 resetTextContent(current.stateNode);
9814 }
9815
9816 if (enableMutatingReconciler) {
9817 return {
9818 commitResetTextContent: commitResetTextContent,
9819 commitPlacement: commitPlacement,
9820 commitDeletion: commitDeletion,
9821 commitWork: commitWork,
9822 commitLifeCycles: commitLifeCycles,
9823 commitAttachRef: commitAttachRef,
9824 commitDetachRef: commitDetachRef
9825 };
9826 } else {
9827 invariant_1(false, 'Mutating reconciler is disabled.');
9828 }
9829};
9830
9831var NO_CONTEXT = {};
9832
9833var ReactFiberHostContext = function (config) {
9834 var getChildHostContext = config.getChildHostContext,
9835 getRootHostContext = config.getRootHostContext;
9836
9837
9838 var contextStackCursor = createCursor(NO_CONTEXT);
9839 var contextFiberStackCursor = createCursor(NO_CONTEXT);
9840 var rootInstanceStackCursor = createCursor(NO_CONTEXT);
9841
9842 function requiredContext(c) {
9843 !(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;
9844 return c;
9845 }
9846
9847 function getRootHostContainer() {
9848 var rootInstance = requiredContext(rootInstanceStackCursor.current);
9849 return rootInstance;
9850 }
9851
9852 function pushHostContainer(fiber, nextRootInstance) {
9853 // Push current root instance onto the stack;
9854 // This allows us to reset root when portals are popped.
9855 push(rootInstanceStackCursor, nextRootInstance, fiber);
9856
9857 var nextRootContext = getRootHostContext(nextRootInstance);
9858
9859 // Track the context and the Fiber that provided it.
9860 // This enables us to pop only Fibers that provide unique contexts.
9861 push(contextFiberStackCursor, fiber, fiber);
9862 push(contextStackCursor, nextRootContext, fiber);
9863 }
9864
9865 function popHostContainer(fiber) {
9866 pop(contextStackCursor, fiber);
9867 pop(contextFiberStackCursor, fiber);
9868 pop(rootInstanceStackCursor, fiber);
9869 }
9870
9871 function getHostContext() {
9872 var context = requiredContext(contextStackCursor.current);
9873 return context;
9874 }
9875
9876 function pushHostContext(fiber) {
9877 var rootInstance = requiredContext(rootInstanceStackCursor.current);
9878 var context = requiredContext(contextStackCursor.current);
9879 var nextContext = getChildHostContext(context, fiber.type, rootInstance);
9880
9881 // Don't push this Fiber's context unless it's unique.
9882 if (context === nextContext) {
9883 return;
9884 }
9885
9886 // Track the context and the Fiber that provided it.
9887 // This enables us to pop only Fibers that provide unique contexts.
9888 push(contextFiberStackCursor, fiber, fiber);
9889 push(contextStackCursor, nextContext, fiber);
9890 }
9891
9892 function popHostContext(fiber) {
9893 // Do not pop unless this Fiber provided the current context.
9894 // pushHostContext() only pushes Fibers that provide unique contexts.
9895 if (contextFiberStackCursor.current !== fiber) {
9896 return;
9897 }
9898
9899 pop(contextStackCursor, fiber);
9900 pop(contextFiberStackCursor, fiber);
9901 }
9902
9903 function resetHostContainer() {
9904 contextStackCursor.current = NO_CONTEXT;
9905 rootInstanceStackCursor.current = NO_CONTEXT;
9906 }
9907
9908 return {
9909 getHostContext: getHostContext,
9910 getRootHostContainer: getRootHostContainer,
9911 popHostContainer: popHostContainer,
9912 popHostContext: popHostContext,
9913 pushHostContainer: pushHostContainer,
9914 pushHostContext: pushHostContext,
9915 resetHostContainer: resetHostContainer
9916 };
9917};
9918
9919var ReactFiberHydrationContext = function (config) {
9920 var shouldSetTextContent = config.shouldSetTextContent,
9921 hydration = config.hydration;
9922
9923 // If this doesn't have hydration mode.
9924
9925 if (!hydration) {
9926 return {
9927 enterHydrationState: function () {
9928 return false;
9929 },
9930 resetHydrationState: function () {},
9931 tryToClaimNextHydratableInstance: function () {},
9932 prepareToHydrateHostInstance: function () {
9933 invariant_1(false, 'Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.');
9934 },
9935 prepareToHydrateHostTextInstance: function () {
9936 invariant_1(false, 'Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.');
9937 },
9938 popHydrationState: function (fiber) {
9939 return false;
9940 }
9941 };
9942 }
9943
9944 var canHydrateInstance = hydration.canHydrateInstance,
9945 canHydrateTextInstance = hydration.canHydrateTextInstance,
9946 getNextHydratableSibling = hydration.getNextHydratableSibling,
9947 getFirstHydratableChild = hydration.getFirstHydratableChild,
9948 hydrateInstance = hydration.hydrateInstance,
9949 hydrateTextInstance = hydration.hydrateTextInstance,
9950 didNotMatchHydratedContainerTextInstance = hydration.didNotMatchHydratedContainerTextInstance,
9951 didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance,
9952 didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance,
9953 didNotHydrateInstance = hydration.didNotHydrateInstance,
9954 didNotFindHydratableContainerInstance = hydration.didNotFindHydratableContainerInstance,
9955 didNotFindHydratableContainerTextInstance = hydration.didNotFindHydratableContainerTextInstance,
9956 didNotFindHydratableInstance = hydration.didNotFindHydratableInstance,
9957 didNotFindHydratableTextInstance = hydration.didNotFindHydratableTextInstance;
9958
9959 // The deepest Fiber on the stack involved in a hydration context.
9960 // This may have been an insertion or a hydration.
9961
9962 var hydrationParentFiber = null;
9963 var nextHydratableInstance = null;
9964 var isHydrating = false;
9965
9966 function enterHydrationState(fiber) {
9967 var parentInstance = fiber.stateNode.containerInfo;
9968 nextHydratableInstance = getFirstHydratableChild(parentInstance);
9969 hydrationParentFiber = fiber;
9970 isHydrating = true;
9971 return true;
9972 }
9973
9974 function deleteHydratableInstance(returnFiber, instance) {
9975 {
9976 switch (returnFiber.tag) {
9977 case HostRoot:
9978 didNotHydrateContainerInstance(returnFiber.stateNode.containerInfo, instance);
9979 break;
9980 case HostComponent:
9981 didNotHydrateInstance(returnFiber.type, returnFiber.memoizedProps, returnFiber.stateNode, instance);
9982 break;
9983 }
9984 }
9985
9986 var childToDelete = createFiberFromHostInstanceForDeletion();
9987 childToDelete.stateNode = instance;
9988 childToDelete['return'] = returnFiber;
9989 childToDelete.effectTag = Deletion;
9990
9991 // This might seem like it belongs on progressedFirstDeletion. However,
9992 // these children are not part of the reconciliation list of children.
9993 // Even if we abort and rereconcile the children, that will try to hydrate
9994 // again and the nodes are still in the host tree so these will be
9995 // recreated.
9996 if (returnFiber.lastEffect !== null) {
9997 returnFiber.lastEffect.nextEffect = childToDelete;
9998 returnFiber.lastEffect = childToDelete;
9999 } else {
10000 returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
10001 }
10002 }
10003
10004 function insertNonHydratedInstance(returnFiber, fiber) {
10005 fiber.effectTag |= Placement;
10006 {
10007 switch (returnFiber.tag) {
10008 case HostRoot:
10009 {
10010 var parentContainer = returnFiber.stateNode.containerInfo;
10011 switch (fiber.tag) {
10012 case HostComponent:
10013 var type = fiber.type;
10014 var props = fiber.pendingProps;
10015 didNotFindHydratableContainerInstance(parentContainer, type, props);
10016 break;
10017 case HostText:
10018 var text = fiber.pendingProps;
10019 didNotFindHydratableContainerTextInstance(parentContainer, text);
10020 break;
10021 }
10022 break;
10023 }
10024 case HostComponent:
10025 {
10026 var parentType = returnFiber.type;
10027 var parentProps = returnFiber.memoizedProps;
10028 var parentInstance = returnFiber.stateNode;
10029 switch (fiber.tag) {
10030 case HostComponent:
10031 var _type = fiber.type;
10032 var _props = fiber.pendingProps;
10033 didNotFindHydratableInstance(parentType, parentProps, parentInstance, _type, _props);
10034 break;
10035 case HostText:
10036 var _text = fiber.pendingProps;
10037 didNotFindHydratableTextInstance(parentType, parentProps, parentInstance, _text);
10038 break;
10039 }
10040 break;
10041 }
10042 default:
10043 return;
10044 }
10045 }
10046 }
10047
10048 function tryHydrate(fiber, nextInstance) {
10049 switch (fiber.tag) {
10050 case HostComponent:
10051 {
10052 var type = fiber.type;
10053 var props = fiber.pendingProps;
10054 var instance = canHydrateInstance(nextInstance, type, props);
10055 if (instance !== null) {
10056 fiber.stateNode = instance;
10057 return true;
10058 }
10059 return false;
10060 }
10061 case HostText:
10062 {
10063 var text = fiber.pendingProps;
10064 var textInstance = canHydrateTextInstance(nextInstance, text);
10065 if (textInstance !== null) {
10066 fiber.stateNode = textInstance;
10067 return true;
10068 }
10069 return false;
10070 }
10071 default:
10072 return false;
10073 }
10074 }
10075
10076 function tryToClaimNextHydratableInstance(fiber) {
10077 if (!isHydrating) {
10078 return;
10079 }
10080 var nextInstance = nextHydratableInstance;
10081 if (!nextInstance) {
10082 // Nothing to hydrate. Make it an insertion.
10083 insertNonHydratedInstance(hydrationParentFiber, fiber);
10084 isHydrating = false;
10085 hydrationParentFiber = fiber;
10086 return;
10087 }
10088 if (!tryHydrate(fiber, nextInstance)) {
10089 // If we can't hydrate this instance let's try the next one.
10090 // We use this as a heuristic. It's based on intuition and not data so it
10091 // might be flawed or unnecessary.
10092 nextInstance = getNextHydratableSibling(nextInstance);
10093 if (!nextInstance || !tryHydrate(fiber, nextInstance)) {
10094 // Nothing to hydrate. Make it an insertion.
10095 insertNonHydratedInstance(hydrationParentFiber, fiber);
10096 isHydrating = false;
10097 hydrationParentFiber = fiber;
10098 return;
10099 }
10100 // We matched the next one, we'll now assume that the first one was
10101 // superfluous and we'll delete it. Since we can't eagerly delete it
10102 // we'll have to schedule a deletion. To do that, this node needs a dummy
10103 // fiber associated with it.
10104 deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance);
10105 }
10106 hydrationParentFiber = fiber;
10107 nextHydratableInstance = getFirstHydratableChild(nextInstance);
10108 }
10109
10110 function prepareToHydrateHostInstance(fiber, rootContainerInstance, hostContext) {
10111 var instance = fiber.stateNode;
10112 var updatePayload = hydrateInstance(instance, fiber.type, fiber.memoizedProps, rootContainerInstance, hostContext, fiber);
10113 // TODO: Type this specific to this type of component.
10114 fiber.updateQueue = updatePayload;
10115 // If the update payload indicates that there is a change or if there
10116 // is a new ref we mark this as an update.
10117 if (updatePayload !== null) {
10118 return true;
10119 }
10120 return false;
10121 }
10122
10123 function prepareToHydrateHostTextInstance(fiber) {
10124 var textInstance = fiber.stateNode;
10125 var textContent = fiber.memoizedProps;
10126 var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber);
10127 {
10128 if (shouldUpdate) {
10129 // We assume that prepareToHydrateHostTextInstance is called in a context where the
10130 // hydration parent is the parent host component of this host text.
10131 var returnFiber = hydrationParentFiber;
10132 if (returnFiber !== null) {
10133 switch (returnFiber.tag) {
10134 case HostRoot:
10135 {
10136 var parentContainer = returnFiber.stateNode.containerInfo;
10137 didNotMatchHydratedContainerTextInstance(parentContainer, textInstance, textContent);
10138 break;
10139 }
10140 case HostComponent:
10141 {
10142 var parentType = returnFiber.type;
10143 var parentProps = returnFiber.memoizedProps;
10144 var parentInstance = returnFiber.stateNode;
10145 didNotMatchHydratedTextInstance(parentType, parentProps, parentInstance, textInstance, textContent);
10146 break;
10147 }
10148 }
10149 }
10150 }
10151 }
10152 return shouldUpdate;
10153 }
10154
10155 function popToNextHostParent(fiber) {
10156 var parent = fiber['return'];
10157 while (parent !== null && parent.tag !== HostComponent && parent.tag !== HostRoot) {
10158 parent = parent['return'];
10159 }
10160 hydrationParentFiber = parent;
10161 }
10162
10163 function popHydrationState(fiber) {
10164 if (fiber !== hydrationParentFiber) {
10165 // We're deeper than the current hydration context, inside an inserted
10166 // tree.
10167 return false;
10168 }
10169 if (!isHydrating) {
10170 // If we're not currently hydrating but we're in a hydration context, then
10171 // we were an insertion and now need to pop up reenter hydration of our
10172 // siblings.
10173 popToNextHostParent(fiber);
10174 isHydrating = true;
10175 return false;
10176 }
10177
10178 var type = fiber.type;
10179
10180 // If we have any remaining hydratable nodes, we need to delete them now.
10181 // We only do this deeper than head and body since they tend to have random
10182 // other nodes in them. We also ignore components with pure text content in
10183 // side of them.
10184 // TODO: Better heuristic.
10185 if (fiber.tag !== HostComponent || type !== 'head' && type !== 'body' && !shouldSetTextContent(type, fiber.memoizedProps)) {
10186 var nextInstance = nextHydratableInstance;
10187 while (nextInstance) {
10188 deleteHydratableInstance(fiber, nextInstance);
10189 nextInstance = getNextHydratableSibling(nextInstance);
10190 }
10191 }
10192
10193 popToNextHostParent(fiber);
10194 nextHydratableInstance = hydrationParentFiber ? getNextHydratableSibling(fiber.stateNode) : null;
10195 return true;
10196 }
10197
10198 function resetHydrationState() {
10199 hydrationParentFiber = null;
10200 nextHydratableInstance = null;
10201 isHydrating = false;
10202 }
10203
10204 return {
10205 enterHydrationState: enterHydrationState,
10206 resetHydrationState: resetHydrationState,
10207 tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance,
10208 prepareToHydrateHostInstance: prepareToHydrateHostInstance,
10209 prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance,
10210 popHydrationState: popHydrationState
10211 };
10212};
10213
10214// This lets us hook into Fiber to debug what it's doing.
10215// See https://github.com/facebook/react/pull/8033.
10216// This is not part of the public API, not even for React DevTools.
10217// You may only inject a debugTool if you work on React Fiber itself.
10218var ReactFiberInstrumentation = {
10219 debugTool: null
10220};
10221
10222var ReactFiberInstrumentation_1 = ReactFiberInstrumentation;
10223
10224// This module is forked in different environments.
10225// By default, return `true` to log errors to the console.
10226// Forks can return `false` if this isn't desirable.
10227function showErrorDialog(capturedError) {
10228 return true;
10229}
10230
10231function logCapturedError(capturedError) {
10232 var logError = showErrorDialog(capturedError);
10233
10234 // Allow injected showErrorDialog() to prevent default console.error logging.
10235 // This enables renderers like ReactNative to better manage redbox behavior.
10236 if (logError === false) {
10237 return;
10238 }
10239
10240 var error = capturedError.error;
10241 var suppressLogging = error && error.suppressReactErrorLogging;
10242 if (suppressLogging) {
10243 return;
10244 }
10245
10246 {
10247 var componentName = capturedError.componentName,
10248 componentStack = capturedError.componentStack,
10249 errorBoundaryName = capturedError.errorBoundaryName,
10250 errorBoundaryFound = capturedError.errorBoundaryFound,
10251 willRetry = capturedError.willRetry;
10252
10253
10254 var componentNameMessage = componentName ? 'The above error occurred in the <' + componentName + '> component:' : 'The above error occurred in one of your React components:';
10255
10256 var errorBoundaryMessage = void 0;
10257 // errorBoundaryFound check is sufficient; errorBoundaryName check is to satisfy Flow.
10258 if (errorBoundaryFound && errorBoundaryName) {
10259 if (willRetry) {
10260 errorBoundaryMessage = 'React will try to recreate this component tree from scratch ' + ('using the error boundary you provided, ' + errorBoundaryName + '.');
10261 } else {
10262 errorBoundaryMessage = 'This error was initially handled by the error boundary ' + errorBoundaryName + '.\n' + 'Recreating the tree from scratch failed so React will unmount the tree.';
10263 }
10264 } else {
10265 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.';
10266 }
10267 var combinedMessage = '' + componentNameMessage + componentStack + '\n\n' + ('' + errorBoundaryMessage);
10268
10269 // In development, we provide our own message with just the component stack.
10270 // We don't include the original error message and JS stack because the browser
10271 // has already printed it. Even if the application swallows the error, it is still
10272 // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils.
10273 console.error(combinedMessage);
10274 }
10275}
10276
10277var invokeGuardedCallback$2 = ReactErrorUtils.invokeGuardedCallback;
10278var hasCaughtError = ReactErrorUtils.hasCaughtError;
10279var clearCaughtError = ReactErrorUtils.clearCaughtError;
10280
10281
10282var didWarnAboutStateTransition = void 0;
10283var didWarnSetStateChildContext = void 0;
10284var warnAboutUpdateOnUnmounted = void 0;
10285var warnAboutInvalidUpdates = void 0;
10286
10287{
10288 didWarnAboutStateTransition = false;
10289 didWarnSetStateChildContext = false;
10290 var didWarnStateUpdateForUnmountedComponent = {};
10291
10292 warnAboutUpdateOnUnmounted = function (fiber) {
10293 var componentName = getComponentName(fiber) || 'ReactClass';
10294 if (didWarnStateUpdateForUnmountedComponent[componentName]) {
10295 return;
10296 }
10297 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);
10298 didWarnStateUpdateForUnmountedComponent[componentName] = true;
10299 };
10300
10301 warnAboutInvalidUpdates = function (instance) {
10302 switch (ReactDebugCurrentFiber.phase) {
10303 case 'getChildContext':
10304 if (didWarnSetStateChildContext) {
10305 return;
10306 }
10307 warning_1(false, 'setState(...): Cannot call setState() inside getChildContext()');
10308 didWarnSetStateChildContext = true;
10309 break;
10310 case 'render':
10311 if (didWarnAboutStateTransition) {
10312 return;
10313 }
10314 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`.');
10315 didWarnAboutStateTransition = true;
10316 break;
10317 }
10318 };
10319}
10320
10321var ReactFiberScheduler = function (config) {
10322 var hostContext = ReactFiberHostContext(config);
10323 var hydrationContext = ReactFiberHydrationContext(config);
10324 var popHostContainer = hostContext.popHostContainer,
10325 popHostContext = hostContext.popHostContext,
10326 resetHostContainer = hostContext.resetHostContainer;
10327
10328 var _ReactFiberBeginWork = ReactFiberBeginWork(config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber),
10329 beginWork = _ReactFiberBeginWork.beginWork,
10330 beginFailedWork = _ReactFiberBeginWork.beginFailedWork;
10331
10332 var _ReactFiberCompleteWo = ReactFiberCompleteWork(config, hostContext, hydrationContext),
10333 completeWork = _ReactFiberCompleteWo.completeWork;
10334
10335 var _ReactFiberCommitWork = ReactFiberCommitWork(config, captureError),
10336 commitResetTextContent = _ReactFiberCommitWork.commitResetTextContent,
10337 commitPlacement = _ReactFiberCommitWork.commitPlacement,
10338 commitDeletion = _ReactFiberCommitWork.commitDeletion,
10339 commitWork = _ReactFiberCommitWork.commitWork,
10340 commitLifeCycles = _ReactFiberCommitWork.commitLifeCycles,
10341 commitAttachRef = _ReactFiberCommitWork.commitAttachRef,
10342 commitDetachRef = _ReactFiberCommitWork.commitDetachRef;
10343
10344 var now = config.now,
10345 scheduleDeferredCallback = config.scheduleDeferredCallback,
10346 cancelDeferredCallback = config.cancelDeferredCallback,
10347 useSyncScheduling = config.useSyncScheduling,
10348 prepareForCommit = config.prepareForCommit,
10349 resetAfterCommit = config.resetAfterCommit;
10350
10351 // Represents the current time in ms.
10352
10353 var startTime = now();
10354 var mostRecentCurrentTime = msToExpirationTime(0);
10355
10356 // Used to ensure computeUniqueAsyncExpiration is monotonically increases.
10357 var lastUniqueAsyncExpiration = 0;
10358
10359 // Represents the expiration time that incoming updates should use. (If this
10360 // is NoWork, use the default strategy: async updates in async mode, sync
10361 // updates in sync mode.)
10362 var expirationContext = NoWork;
10363
10364 var isWorking = false;
10365
10366 // The next work in progress fiber that we're currently working on.
10367 var nextUnitOfWork = null;
10368 var nextRoot = null;
10369 // The time at which we're currently rendering work.
10370 var nextRenderExpirationTime = NoWork;
10371
10372 // The next fiber with an effect that we're currently committing.
10373 var nextEffect = null;
10374
10375 // Keep track of which fibers have captured an error that need to be handled.
10376 // Work is removed from this collection after componentDidCatch is called.
10377 var capturedErrors = null;
10378 // Keep track of which fibers have failed during the current batch of work.
10379 // This is a different set than capturedErrors, because it is not reset until
10380 // the end of the batch. This is needed to propagate errors correctly if a
10381 // subtree fails more than once.
10382 var failedBoundaries = null;
10383 // Error boundaries that captured an error during the current commit.
10384 var commitPhaseBoundaries = null;
10385 var firstUncaughtError = null;
10386 var didFatal = false;
10387
10388 var isCommitting = false;
10389 var isUnmounting = false;
10390
10391 // Used for performance tracking.
10392 var interruptedBy = null;
10393
10394 function resetContextStack() {
10395 // Reset the stack
10396 reset$1();
10397 // Reset the cursors
10398 resetContext();
10399 resetHostContainer();
10400 }
10401
10402 function commitAllHostEffects() {
10403 while (nextEffect !== null) {
10404 {
10405 ReactDebugCurrentFiber.setCurrentFiber(nextEffect);
10406 }
10407 recordEffect();
10408
10409 var effectTag = nextEffect.effectTag;
10410 if (effectTag & ContentReset) {
10411 commitResetTextContent(nextEffect);
10412 }
10413
10414 if (effectTag & Ref) {
10415 var current = nextEffect.alternate;
10416 if (current !== null) {
10417 commitDetachRef(current);
10418 }
10419 }
10420
10421 // The following switch statement is only concerned about placement,
10422 // updates, and deletions. To avoid needing to add a case for every
10423 // possible bitmap value, we remove the secondary effects from the
10424 // effect tag and switch on that value.
10425 var primaryEffectTag = effectTag & ~(Callback | Err | ContentReset | Ref | PerformedWork);
10426 switch (primaryEffectTag) {
10427 case Placement:
10428 {
10429 commitPlacement(nextEffect);
10430 // Clear the "placement" from effect tag so that we know that this is inserted, before
10431 // any life-cycles like componentDidMount gets called.
10432 // TODO: findDOMNode doesn't rely on this any more but isMounted
10433 // does and isMounted is deprecated anyway so we should be able
10434 // to kill this.
10435 nextEffect.effectTag &= ~Placement;
10436 break;
10437 }
10438 case PlacementAndUpdate:
10439 {
10440 // Placement
10441 commitPlacement(nextEffect);
10442 // Clear the "placement" from effect tag so that we know that this is inserted, before
10443 // any life-cycles like componentDidMount gets called.
10444 nextEffect.effectTag &= ~Placement;
10445
10446 // Update
10447 var _current = nextEffect.alternate;
10448 commitWork(_current, nextEffect);
10449 break;
10450 }
10451 case Update:
10452 {
10453 var _current2 = nextEffect.alternate;
10454 commitWork(_current2, nextEffect);
10455 break;
10456 }
10457 case Deletion:
10458 {
10459 isUnmounting = true;
10460 commitDeletion(nextEffect);
10461 isUnmounting = false;
10462 break;
10463 }
10464 }
10465 nextEffect = nextEffect.nextEffect;
10466 }
10467
10468 {
10469 ReactDebugCurrentFiber.resetCurrentFiber();
10470 }
10471 }
10472
10473 function commitAllLifeCycles() {
10474 while (nextEffect !== null) {
10475 var effectTag = nextEffect.effectTag;
10476
10477 if (effectTag & (Update | Callback)) {
10478 recordEffect();
10479 var current = nextEffect.alternate;
10480 commitLifeCycles(current, nextEffect);
10481 }
10482
10483 if (effectTag & Ref) {
10484 recordEffect();
10485 commitAttachRef(nextEffect);
10486 }
10487
10488 if (effectTag & Err) {
10489 recordEffect();
10490 commitErrorHandling(nextEffect);
10491 }
10492
10493 var next = nextEffect.nextEffect;
10494 // Ensure that we clean these up so that we don't accidentally keep them.
10495 // I'm not actually sure this matters because we can't reset firstEffect
10496 // and lastEffect since they're on every node, not just the effectful
10497 // ones. So we have to clean everything as we reuse nodes anyway.
10498 nextEffect.nextEffect = null;
10499 // Ensure that we reset the effectTag here so that we can rely on effect
10500 // tags to reason about the current life-cycle.
10501 nextEffect = next;
10502 }
10503 }
10504
10505 function commitRoot(finishedWork) {
10506 // We keep track of this so that captureError can collect any boundaries
10507 // that capture an error during the commit phase. The reason these aren't
10508 // local to this function is because errors that occur during cWU are
10509 // captured elsewhere, to prevent the unmount from being interrupted.
10510 isWorking = true;
10511 isCommitting = true;
10512 startCommitTimer();
10513
10514 var root = finishedWork.stateNode;
10515 !(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;
10516 root.isReadyForCommit = false;
10517
10518 // Reset this to null before calling lifecycles
10519 ReactCurrentOwner.current = null;
10520
10521 var firstEffect = void 0;
10522 if (finishedWork.effectTag > PerformedWork) {
10523 // A fiber's effect list consists only of its children, not itself. So if
10524 // the root has an effect, we need to add it to the end of the list. The
10525 // resulting list is the set that would belong to the root's parent, if
10526 // it had one; that is, all the effects in the tree including the root.
10527 if (finishedWork.lastEffect !== null) {
10528 finishedWork.lastEffect.nextEffect = finishedWork;
10529 firstEffect = finishedWork.firstEffect;
10530 } else {
10531 firstEffect = finishedWork;
10532 }
10533 } else {
10534 // There is no effect on the root.
10535 firstEffect = finishedWork.firstEffect;
10536 }
10537
10538 prepareForCommit();
10539
10540 // Commit all the side-effects within a tree. We'll do this in two passes.
10541 // The first pass performs all the host insertions, updates, deletions and
10542 // ref unmounts.
10543 nextEffect = firstEffect;
10544 startCommitHostEffectsTimer();
10545 while (nextEffect !== null) {
10546 var didError = false;
10547 var _error = void 0;
10548 {
10549 invokeGuardedCallback$2(null, commitAllHostEffects, null);
10550 if (hasCaughtError()) {
10551 didError = true;
10552 _error = clearCaughtError();
10553 }
10554 }
10555 if (didError) {
10556 !(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;
10557 captureError(nextEffect, _error);
10558 // Clean-up
10559 if (nextEffect !== null) {
10560 nextEffect = nextEffect.nextEffect;
10561 }
10562 }
10563 }
10564 stopCommitHostEffectsTimer();
10565
10566 resetAfterCommit();
10567
10568 // The work-in-progress tree is now the current tree. This must come after
10569 // the first pass of the commit phase, so that the previous tree is still
10570 // current during componentWillUnmount, but before the second pass, so that
10571 // the finished work is current during componentDidMount/Update.
10572 root.current = finishedWork;
10573
10574 // In the second pass we'll perform all life-cycles and ref callbacks.
10575 // Life-cycles happen as a separate pass so that all placements, updates,
10576 // and deletions in the entire tree have already been invoked.
10577 // This pass also triggers any renderer-specific initial effects.
10578 nextEffect = firstEffect;
10579 startCommitLifeCyclesTimer();
10580 while (nextEffect !== null) {
10581 var _didError = false;
10582 var _error2 = void 0;
10583 {
10584 invokeGuardedCallback$2(null, commitAllLifeCycles, null);
10585 if (hasCaughtError()) {
10586 _didError = true;
10587 _error2 = clearCaughtError();
10588 }
10589 }
10590 if (_didError) {
10591 !(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;
10592 captureError(nextEffect, _error2);
10593 if (nextEffect !== null) {
10594 nextEffect = nextEffect.nextEffect;
10595 }
10596 }
10597 }
10598
10599 isCommitting = false;
10600 isWorking = false;
10601 stopCommitLifeCyclesTimer();
10602 stopCommitTimer();
10603 if (typeof onCommitRoot === 'function') {
10604 onCommitRoot(finishedWork.stateNode);
10605 }
10606 if (true && ReactFiberInstrumentation_1.debugTool) {
10607 ReactFiberInstrumentation_1.debugTool.onCommitWork(finishedWork);
10608 }
10609
10610 // If we caught any errors during this commit, schedule their boundaries
10611 // to update.
10612 if (commitPhaseBoundaries) {
10613 commitPhaseBoundaries.forEach(scheduleErrorRecovery);
10614 commitPhaseBoundaries = null;
10615 }
10616
10617 if (firstUncaughtError !== null) {
10618 var _error3 = firstUncaughtError;
10619 firstUncaughtError = null;
10620 onUncaughtError(_error3);
10621 }
10622
10623 var remainingTime = root.current.expirationTime;
10624
10625 if (remainingTime === NoWork) {
10626 capturedErrors = null;
10627 failedBoundaries = null;
10628 }
10629
10630 return remainingTime;
10631 }
10632
10633 function resetExpirationTime(workInProgress, renderTime) {
10634 if (renderTime !== Never && workInProgress.expirationTime === Never) {
10635 // The children of this component are hidden. Don't bubble their
10636 // expiration times.
10637 return;
10638 }
10639
10640 // Check for pending updates.
10641 var newExpirationTime = getUpdateExpirationTime(workInProgress);
10642
10643 // TODO: Calls need to visit stateNode
10644
10645 // Bubble up the earliest expiration time.
10646 var child = workInProgress.child;
10647 while (child !== null) {
10648 if (child.expirationTime !== NoWork && (newExpirationTime === NoWork || newExpirationTime > child.expirationTime)) {
10649 newExpirationTime = child.expirationTime;
10650 }
10651 child = child.sibling;
10652 }
10653 workInProgress.expirationTime = newExpirationTime;
10654 }
10655
10656 function completeUnitOfWork(workInProgress) {
10657 while (true) {
10658 // The current, flushed, state of this fiber is the alternate.
10659 // Ideally nothing should rely on this, but relying on it here
10660 // means that we don't need an additional field on the work in
10661 // progress.
10662 var current = workInProgress.alternate;
10663 {
10664 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10665 }
10666 var next = completeWork(current, workInProgress, nextRenderExpirationTime);
10667 {
10668 ReactDebugCurrentFiber.resetCurrentFiber();
10669 }
10670
10671 var returnFiber = workInProgress['return'];
10672 var siblingFiber = workInProgress.sibling;
10673
10674 resetExpirationTime(workInProgress, nextRenderExpirationTime);
10675
10676 if (next !== null) {
10677 stopWorkTimer(workInProgress);
10678 if (true && ReactFiberInstrumentation_1.debugTool) {
10679 ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress);
10680 }
10681 // If completing this work spawned new work, do that next. We'll come
10682 // back here again.
10683 return next;
10684 }
10685
10686 if (returnFiber !== null) {
10687 // Append all the effects of the subtree and this fiber onto the effect
10688 // list of the parent. The completion order of the children affects the
10689 // side-effect order.
10690 if (returnFiber.firstEffect === null) {
10691 returnFiber.firstEffect = workInProgress.firstEffect;
10692 }
10693 if (workInProgress.lastEffect !== null) {
10694 if (returnFiber.lastEffect !== null) {
10695 returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;
10696 }
10697 returnFiber.lastEffect = workInProgress.lastEffect;
10698 }
10699
10700 // If this fiber had side-effects, we append it AFTER the children's
10701 // side-effects. We can perform certain side-effects earlier if
10702 // needed, by doing multiple passes over the effect list. We don't want
10703 // to schedule our own side-effect on our own list because if end up
10704 // reusing children we'll schedule this effect onto itself since we're
10705 // at the end.
10706 var effectTag = workInProgress.effectTag;
10707 // Skip both NoWork and PerformedWork tags when creating the effect list.
10708 // PerformedWork effect is read by React DevTools but shouldn't be committed.
10709 if (effectTag > PerformedWork) {
10710 if (returnFiber.lastEffect !== null) {
10711 returnFiber.lastEffect.nextEffect = workInProgress;
10712 } else {
10713 returnFiber.firstEffect = workInProgress;
10714 }
10715 returnFiber.lastEffect = workInProgress;
10716 }
10717 }
10718
10719 stopWorkTimer(workInProgress);
10720 if (true && ReactFiberInstrumentation_1.debugTool) {
10721 ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress);
10722 }
10723
10724 if (siblingFiber !== null) {
10725 // If there is more work to do in this returnFiber, do that next.
10726 return siblingFiber;
10727 } else if (returnFiber !== null) {
10728 // If there's no more work in this returnFiber. Complete the returnFiber.
10729 workInProgress = returnFiber;
10730 continue;
10731 } else {
10732 // We've reached the root.
10733 var root = workInProgress.stateNode;
10734 root.isReadyForCommit = true;
10735 return null;
10736 }
10737 }
10738
10739 // Without this explicit null return Flow complains of invalid return type
10740 // TODO Remove the above while(true) loop
10741 // eslint-disable-next-line no-unreachable
10742 return null;
10743 }
10744
10745 function performUnitOfWork(workInProgress) {
10746 // The current, flushed, state of this fiber is the alternate.
10747 // Ideally nothing should rely on this, but relying on it here
10748 // means that we don't need an additional field on the work in
10749 // progress.
10750 var current = workInProgress.alternate;
10751
10752 // See if beginning this work spawns more work.
10753 startWorkTimer(workInProgress);
10754 {
10755 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10756 }
10757
10758 var next = beginWork(current, workInProgress, nextRenderExpirationTime);
10759 {
10760 ReactDebugCurrentFiber.resetCurrentFiber();
10761 }
10762 if (true && ReactFiberInstrumentation_1.debugTool) {
10763 ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
10764 }
10765
10766 if (next === null) {
10767 // If this doesn't spawn new work, complete the current work.
10768 next = completeUnitOfWork(workInProgress);
10769 }
10770
10771 ReactCurrentOwner.current = null;
10772
10773 return next;
10774 }
10775
10776 function performFailedUnitOfWork(workInProgress) {
10777 // The current, flushed, state of this fiber is the alternate.
10778 // Ideally nothing should rely on this, but relying on it here
10779 // means that we don't need an additional field on the work in
10780 // progress.
10781 var current = workInProgress.alternate;
10782
10783 // See if beginning this work spawns more work.
10784 startWorkTimer(workInProgress);
10785 {
10786 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10787 }
10788 var next = beginFailedWork(current, workInProgress, nextRenderExpirationTime);
10789 {
10790 ReactDebugCurrentFiber.resetCurrentFiber();
10791 }
10792 if (true && ReactFiberInstrumentation_1.debugTool) {
10793 ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
10794 }
10795
10796 if (next === null) {
10797 // If this doesn't spawn new work, complete the current work.
10798 next = completeUnitOfWork(workInProgress);
10799 }
10800
10801 ReactCurrentOwner.current = null;
10802
10803 return next;
10804 }
10805
10806 function workLoop(expirationTime) {
10807 if (capturedErrors !== null) {
10808 // If there are unhandled errors, switch to the slow work loop.
10809 // TODO: How to avoid this check in the fast path? Maybe the renderer
10810 // could keep track of which roots have unhandled errors and call a
10811 // forked version of renderRoot.
10812 slowWorkLoopThatChecksForFailedWork(expirationTime);
10813 return;
10814 }
10815 if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
10816 return;
10817 }
10818
10819 if (nextRenderExpirationTime <= mostRecentCurrentTime) {
10820 // Flush all expired work.
10821 while (nextUnitOfWork !== null) {
10822 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10823 }
10824 } else {
10825 // Flush asynchronous work until the deadline runs out of time.
10826 while (nextUnitOfWork !== null && !shouldYield()) {
10827 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10828 }
10829 }
10830 }
10831
10832 function slowWorkLoopThatChecksForFailedWork(expirationTime) {
10833 if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
10834 return;
10835 }
10836
10837 if (nextRenderExpirationTime <= mostRecentCurrentTime) {
10838 // Flush all expired work.
10839 while (nextUnitOfWork !== null) {
10840 if (hasCapturedError(nextUnitOfWork)) {
10841 // Use a forked version of performUnitOfWork
10842 nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork);
10843 } else {
10844 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10845 }
10846 }
10847 } else {
10848 // Flush asynchronous work until the deadline runs out of time.
10849 while (nextUnitOfWork !== null && !shouldYield()) {
10850 if (hasCapturedError(nextUnitOfWork)) {
10851 // Use a forked version of performUnitOfWork
10852 nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork);
10853 } else {
10854 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10855 }
10856 }
10857 }
10858 }
10859
10860 function renderRootCatchBlock(root, failedWork, boundary, expirationTime) {
10861 // We're going to restart the error boundary that captured the error.
10862 // Conceptually, we're unwinding the stack. We need to unwind the
10863 // context stack, too.
10864 unwindContexts(failedWork, boundary);
10865
10866 // Restart the error boundary using a forked version of
10867 // performUnitOfWork that deletes the boundary's children. The entire
10868 // failed subree will be unmounted. During the commit phase, a special
10869 // lifecycle method is called on the error boundary, which triggers
10870 // a re-render.
10871 nextUnitOfWork = performFailedUnitOfWork(boundary);
10872
10873 // Continue working.
10874 workLoop(expirationTime);
10875 }
10876
10877 function renderRoot(root, expirationTime) {
10878 !!isWorking ? invariant_1(false, 'renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
10879 isWorking = true;
10880
10881 // We're about to mutate the work-in-progress tree. If the root was pending
10882 // commit, it no longer is: we'll need to complete it again.
10883 root.isReadyForCommit = false;
10884
10885 // Check if we're starting from a fresh stack, or if we're resuming from
10886 // previously yielded work.
10887 if (root !== nextRoot || expirationTime !== nextRenderExpirationTime || nextUnitOfWork === null) {
10888 // Reset the stack and start working from the root.
10889 resetContextStack();
10890 nextRoot = root;
10891 nextRenderExpirationTime = expirationTime;
10892 nextUnitOfWork = createWorkInProgress(nextRoot.current, null, expirationTime);
10893 }
10894
10895 startWorkLoopTimer(nextUnitOfWork);
10896
10897 var didError = false;
10898 var error = null;
10899 {
10900 invokeGuardedCallback$2(null, workLoop, null, expirationTime);
10901 if (hasCaughtError()) {
10902 didError = true;
10903 error = clearCaughtError();
10904 }
10905 }
10906
10907 // An error was thrown during the render phase.
10908 while (didError) {
10909 if (didFatal) {
10910 // This was a fatal error. Don't attempt to recover from it.
10911 firstUncaughtError = error;
10912 break;
10913 }
10914
10915 var failedWork = nextUnitOfWork;
10916 if (failedWork === null) {
10917 // An error was thrown but there's no current unit of work. This can
10918 // happen during the commit phase if there's a bug in the renderer.
10919 didFatal = true;
10920 continue;
10921 }
10922
10923 // "Capture" the error by finding the nearest boundary. If there is no
10924 // error boundary, we use the root.
10925 var boundary = captureError(failedWork, error);
10926 !(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;
10927
10928 if (didFatal) {
10929 // The error we just captured was a fatal error. This happens
10930 // when the error propagates to the root more than once.
10931 continue;
10932 }
10933
10934 didError = false;
10935 error = null;
10936 {
10937 invokeGuardedCallback$2(null, renderRootCatchBlock, null, root, failedWork, boundary, expirationTime);
10938 if (hasCaughtError()) {
10939 didError = true;
10940 error = clearCaughtError();
10941 continue;
10942 }
10943 }
10944 // We're finished working. Exit the error loop.
10945 break;
10946 }
10947
10948 var uncaughtError = firstUncaughtError;
10949
10950 // We're done performing work. Time to clean up.
10951 stopWorkLoopTimer(interruptedBy);
10952 interruptedBy = null;
10953 isWorking = false;
10954 didFatal = false;
10955 firstUncaughtError = null;
10956
10957 if (uncaughtError !== null) {
10958 onUncaughtError(uncaughtError);
10959 }
10960
10961 return root.isReadyForCommit ? root.current.alternate : null;
10962 }
10963
10964 // Returns the boundary that captured the error, or null if the error is ignored
10965 function captureError(failedWork, error) {
10966 // It is no longer valid because we exited the user code.
10967 ReactCurrentOwner.current = null;
10968 {
10969 ReactDebugCurrentFiber.resetCurrentFiber();
10970 }
10971
10972 // Search for the nearest error boundary.
10973 var boundary = null;
10974
10975 // Passed to logCapturedError()
10976 var errorBoundaryFound = false;
10977 var willRetry = false;
10978 var errorBoundaryName = null;
10979
10980 // Host containers are a special case. If the failed work itself is a host
10981 // container, then it acts as its own boundary. In all other cases, we
10982 // ignore the work itself and only search through the parents.
10983 if (failedWork.tag === HostRoot) {
10984 boundary = failedWork;
10985
10986 if (isFailedBoundary(failedWork)) {
10987 // If this root already failed, there must have been an error when
10988 // attempting to unmount it. This is a worst-case scenario and
10989 // should only be possible if there's a bug in the renderer.
10990 didFatal = true;
10991 }
10992 } else {
10993 var node = failedWork['return'];
10994 while (node !== null && boundary === null) {
10995 if (node.tag === ClassComponent) {
10996 var instance = node.stateNode;
10997 if (typeof instance.componentDidCatch === 'function') {
10998 errorBoundaryFound = true;
10999 errorBoundaryName = getComponentName(node);
11000
11001 // Found an error boundary!
11002 boundary = node;
11003 willRetry = true;
11004 }
11005 } else if (node.tag === HostRoot) {
11006 // Treat the root like a no-op error boundary
11007 boundary = node;
11008 }
11009
11010 if (isFailedBoundary(node)) {
11011 // This boundary is already in a failed state.
11012
11013 // If we're currently unmounting, that means this error was
11014 // thrown while unmounting a failed subtree. We should ignore
11015 // the error.
11016 if (isUnmounting) {
11017 return null;
11018 }
11019
11020 // If we're in the commit phase, we should check to see if
11021 // this boundary already captured an error during this commit.
11022 // This case exists because multiple errors can be thrown during
11023 // a single commit without interruption.
11024 if (commitPhaseBoundaries !== null && (commitPhaseBoundaries.has(node) || node.alternate !== null && commitPhaseBoundaries.has(node.alternate))) {
11025 // If so, we should ignore this error.
11026 return null;
11027 }
11028
11029 // The error should propagate to the next boundary -? we keep looking.
11030 boundary = null;
11031 willRetry = false;
11032 }
11033
11034 node = node['return'];
11035 }
11036 }
11037
11038 if (boundary !== null) {
11039 // Add to the collection of failed boundaries. This lets us know that
11040 // subsequent errors in this subtree should propagate to the next boundary.
11041 if (failedBoundaries === null) {
11042 failedBoundaries = new Set();
11043 }
11044 failedBoundaries.add(boundary);
11045
11046 // This method is unsafe outside of the begin and complete phases.
11047 // We might be in the commit phase when an error is captured.
11048 // The risk is that the return path from this Fiber may not be accurate.
11049 // That risk is acceptable given the benefit of providing users more context.
11050 var _componentStack = getStackAddendumByWorkInProgressFiber(failedWork);
11051 var _componentName = getComponentName(failedWork);
11052
11053 // Add to the collection of captured errors. This is stored as a global
11054 // map of errors and their component stack location keyed by the boundaries
11055 // that capture them. We mostly use this Map as a Set; it's a Map only to
11056 // avoid adding a field to Fiber to store the error.
11057 if (capturedErrors === null) {
11058 capturedErrors = new Map();
11059 }
11060
11061 var capturedError = {
11062 componentName: _componentName,
11063 componentStack: _componentStack,
11064 error: error,
11065 errorBoundary: errorBoundaryFound ? boundary.stateNode : null,
11066 errorBoundaryFound: errorBoundaryFound,
11067 errorBoundaryName: errorBoundaryName,
11068 willRetry: willRetry
11069 };
11070
11071 capturedErrors.set(boundary, capturedError);
11072
11073 try {
11074 logCapturedError(capturedError);
11075 } catch (e) {
11076 // Prevent cycle if logCapturedError() throws.
11077 // A cycle may still occur if logCapturedError renders a component that throws.
11078 var suppressLogging = e && e.suppressReactErrorLogging;
11079 if (!suppressLogging) {
11080 console.error(e);
11081 }
11082 }
11083
11084 // If we're in the commit phase, defer scheduling an update on the
11085 // boundary until after the commit is complete
11086 if (isCommitting) {
11087 if (commitPhaseBoundaries === null) {
11088 commitPhaseBoundaries = new Set();
11089 }
11090 commitPhaseBoundaries.add(boundary);
11091 } else {
11092 // Otherwise, schedule an update now.
11093 // TODO: Is this actually necessary during the render phase? Is it
11094 // possible to unwind and continue rendering at the same priority,
11095 // without corrupting internal state?
11096 scheduleErrorRecovery(boundary);
11097 }
11098 return boundary;
11099 } else if (firstUncaughtError === null) {
11100 // If no boundary is found, we'll need to throw the error
11101 firstUncaughtError = error;
11102 }
11103 return null;
11104 }
11105
11106 function hasCapturedError(fiber) {
11107 // TODO: capturedErrors should store the boundary instance, to avoid needing
11108 // to check the alternate.
11109 return capturedErrors !== null && (capturedErrors.has(fiber) || fiber.alternate !== null && capturedErrors.has(fiber.alternate));
11110 }
11111
11112 function isFailedBoundary(fiber) {
11113 // TODO: failedBoundaries should store the boundary instance, to avoid
11114 // needing to check the alternate.
11115 return failedBoundaries !== null && (failedBoundaries.has(fiber) || fiber.alternate !== null && failedBoundaries.has(fiber.alternate));
11116 }
11117
11118 function commitErrorHandling(effectfulFiber) {
11119 var capturedError = void 0;
11120 if (capturedErrors !== null) {
11121 capturedError = capturedErrors.get(effectfulFiber);
11122 capturedErrors['delete'](effectfulFiber);
11123 if (capturedError == null) {
11124 if (effectfulFiber.alternate !== null) {
11125 effectfulFiber = effectfulFiber.alternate;
11126 capturedError = capturedErrors.get(effectfulFiber);
11127 capturedErrors['delete'](effectfulFiber);
11128 }
11129 }
11130 }
11131
11132 !(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;
11133
11134 switch (effectfulFiber.tag) {
11135 case ClassComponent:
11136 var instance = effectfulFiber.stateNode;
11137
11138 var info = {
11139 componentStack: capturedError.componentStack
11140 };
11141
11142 // Allow the boundary to handle the error, usually by scheduling
11143 // an update to itself
11144 instance.componentDidCatch(capturedError.error, info);
11145 return;
11146 case HostRoot:
11147 if (firstUncaughtError === null) {
11148 firstUncaughtError = capturedError.error;
11149 }
11150 return;
11151 default:
11152 invariant_1(false, 'Invalid type of work. This error is likely caused by a bug in React. Please file an issue.');
11153 }
11154 }
11155
11156 function unwindContexts(from, to) {
11157 var node = from;
11158 while (node !== null) {
11159 switch (node.tag) {
11160 case ClassComponent:
11161 popContextProvider(node);
11162 break;
11163 case HostComponent:
11164 popHostContext(node);
11165 break;
11166 case HostRoot:
11167 popHostContainer(node);
11168 break;
11169 case HostPortal:
11170 popHostContainer(node);
11171 break;
11172 }
11173 if (node === to || node.alternate === to) {
11174 stopFailedWorkTimer(node);
11175 break;
11176 } else {
11177 stopWorkTimer(node);
11178 }
11179 node = node['return'];
11180 }
11181 }
11182
11183 function computeAsyncExpiration() {
11184 // Given the current clock time, returns an expiration time. We use rounding
11185 // to batch like updates together.
11186 // Should complete within ~1000ms. 1200ms max.
11187 var currentTime = recalculateCurrentTime();
11188 var expirationMs = 1000;
11189 var bucketSizeMs = 200;
11190 return computeExpirationBucket(currentTime, expirationMs, bucketSizeMs);
11191 }
11192
11193 // Creates a unique async expiration time.
11194 function computeUniqueAsyncExpiration() {
11195 var result = computeAsyncExpiration();
11196 if (result <= lastUniqueAsyncExpiration) {
11197 // Since we assume the current time monotonically increases, we only hit
11198 // this branch when computeUniqueAsyncExpiration is fired multiple times
11199 // within a 200ms window (or whatever the async bucket size is).
11200 result = lastUniqueAsyncExpiration + 1;
11201 }
11202 lastUniqueAsyncExpiration = result;
11203 return lastUniqueAsyncExpiration;
11204 }
11205
11206 function computeExpirationForFiber(fiber) {
11207 var expirationTime = void 0;
11208 if (expirationContext !== NoWork) {
11209 // An explicit expiration context was set;
11210 expirationTime = expirationContext;
11211 } else if (isWorking) {
11212 if (isCommitting) {
11213 // Updates that occur during the commit phase should have sync priority
11214 // by default.
11215 expirationTime = Sync;
11216 } else {
11217 // Updates during the render phase should expire at the same time as
11218 // the work that is being rendered.
11219 expirationTime = nextRenderExpirationTime;
11220 }
11221 } else {
11222 // No explicit expiration context was set, and we're not currently
11223 // performing work. Calculate a new expiration time.
11224 if (useSyncScheduling && !(fiber.internalContextTag & AsyncUpdates)) {
11225 // This is a sync update
11226 expirationTime = Sync;
11227 } else {
11228 // This is an async update
11229 expirationTime = computeAsyncExpiration();
11230 }
11231 }
11232 return expirationTime;
11233 }
11234
11235 function scheduleWork(fiber, expirationTime) {
11236 return scheduleWorkImpl(fiber, expirationTime, false);
11237 }
11238
11239 function checkRootNeedsClearing(root, fiber, expirationTime) {
11240 if (!isWorking && root === nextRoot && expirationTime < nextRenderExpirationTime) {
11241 // Restart the root from the top.
11242 if (nextUnitOfWork !== null) {
11243 // This is an interruption. (Used for performance tracking.)
11244 interruptedBy = fiber;
11245 }
11246 nextRoot = null;
11247 nextUnitOfWork = null;
11248 nextRenderExpirationTime = NoWork;
11249 }
11250 }
11251
11252 function scheduleWorkImpl(fiber, expirationTime, isErrorRecovery) {
11253 recordScheduleUpdate();
11254
11255 {
11256 if (!isErrorRecovery && fiber.tag === ClassComponent) {
11257 var instance = fiber.stateNode;
11258 warnAboutInvalidUpdates(instance);
11259 }
11260 }
11261
11262 var node = fiber;
11263 while (node !== null) {
11264 // Walk the parent path to the root and update each node's
11265 // expiration time.
11266 if (node.expirationTime === NoWork || node.expirationTime > expirationTime) {
11267 node.expirationTime = expirationTime;
11268 }
11269 if (node.alternate !== null) {
11270 if (node.alternate.expirationTime === NoWork || node.alternate.expirationTime > expirationTime) {
11271 node.alternate.expirationTime = expirationTime;
11272 }
11273 }
11274 if (node['return'] === null) {
11275 if (node.tag === HostRoot) {
11276 var root = node.stateNode;
11277
11278 checkRootNeedsClearing(root, fiber, expirationTime);
11279 requestWork(root, expirationTime);
11280 checkRootNeedsClearing(root, fiber, expirationTime);
11281 } else {
11282 {
11283 if (!isErrorRecovery && fiber.tag === ClassComponent) {
11284 warnAboutUpdateOnUnmounted(fiber);
11285 }
11286 }
11287 return;
11288 }
11289 }
11290 node = node['return'];
11291 }
11292 }
11293
11294 function scheduleErrorRecovery(fiber) {
11295 scheduleWorkImpl(fiber, Sync, true);
11296 }
11297
11298 function recalculateCurrentTime() {
11299 // Subtract initial time so it fits inside 32bits
11300 var ms = now() - startTime;
11301 mostRecentCurrentTime = msToExpirationTime(ms);
11302 return mostRecentCurrentTime;
11303 }
11304
11305 function deferredUpdates(fn) {
11306 var previousExpirationContext = expirationContext;
11307 expirationContext = computeAsyncExpiration();
11308 try {
11309 return fn();
11310 } finally {
11311 expirationContext = previousExpirationContext;
11312 }
11313 }
11314
11315 function syncUpdates(fn) {
11316 var previousExpirationContext = expirationContext;
11317 expirationContext = Sync;
11318 try {
11319 return fn();
11320 } finally {
11321 expirationContext = previousExpirationContext;
11322 }
11323 }
11324
11325 // TODO: Everything below this is written as if it has been lifted to the
11326 // renderers. I'll do this in a follow-up.
11327
11328 // Linked-list of roots
11329 var firstScheduledRoot = null;
11330 var lastScheduledRoot = null;
11331
11332 var callbackExpirationTime = NoWork;
11333 var callbackID = -1;
11334 var isRendering = false;
11335 var nextFlushedRoot = null;
11336 var nextFlushedExpirationTime = NoWork;
11337 var deadlineDidExpire = false;
11338 var hasUnhandledError = false;
11339 var unhandledError = null;
11340 var deadline = null;
11341
11342 var isBatchingUpdates = false;
11343 var isUnbatchingUpdates = false;
11344
11345 var completedBatches = null;
11346
11347 // Use these to prevent an infinite loop of nested updates
11348 var NESTED_UPDATE_LIMIT = 1000;
11349 var nestedUpdateCount = 0;
11350
11351 var timeHeuristicForUnitOfWork = 1;
11352
11353 function scheduleCallbackWithExpiration(expirationTime) {
11354 if (callbackExpirationTime !== NoWork) {
11355 // A callback is already scheduled. Check its expiration time (timeout).
11356 if (expirationTime > callbackExpirationTime) {
11357 // Existing callback has sufficient timeout. Exit.
11358 return;
11359 } else {
11360 // Existing callback has insufficient timeout. Cancel and schedule a
11361 // new one.
11362 cancelDeferredCallback(callbackID);
11363 }
11364 // The request callback timer is already running. Don't start a new one.
11365 } else {
11366 startRequestCallbackTimer();
11367 }
11368
11369 // Compute a timeout for the given expiration time.
11370 var currentMs = now() - startTime;
11371 var expirationMs = expirationTimeToMs(expirationTime);
11372 var timeout = expirationMs - currentMs;
11373
11374 callbackExpirationTime = expirationTime;
11375 callbackID = scheduleDeferredCallback(performAsyncWork, { timeout: timeout });
11376 }
11377
11378 // requestWork is called by the scheduler whenever a root receives an update.
11379 // It's up to the renderer to call renderRoot at some point in the future.
11380 function requestWork(root, expirationTime) {
11381 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
11382 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.');
11383 }
11384
11385 // Add the root to the schedule.
11386 // Check if this root is already part of the schedule.
11387 if (root.nextScheduledRoot === null) {
11388 // This root is not already scheduled. Add it.
11389 root.remainingExpirationTime = expirationTime;
11390 if (lastScheduledRoot === null) {
11391 firstScheduledRoot = lastScheduledRoot = root;
11392 root.nextScheduledRoot = root;
11393 } else {
11394 lastScheduledRoot.nextScheduledRoot = root;
11395 lastScheduledRoot = root;
11396 lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
11397 }
11398 } else {
11399 // This root is already scheduled, but its priority may have increased.
11400 var remainingExpirationTime = root.remainingExpirationTime;
11401 if (remainingExpirationTime === NoWork || expirationTime < remainingExpirationTime) {
11402 // Update the priority.
11403 root.remainingExpirationTime = expirationTime;
11404 }
11405 }
11406
11407 if (isRendering) {
11408 // Prevent reentrancy. Remaining work will be scheduled at the end of
11409 // the currently rendering batch.
11410 return;
11411 }
11412
11413 if (isBatchingUpdates) {
11414 // Flush work at the end of the batch.
11415 if (isUnbatchingUpdates) {
11416 // ...unless we're inside unbatchedUpdates, in which case we should
11417 // flush it now.
11418 nextFlushedRoot = root;
11419 nextFlushedExpirationTime = Sync;
11420 performWorkOnRoot(root, Sync, recalculateCurrentTime());
11421 }
11422 return;
11423 }
11424
11425 // TODO: Get rid of Sync and use current time?
11426 if (expirationTime === Sync) {
11427 performWork(Sync, null);
11428 } else {
11429 scheduleCallbackWithExpiration(expirationTime);
11430 }
11431 }
11432
11433 function findHighestPriorityRoot() {
11434 var highestPriorityWork = NoWork;
11435 var highestPriorityRoot = null;
11436
11437 if (lastScheduledRoot !== null) {
11438 var previousScheduledRoot = lastScheduledRoot;
11439 var root = firstScheduledRoot;
11440 while (root !== null) {
11441 var remainingExpirationTime = root.remainingExpirationTime;
11442 if (remainingExpirationTime === NoWork) {
11443 // This root no longer has work. Remove it from the scheduler.
11444
11445 // TODO: This check is redudant, but Flow is confused by the branch
11446 // below where we set lastScheduledRoot to null, even though we break
11447 // from the loop right after.
11448 !(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;
11449 if (root === root.nextScheduledRoot) {
11450 // This is the only root in the list.
11451 root.nextScheduledRoot = null;
11452 firstScheduledRoot = lastScheduledRoot = null;
11453 break;
11454 } else if (root === firstScheduledRoot) {
11455 // This is the first root in the list.
11456 var next = root.nextScheduledRoot;
11457 firstScheduledRoot = next;
11458 lastScheduledRoot.nextScheduledRoot = next;
11459 root.nextScheduledRoot = null;
11460 } else if (root === lastScheduledRoot) {
11461 // This is the last root in the list.
11462 lastScheduledRoot = previousScheduledRoot;
11463 lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
11464 root.nextScheduledRoot = null;
11465 break;
11466 } else {
11467 previousScheduledRoot.nextScheduledRoot = root.nextScheduledRoot;
11468 root.nextScheduledRoot = null;
11469 }
11470 root = previousScheduledRoot.nextScheduledRoot;
11471 } else {
11472 if (highestPriorityWork === NoWork || remainingExpirationTime < highestPriorityWork) {
11473 // Update the priority, if it's higher
11474 highestPriorityWork = remainingExpirationTime;
11475 highestPriorityRoot = root;
11476 }
11477 if (root === lastScheduledRoot) {
11478 break;
11479 }
11480 previousScheduledRoot = root;
11481 root = root.nextScheduledRoot;
11482 }
11483 }
11484 }
11485
11486 // If the next root is the same as the previous root, this is a nested
11487 // update. To prevent an infinite loop, increment the nested update count.
11488 var previousFlushedRoot = nextFlushedRoot;
11489 if (previousFlushedRoot !== null && previousFlushedRoot === highestPriorityRoot) {
11490 nestedUpdateCount++;
11491 } else {
11492 // Reset whenever we switch roots.
11493 nestedUpdateCount = 0;
11494 }
11495 nextFlushedRoot = highestPriorityRoot;
11496 nextFlushedExpirationTime = highestPriorityWork;
11497 }
11498
11499 function performAsyncWork(dl) {
11500 performWork(NoWork, dl);
11501 }
11502
11503 function performWork(minExpirationTime, dl) {
11504 deadline = dl;
11505
11506 // Keep working on roots until there's no more work, or until the we reach
11507 // the deadline.
11508 findHighestPriorityRoot();
11509
11510 if (enableUserTimingAPI && deadline !== null) {
11511 var didExpire = nextFlushedExpirationTime < recalculateCurrentTime();
11512 stopRequestCallbackTimer(didExpire);
11513 }
11514
11515 while (nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && (minExpirationTime === NoWork || nextFlushedExpirationTime <= minExpirationTime) && !deadlineDidExpire) {
11516 performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, recalculateCurrentTime());
11517 // Find the next highest priority work.
11518 findHighestPriorityRoot();
11519 }
11520
11521 // We're done flushing work. Either we ran out of time in this callback,
11522 // or there's no more work left with sufficient priority.
11523
11524 // If we're inside a callback, set this to false since we just completed it.
11525 if (deadline !== null) {
11526 callbackExpirationTime = NoWork;
11527 callbackID = -1;
11528 }
11529 // If there's work left over, schedule a new callback.
11530 if (nextFlushedExpirationTime !== NoWork) {
11531 scheduleCallbackWithExpiration(nextFlushedExpirationTime);
11532 }
11533
11534 // Clean-up.
11535 deadline = null;
11536 deadlineDidExpire = false;
11537 nestedUpdateCount = 0;
11538
11539 finishRendering();
11540 }
11541
11542 function flushRoot(root, expirationTime) {
11543 !!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;
11544 // Perform work on root as if the given expiration time is the current time.
11545 // This has the effect of synchronously flushing all work up to and
11546 // including the given time.
11547 performWorkOnRoot(root, expirationTime, expirationTime);
11548 finishRendering();
11549 }
11550
11551 function finishRendering() {
11552 if (completedBatches !== null) {
11553 var batches = completedBatches;
11554 completedBatches = null;
11555 for (var i = 0; i < batches.length; i++) {
11556 var batch = batches[i];
11557 try {
11558 batch._onComplete();
11559 } catch (error) {
11560 if (!hasUnhandledError) {
11561 hasUnhandledError = true;
11562 unhandledError = error;
11563 }
11564 }
11565 }
11566 }
11567
11568 if (hasUnhandledError) {
11569 var _error4 = unhandledError;
11570 unhandledError = null;
11571 hasUnhandledError = false;
11572 throw _error4;
11573 }
11574 }
11575
11576 function performWorkOnRoot(root, expirationTime, currentTime) {
11577 !!isRendering ? invariant_1(false, 'performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
11578
11579 isRendering = true;
11580
11581 // Check if this is async work or sync/expired work.
11582 if (expirationTime <= currentTime) {
11583 // Flush sync work.
11584 var finishedWork = root.finishedWork;
11585 if (finishedWork !== null) {
11586 // This root is already complete. We can commit it.
11587 completeRoot(root, finishedWork, expirationTime);
11588 } else {
11589 root.finishedWork = null;
11590 finishedWork = renderRoot(root, expirationTime);
11591 if (finishedWork !== null) {
11592 // We've completed the root. Commit it.
11593 completeRoot(root, finishedWork, expirationTime);
11594 }
11595 }
11596 } else {
11597 // Flush async work.
11598 var _finishedWork = root.finishedWork;
11599 if (_finishedWork !== null) {
11600 // This root is already complete. We can commit it.
11601 completeRoot(root, _finishedWork, expirationTime);
11602 } else {
11603 root.finishedWork = null;
11604 _finishedWork = renderRoot(root, expirationTime);
11605 if (_finishedWork !== null) {
11606 // We've completed the root. Check the deadline one more time
11607 // before committing.
11608 if (!shouldYield()) {
11609 // Still time left. Commit the root.
11610 completeRoot(root, _finishedWork, expirationTime);
11611 } else {
11612 // There's no time left. Mark this root as complete. We'll come
11613 // back and commit it later.
11614 root.finishedWork = _finishedWork;
11615 }
11616 }
11617 }
11618 }
11619
11620 isRendering = false;
11621 }
11622
11623 function completeRoot(root, finishedWork, expirationTime) {
11624 // Check if there's a batch that matches this expiration time.
11625 var firstBatch = root.firstBatch;
11626 if (firstBatch !== null && firstBatch._expirationTime <= expirationTime) {
11627 if (completedBatches === null) {
11628 completedBatches = [firstBatch];
11629 } else {
11630 completedBatches.push(firstBatch);
11631 }
11632 if (firstBatch._defer) {
11633 // This root is blocked from committing by a batch. Unschedule it until
11634 // we receive another update.
11635 root.finishedWork = finishedWork;
11636 root.remainingExpirationTime = NoWork;
11637 return;
11638 }
11639 }
11640
11641 // Commit the root.
11642 root.finishedWork = null;
11643 root.remainingExpirationTime = commitRoot(finishedWork);
11644 }
11645
11646 // When working on async work, the reconciler asks the renderer if it should
11647 // yield execution. For DOM, we implement this with requestIdleCallback.
11648 function shouldYield() {
11649 if (deadline === null) {
11650 return false;
11651 }
11652 if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
11653 // Disregard deadline.didTimeout. Only expired work should be flushed
11654 // during a timeout. This path is only hit for non-expired work.
11655 return false;
11656 }
11657 deadlineDidExpire = true;
11658 return true;
11659 }
11660
11661 // TODO: Not happy about this hook. Conceptually, renderRoot should return a
11662 // tuple of (isReadyForCommit, didError, error)
11663 function onUncaughtError(error) {
11664 !(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;
11665 // Unschedule this root so we don't work on it again until there's
11666 // another update.
11667 nextFlushedRoot.remainingExpirationTime = NoWork;
11668 if (!hasUnhandledError) {
11669 hasUnhandledError = true;
11670 unhandledError = error;
11671 }
11672 }
11673
11674 // TODO: Batching should be implemented at the renderer level, not inside
11675 // the reconciler.
11676 function batchedUpdates(fn, a) {
11677 var previousIsBatchingUpdates = isBatchingUpdates;
11678 isBatchingUpdates = true;
11679 try {
11680 return fn(a);
11681 } finally {
11682 isBatchingUpdates = previousIsBatchingUpdates;
11683 if (!isBatchingUpdates && !isRendering) {
11684 performWork(Sync, null);
11685 }
11686 }
11687 }
11688
11689 // TODO: Batching should be implemented at the renderer level, not inside
11690 // the reconciler.
11691 function unbatchedUpdates(fn) {
11692 if (isBatchingUpdates && !isUnbatchingUpdates) {
11693 isUnbatchingUpdates = true;
11694 try {
11695 return fn();
11696 } finally {
11697 isUnbatchingUpdates = false;
11698 }
11699 }
11700 return fn();
11701 }
11702
11703 // TODO: Batching should be implemented at the renderer level, not within
11704 // the reconciler.
11705 function flushSync(fn) {
11706 var previousIsBatchingUpdates = isBatchingUpdates;
11707 isBatchingUpdates = true;
11708 try {
11709 return syncUpdates(fn);
11710 } finally {
11711 isBatchingUpdates = previousIsBatchingUpdates;
11712 !!isRendering ? invariant_1(false, 'flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.') : void 0;
11713 performWork(Sync, null);
11714 }
11715 }
11716
11717 return {
11718 computeExpirationForFiber: computeExpirationForFiber,
11719 scheduleWork: scheduleWork,
11720 requestWork: requestWork,
11721 flushRoot: flushRoot,
11722 batchedUpdates: batchedUpdates,
11723 unbatchedUpdates: unbatchedUpdates,
11724 flushSync: flushSync,
11725 deferredUpdates: deferredUpdates,
11726 computeUniqueAsyncExpiration: computeUniqueAsyncExpiration
11727 };
11728};
11729
11730var didWarnAboutNestedUpdates = void 0;
11731
11732{
11733 didWarnAboutNestedUpdates = false;
11734}
11735
11736// 0 is PROD, 1 is DEV.
11737// Might add PROFILE later.
11738
11739
11740function getContextForSubtree(parentComponent) {
11741 if (!parentComponent) {
11742 return emptyObject_1;
11743 }
11744
11745 var fiber = get(parentComponent);
11746 var parentContext = findCurrentUnmaskedContext(fiber);
11747 return isContextProvider(fiber) ? processChildContext(fiber, parentContext) : parentContext;
11748}
11749
11750var ReactFiberReconciler$1 = function (config) {
11751 var getPublicInstance = config.getPublicInstance;
11752
11753 var _ReactFiberScheduler = ReactFiberScheduler(config),
11754 computeUniqueAsyncExpiration = _ReactFiberScheduler.computeUniqueAsyncExpiration,
11755 computeExpirationForFiber = _ReactFiberScheduler.computeExpirationForFiber,
11756 scheduleWork = _ReactFiberScheduler.scheduleWork,
11757 requestWork = _ReactFiberScheduler.requestWork,
11758 flushRoot = _ReactFiberScheduler.flushRoot,
11759 batchedUpdates = _ReactFiberScheduler.batchedUpdates,
11760 unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates,
11761 flushSync = _ReactFiberScheduler.flushSync,
11762 deferredUpdates = _ReactFiberScheduler.deferredUpdates;
11763
11764 function scheduleRootUpdate(current, element, expirationTime, callback) {
11765 {
11766 if (ReactDebugCurrentFiber.phase === 'render' && ReactDebugCurrentFiber.current !== null && !didWarnAboutNestedUpdates) {
11767 didWarnAboutNestedUpdates = true;
11768 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');
11769 }
11770 }
11771
11772 callback = callback === undefined ? null : callback;
11773 {
11774 warning_1(callback === null || typeof callback === 'function', 'render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback);
11775 }
11776
11777 var update = {
11778 expirationTime: expirationTime,
11779 partialState: { element: element },
11780 callback: callback,
11781 isReplace: false,
11782 isForced: false,
11783 next: null
11784 };
11785 insertUpdateIntoFiber(current, update);
11786 scheduleWork(current, expirationTime);
11787
11788 return expirationTime;
11789 }
11790
11791 function updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback) {
11792 // TODO: If this is a nested container, this won't be the root.
11793 var current = container.current;
11794
11795 {
11796 if (ReactFiberInstrumentation_1.debugTool) {
11797 if (current.alternate === null) {
11798 ReactFiberInstrumentation_1.debugTool.onMountContainer(container);
11799 } else if (element === null) {
11800 ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container);
11801 } else {
11802 ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container);
11803 }
11804 }
11805 }
11806
11807 var context = getContextForSubtree(parentComponent);
11808 if (container.context === null) {
11809 container.context = context;
11810 } else {
11811 container.pendingContext = context;
11812 }
11813
11814 return scheduleRootUpdate(current, element, expirationTime, callback);
11815 }
11816
11817 function findHostInstance(fiber) {
11818 var hostFiber = findCurrentHostFiber(fiber);
11819 if (hostFiber === null) {
11820 return null;
11821 }
11822 return hostFiber.stateNode;
11823 }
11824
11825 return {
11826 createContainer: function (containerInfo, isAsync, hydrate) {
11827 return createFiberRoot(containerInfo, isAsync, hydrate);
11828 },
11829 updateContainer: function (element, container, parentComponent, callback) {
11830 var current = container.current;
11831 var expirationTime = computeExpirationForFiber(current);
11832 return updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback);
11833 },
11834
11835
11836 updateContainerAtExpirationTime: updateContainerAtExpirationTime,
11837
11838 flushRoot: flushRoot,
11839
11840 requestWork: requestWork,
11841
11842 computeUniqueAsyncExpiration: computeUniqueAsyncExpiration,
11843
11844 batchedUpdates: batchedUpdates,
11845
11846 unbatchedUpdates: unbatchedUpdates,
11847
11848 deferredUpdates: deferredUpdates,
11849
11850 flushSync: flushSync,
11851
11852 getPublicRootInstance: function (container) {
11853 var containerFiber = container.current;
11854 if (!containerFiber.child) {
11855 return null;
11856 }
11857 switch (containerFiber.child.tag) {
11858 case HostComponent:
11859 return getPublicInstance(containerFiber.child.stateNode);
11860 default:
11861 return containerFiber.child.stateNode;
11862 }
11863 },
11864
11865
11866 findHostInstance: findHostInstance,
11867
11868 findHostInstanceWithNoPortals: function (fiber) {
11869 var hostFiber = findCurrentHostFiberWithNoPortals(fiber);
11870 if (hostFiber === null) {
11871 return null;
11872 }
11873 return hostFiber.stateNode;
11874 },
11875 injectIntoDevTools: function (devToolsConfig) {
11876 var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance;
11877
11878 return injectInternals(_assign({}, devToolsConfig, {
11879 findHostInstanceByFiber: function (fiber) {
11880 return findHostInstance(fiber);
11881 },
11882 findFiberByHostInstance: function (instance) {
11883 if (!findFiberByHostInstance) {
11884 // Might not be implemented by the renderer.
11885 return null;
11886 }
11887 return findFiberByHostInstance(instance);
11888 }
11889 }));
11890 }
11891 };
11892};
11893
11894var ReactFiberReconciler$2 = Object.freeze({
11895 default: ReactFiberReconciler$1
11896});
11897
11898var ReactFiberReconciler$3 = ( ReactFiberReconciler$2 && ReactFiberReconciler$1 ) || ReactFiberReconciler$2;
11899
11900// TODO: bundle Flow types with the package.
11901
11902
11903
11904// TODO: decide on the top-level export form.
11905// This is hacky but makes it work with both Rollup and Jest.
11906var reactReconciler = ReactFiberReconciler$3['default'] ? ReactFiberReconciler$3['default'] : ReactFiberReconciler$3;
11907
11908function createPortal$1(children, containerInfo,
11909// TODO: figure out the API for cross-renderer implementation.
11910implementation) {
11911 var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
11912
11913 return {
11914 // This tag allow us to uniquely identify this as a React Portal
11915 $$typeof: REACT_PORTAL_TYPE,
11916 key: key == null ? null : '' + key,
11917 children: children,
11918 containerInfo: containerInfo,
11919 implementation: implementation
11920 };
11921}
11922
11923// TODO: this is special because it gets imported during build.
11924
11925var ReactVersion = '16.2.0';
11926
11927// a requestAnimationFrame, storing the time for the start of the frame, then
11928// scheduling a postMessage which gets scheduled after paint. Within the
11929// postMessage handler do as much work as possible until time + frame rate.
11930// By separating the idle call into a separate event tick we ensure that
11931// layout, paint and other browser work is counted against the available time.
11932// The frame rate is dynamically adjusted.
11933
11934{
11935 if (ExecutionEnvironment_1.canUseDOM && typeof requestAnimationFrame !== 'function') {
11936 warning_1(false, 'React depends on requestAnimationFrame. Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills');
11937 }
11938}
11939
11940var hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function';
11941
11942var now = void 0;
11943if (hasNativePerformanceNow) {
11944 now = function () {
11945 return performance.now();
11946 };
11947} else {
11948 now = function () {
11949 return Date.now();
11950 };
11951}
11952
11953// TODO: There's no way to cancel, because Fiber doesn't atm.
11954var rIC = void 0;
11955var cIC = void 0;
11956
11957if (!ExecutionEnvironment_1.canUseDOM) {
11958 rIC = function (frameCallback) {
11959 return setTimeout(function () {
11960 frameCallback({
11961 timeRemaining: function () {
11962 return Infinity;
11963 }
11964 });
11965 });
11966 };
11967 cIC = function (timeoutID) {
11968 clearTimeout(timeoutID);
11969 };
11970} else if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') {
11971 // Polyfill requestIdleCallback and cancelIdleCallback
11972
11973 var scheduledRICCallback = null;
11974 var isIdleScheduled = false;
11975 var timeoutTime = -1;
11976
11977 var isAnimationFrameScheduled = false;
11978
11979 var frameDeadline = 0;
11980 // We start out assuming that we run at 30fps but then the heuristic tracking
11981 // will adjust this value to a faster fps if we get more frequent animation
11982 // frames.
11983 var previousFrameTime = 33;
11984 var activeFrameTime = 33;
11985
11986 var frameDeadlineObject = void 0;
11987 if (hasNativePerformanceNow) {
11988 frameDeadlineObject = {
11989 didTimeout: false,
11990 timeRemaining: function () {
11991 // We assume that if we have a performance timer that the rAF callback
11992 // gets a performance timer value. Not sure if this is always true.
11993 var remaining = frameDeadline - performance.now();
11994 return remaining > 0 ? remaining : 0;
11995 }
11996 };
11997 } else {
11998 frameDeadlineObject = {
11999 didTimeout: false,
12000 timeRemaining: function () {
12001 // Fallback to Date.now()
12002 var remaining = frameDeadline - Date.now();
12003 return remaining > 0 ? remaining : 0;
12004 }
12005 };
12006 }
12007
12008 // We use the postMessage trick to defer idle work until after the repaint.
12009 var messageKey = '__reactIdleCallback$' + Math.random().toString(36).slice(2);
12010 var idleTick = function (event) {
12011 if (event.source !== window || event.data !== messageKey) {
12012 return;
12013 }
12014
12015 isIdleScheduled = false;
12016
12017 var currentTime = now();
12018 if (frameDeadline - currentTime <= 0) {
12019 // There's no time left in this idle period. Check if the callback has
12020 // a timeout and whether it's been exceeded.
12021 if (timeoutTime !== -1 && timeoutTime <= currentTime) {
12022 // Exceeded the timeout. Invoke the callback even though there's no
12023 // time left.
12024 frameDeadlineObject.didTimeout = true;
12025 } else {
12026 // No timeout.
12027 if (!isAnimationFrameScheduled) {
12028 // Schedule another animation callback so we retry later.
12029 isAnimationFrameScheduled = true;
12030 requestAnimationFrame(animationTick);
12031 }
12032 // Exit without invoking the callback.
12033 return;
12034 }
12035 } else {
12036 // There's still time left in this idle period.
12037 frameDeadlineObject.didTimeout = false;
12038 }
12039
12040 timeoutTime = -1;
12041 var callback = scheduledRICCallback;
12042 scheduledRICCallback = null;
12043 if (callback !== null) {
12044 callback(frameDeadlineObject);
12045 }
12046 };
12047 // Assumes that we have addEventListener in this environment. Might need
12048 // something better for old IE.
12049 window.addEventListener('message', idleTick, false);
12050
12051 var animationTick = function (rafTime) {
12052 isAnimationFrameScheduled = false;
12053 var nextFrameTime = rafTime - frameDeadline + activeFrameTime;
12054 if (nextFrameTime < activeFrameTime && previousFrameTime < activeFrameTime) {
12055 if (nextFrameTime < 8) {
12056 // Defensive coding. We don't support higher frame rates than 120hz.
12057 // If we get lower than that, it is probably a bug.
12058 nextFrameTime = 8;
12059 }
12060 // If one frame goes long, then the next one can be short to catch up.
12061 // If two frames are short in a row, then that's an indication that we
12062 // actually have a higher frame rate than what we're currently optimizing.
12063 // We adjust our heuristic dynamically accordingly. For example, if we're
12064 // running on 120hz display or 90hz VR display.
12065 // Take the max of the two in case one of them was an anomaly due to
12066 // missed frame deadlines.
12067 activeFrameTime = nextFrameTime < previousFrameTime ? previousFrameTime : nextFrameTime;
12068 } else {
12069 previousFrameTime = nextFrameTime;
12070 }
12071 frameDeadline = rafTime + activeFrameTime;
12072 if (!isIdleScheduled) {
12073 isIdleScheduled = true;
12074 window.postMessage(messageKey, '*');
12075 }
12076 };
12077
12078 rIC = function (callback, options) {
12079 // This assumes that we only schedule one callback at a time because that's
12080 // how Fiber uses it.
12081 scheduledRICCallback = callback;
12082 if (options != null && typeof options.timeout === 'number') {
12083 timeoutTime = now() + options.timeout;
12084 }
12085 if (!isAnimationFrameScheduled) {
12086 // If rAF didn't already schedule one, we need to schedule a frame.
12087 // TODO: If this rAF doesn't materialize because the browser throttles, we
12088 // might want to still have setTimeout trigger rIC as a backup to ensure
12089 // that we keep performing work.
12090 isAnimationFrameScheduled = true;
12091 requestAnimationFrame(animationTick);
12092 }
12093 return 0;
12094 };
12095
12096 cIC = function () {
12097 scheduledRICCallback = null;
12098 isIdleScheduled = false;
12099 timeoutTime = -1;
12100 };
12101} else {
12102 rIC = window.requestIdleCallback;
12103 cIC = window.cancelIdleCallback;
12104}
12105
12106var didWarnSelectedSetOnOption = false;
12107
12108function flattenChildren(children) {
12109 var content = '';
12110
12111 // Flatten children and warn if they aren't strings or numbers;
12112 // invalid types are ignored.
12113 // We can silently skip them because invalid DOM nesting warning
12114 // catches these cases in Fiber.
12115 React.Children.forEach(children, function (child) {
12116 if (child == null) {
12117 return;
12118 }
12119 if (typeof child === 'string' || typeof child === 'number') {
12120 content += child;
12121 }
12122 });
12123
12124 return content;
12125}
12126
12127/**
12128 * Implements an <option> host component that warns when `selected` is set.
12129 */
12130
12131function validateProps(element, props) {
12132 // TODO (yungsters): Remove support for `selected` in <option>.
12133 {
12134 if (props.selected != null && !didWarnSelectedSetOnOption) {
12135 warning_1(false, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.');
12136 didWarnSelectedSetOnOption = true;
12137 }
12138 }
12139}
12140
12141function postMountWrapper$1(element, props) {
12142 // value="" should make a value attribute (#6219)
12143 if (props.value != null) {
12144 element.setAttribute('value', props.value);
12145 }
12146}
12147
12148function getHostProps$1(element, props) {
12149 var hostProps = _assign({ children: undefined }, props);
12150 var content = flattenChildren(props.children);
12151
12152 if (content) {
12153 hostProps.children = content;
12154 }
12155
12156 return hostProps;
12157}
12158
12159// TODO: direct imports like some-package/src/* are bad. Fix me.
12160var getCurrentFiberOwnerName$3 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
12161var getCurrentFiberStackAddendum$4 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
12162
12163
12164var didWarnValueDefaultValue$1 = void 0;
12165
12166{
12167 didWarnValueDefaultValue$1 = false;
12168}
12169
12170function getDeclarationErrorAddendum() {
12171 var ownerName = getCurrentFiberOwnerName$3();
12172 if (ownerName) {
12173 return '\n\nCheck the render method of `' + ownerName + '`.';
12174 }
12175 return '';
12176}
12177
12178var valuePropNames = ['value', 'defaultValue'];
12179
12180/**
12181 * Validation function for `value` and `defaultValue`.
12182 */
12183function checkSelectPropTypes(props) {
12184 ReactControlledValuePropTypes.checkPropTypes('select', props, getCurrentFiberStackAddendum$4);
12185
12186 for (var i = 0; i < valuePropNames.length; i++) {
12187 var propName = valuePropNames[i];
12188 if (props[propName] == null) {
12189 continue;
12190 }
12191 var isArray = Array.isArray(props[propName]);
12192 if (props.multiple && !isArray) {
12193 warning_1(false, 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum());
12194 } else if (!props.multiple && isArray) {
12195 warning_1(false, 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum());
12196 }
12197 }
12198}
12199
12200function updateOptions(node, multiple, propValue, setDefaultSelected) {
12201 var options = node.options;
12202
12203 if (multiple) {
12204 var selectedValues = propValue;
12205 var selectedValue = {};
12206 for (var i = 0; i < selectedValues.length; i++) {
12207 // Prefix to avoid chaos with special keys.
12208 selectedValue['$' + selectedValues[i]] = true;
12209 }
12210 for (var _i = 0; _i < options.length; _i++) {
12211 var selected = selectedValue.hasOwnProperty('$' + options[_i].value);
12212 if (options[_i].selected !== selected) {
12213 options[_i].selected = selected;
12214 }
12215 if (selected && setDefaultSelected) {
12216 options[_i].defaultSelected = true;
12217 }
12218 }
12219 } else {
12220 // Do not set `select.value` as exact behavior isn't consistent across all
12221 // browsers for all cases.
12222 var _selectedValue = '' + propValue;
12223 var defaultSelected = null;
12224 for (var _i2 = 0; _i2 < options.length; _i2++) {
12225 if (options[_i2].value === _selectedValue) {
12226 options[_i2].selected = true;
12227 if (setDefaultSelected) {
12228 options[_i2].defaultSelected = true;
12229 }
12230 return;
12231 }
12232 if (defaultSelected === null && !options[_i2].disabled) {
12233 defaultSelected = options[_i2];
12234 }
12235 }
12236 if (defaultSelected !== null) {
12237 defaultSelected.selected = true;
12238 }
12239 }
12240}
12241
12242/**
12243 * Implements a <select> host component that allows optionally setting the
12244 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
12245 * stringable. If `multiple` is true, the prop must be an array of stringables.
12246 *
12247 * If `value` is not supplied (or null/undefined), user actions that change the
12248 * selected option will trigger updates to the rendered options.
12249 *
12250 * If it is supplied (and not null/undefined), the rendered options will not
12251 * update in response to user actions. Instead, the `value` prop must change in
12252 * order for the rendered options to update.
12253 *
12254 * If `defaultValue` is provided, any options with the supplied values will be
12255 * selected.
12256 */
12257
12258function getHostProps$2(element, props) {
12259 return _assign({}, props, {
12260 value: undefined
12261 });
12262}
12263
12264function initWrapperState$1(element, props) {
12265 var node = element;
12266 {
12267 checkSelectPropTypes(props);
12268 }
12269
12270 var value = props.value;
12271 node._wrapperState = {
12272 initialValue: value != null ? value : props.defaultValue,
12273 wasMultiple: !!props.multiple
12274 };
12275
12276 {
12277 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) {
12278 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');
12279 didWarnValueDefaultValue$1 = true;
12280 }
12281 }
12282}
12283
12284function postMountWrapper$2(element, props) {
12285 var node = element;
12286 node.multiple = !!props.multiple;
12287 var value = props.value;
12288 if (value != null) {
12289 updateOptions(node, !!props.multiple, value, false);
12290 } else if (props.defaultValue != null) {
12291 updateOptions(node, !!props.multiple, props.defaultValue, true);
12292 }
12293}
12294
12295function postUpdateWrapper(element, props) {
12296 var node = element;
12297 // After the initial mount, we control selected-ness manually so don't pass
12298 // this value down
12299 node._wrapperState.initialValue = undefined;
12300
12301 var wasMultiple = node._wrapperState.wasMultiple;
12302 node._wrapperState.wasMultiple = !!props.multiple;
12303
12304 var value = props.value;
12305 if (value != null) {
12306 updateOptions(node, !!props.multiple, value, false);
12307 } else if (wasMultiple !== !!props.multiple) {
12308 // For simplicity, reapply `defaultValue` if `multiple` is toggled.
12309 if (props.defaultValue != null) {
12310 updateOptions(node, !!props.multiple, props.defaultValue, true);
12311 } else {
12312 // Revert the select back to its default unselected state.
12313 updateOptions(node, !!props.multiple, props.multiple ? [] : '', false);
12314 }
12315 }
12316}
12317
12318function restoreControlledState$2(element, props) {
12319 var node = element;
12320 var value = props.value;
12321
12322 if (value != null) {
12323 updateOptions(node, !!props.multiple, value, false);
12324 }
12325}
12326
12327// TODO: direct imports like some-package/src/* are bad. Fix me.
12328var getCurrentFiberStackAddendum$5 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
12329
12330var didWarnValDefaultVal = false;
12331
12332/**
12333 * Implements a <textarea> host component that allows setting `value`, and
12334 * `defaultValue`. This differs from the traditional DOM API because value is
12335 * usually set as PCDATA children.
12336 *
12337 * If `value` is not supplied (or null/undefined), user actions that affect the
12338 * value will trigger updates to the element.
12339 *
12340 * If `value` is supplied (and not null/undefined), the rendered element will
12341 * not trigger updates to the element. Instead, the `value` prop must change in
12342 * order for the rendered element to be updated.
12343 *
12344 * The rendered element will be initialized with an empty value, the prop
12345 * `defaultValue` if specified, or the children content (deprecated).
12346 */
12347
12348function getHostProps$3(element, props) {
12349 var node = element;
12350 !(props.dangerouslySetInnerHTML == null) ? invariant_1(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : void 0;
12351
12352 // Always set children to the same thing. In IE9, the selection range will
12353 // get reset if `textContent` is mutated. We could add a check in setTextContent
12354 // to only set the value if/when the value differs from the node value (which would
12355 // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this
12356 // solution. The value can be a boolean or object so that's why it's forced
12357 // to be a string.
12358 var hostProps = _assign({}, props, {
12359 value: undefined,
12360 defaultValue: undefined,
12361 children: '' + node._wrapperState.initialValue
12362 });
12363
12364 return hostProps;
12365}
12366
12367function initWrapperState$2(element, props) {
12368 var node = element;
12369 {
12370 ReactControlledValuePropTypes.checkPropTypes('textarea', props, getCurrentFiberStackAddendum$5);
12371 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
12372 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');
12373 didWarnValDefaultVal = true;
12374 }
12375 }
12376
12377 var initialValue = props.value;
12378
12379 // Only bother fetching default value if we're going to use it
12380 if (initialValue == null) {
12381 var defaultValue = props.defaultValue;
12382 // TODO (yungsters): Remove support for children content in <textarea>.
12383 var children = props.children;
12384 if (children != null) {
12385 {
12386 warning_1(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.');
12387 }
12388 !(defaultValue == null) ? invariant_1(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : void 0;
12389 if (Array.isArray(children)) {
12390 !(children.length <= 1) ? invariant_1(false, '<textarea> can only have at most one child.') : void 0;
12391 children = children[0];
12392 }
12393
12394 defaultValue = '' + children;
12395 }
12396 if (defaultValue == null) {
12397 defaultValue = '';
12398 }
12399 initialValue = defaultValue;
12400 }
12401
12402 node._wrapperState = {
12403 initialValue: '' + initialValue
12404 };
12405}
12406
12407function updateWrapper$1(element, props) {
12408 var node = element;
12409 var value = props.value;
12410 if (value != null) {
12411 // Cast `value` to a string to ensure the value is set correctly. While
12412 // browsers typically do this as necessary, jsdom doesn't.
12413 var newValue = '' + value;
12414
12415 // To avoid side effects (such as losing text selection), only set value if changed
12416 if (newValue !== node.value) {
12417 node.value = newValue;
12418 }
12419 if (props.defaultValue == null) {
12420 node.defaultValue = newValue;
12421 }
12422 }
12423 if (props.defaultValue != null) {
12424 node.defaultValue = props.defaultValue;
12425 }
12426}
12427
12428function postMountWrapper$3(element, props) {
12429 var node = element;
12430 // This is in postMount because we need access to the DOM node, which is not
12431 // available until after the component has mounted.
12432 var textContent = node.textContent;
12433
12434 // Only set node.value if textContent is equal to the expected
12435 // initial value. In IE10/IE11 there is a bug where the placeholder attribute
12436 // will populate textContent as well.
12437 // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
12438 if (textContent === node._wrapperState.initialValue) {
12439 node.value = textContent;
12440 }
12441}
12442
12443function restoreControlledState$3(element, props) {
12444 // DOM component is still mounted; update
12445 updateWrapper$1(element, props);
12446}
12447
12448var HTML_NAMESPACE$1 = 'http://www.w3.org/1999/xhtml';
12449var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
12450var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
12451
12452var Namespaces = {
12453 html: HTML_NAMESPACE$1,
12454 mathml: MATH_NAMESPACE,
12455 svg: SVG_NAMESPACE
12456};
12457
12458// Assumes there is no parent namespace.
12459function getIntrinsicNamespace(type) {
12460 switch (type) {
12461 case 'svg':
12462 return SVG_NAMESPACE;
12463 case 'math':
12464 return MATH_NAMESPACE;
12465 default:
12466 return HTML_NAMESPACE$1;
12467 }
12468}
12469
12470function getChildNamespace(parentNamespace, type) {
12471 if (parentNamespace == null || parentNamespace === HTML_NAMESPACE$1) {
12472 // No (or default) parent namespace: potential entry point.
12473 return getIntrinsicNamespace(type);
12474 }
12475 if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') {
12476 // We're leaving SVG.
12477 return HTML_NAMESPACE$1;
12478 }
12479 // By default, pass namespace below.
12480 return parentNamespace;
12481}
12482
12483/* globals MSApp */
12484
12485/**
12486 * Create a function which has 'unsafe' privileges (required by windows8 apps)
12487 */
12488var createMicrosoftUnsafeLocalFunction = function (func) {
12489 if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
12490 return function (arg0, arg1, arg2, arg3) {
12491 MSApp.execUnsafeLocalFunction(function () {
12492 return func(arg0, arg1, arg2, arg3);
12493 });
12494 };
12495 } else {
12496 return func;
12497 }
12498};
12499
12500// SVG temp container for IE lacking innerHTML
12501var reusableSVGContainer = void 0;
12502
12503/**
12504 * Set the innerHTML property of a node
12505 *
12506 * @param {DOMElement} node
12507 * @param {string} html
12508 * @internal
12509 */
12510var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
12511 // IE does not have innerHTML for SVG nodes, so instead we inject the
12512 // new markup in a temp node and then move the child nodes across into
12513 // the target node
12514
12515 if (node.namespaceURI === Namespaces.svg && !('innerHTML' in node)) {
12516 reusableSVGContainer = reusableSVGContainer || document.createElement('div');
12517 reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
12518 var svgNode = reusableSVGContainer.firstChild;
12519 while (node.firstChild) {
12520 node.removeChild(node.firstChild);
12521 }
12522 while (svgNode.firstChild) {
12523 node.appendChild(svgNode.firstChild);
12524 }
12525 } else {
12526 node.innerHTML = html;
12527 }
12528});
12529
12530/**
12531 * Set the textContent property of a node. For text updates, it's faster
12532 * to set the `nodeValue` of the Text node directly instead of using
12533 * `.textContent` which will remove the existing node and create a new one.
12534 *
12535 * @param {DOMElement} node
12536 * @param {string} text
12537 * @internal
12538 */
12539var setTextContent = function (node, text) {
12540 if (text) {
12541 var firstChild = node.firstChild;
12542
12543 if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) {
12544 firstChild.nodeValue = text;
12545 return;
12546 }
12547 }
12548 node.textContent = text;
12549};
12550
12551/**
12552 * CSS properties which accept numbers but are not in units of "px".
12553 */
12554var isUnitlessNumber = {
12555 animationIterationCount: true,
12556 borderImageOutset: true,
12557 borderImageSlice: true,
12558 borderImageWidth: true,
12559 boxFlex: true,
12560 boxFlexGroup: true,
12561 boxOrdinalGroup: true,
12562 columnCount: true,
12563 columns: true,
12564 flex: true,
12565 flexGrow: true,
12566 flexPositive: true,
12567 flexShrink: true,
12568 flexNegative: true,
12569 flexOrder: true,
12570 gridRow: true,
12571 gridRowEnd: true,
12572 gridRowSpan: true,
12573 gridRowStart: true,
12574 gridColumn: true,
12575 gridColumnEnd: true,
12576 gridColumnSpan: true,
12577 gridColumnStart: true,
12578 fontWeight: true,
12579 lineClamp: true,
12580 lineHeight: true,
12581 opacity: true,
12582 order: true,
12583 orphans: true,
12584 tabSize: true,
12585 widows: true,
12586 zIndex: true,
12587 zoom: true,
12588
12589 // SVG-related properties
12590 fillOpacity: true,
12591 floodOpacity: true,
12592 stopOpacity: true,
12593 strokeDasharray: true,
12594 strokeDashoffset: true,
12595 strokeMiterlimit: true,
12596 strokeOpacity: true,
12597 strokeWidth: true
12598};
12599
12600/**
12601 * @param {string} prefix vendor-specific prefix, eg: Webkit
12602 * @param {string} key style name, eg: transitionDuration
12603 * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
12604 * WebkitTransitionDuration
12605 */
12606function prefixKey(prefix, key) {
12607 return prefix + key.charAt(0).toUpperCase() + key.substring(1);
12608}
12609
12610/**
12611 * Support style names that may come passed in prefixed by adding permutations
12612 * of vendor prefixes.
12613 */
12614var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
12615
12616// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
12617// infinite loop, because it iterates over the newly added props too.
12618Object.keys(isUnitlessNumber).forEach(function (prop) {
12619 prefixes.forEach(function (prefix) {
12620 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
12621 });
12622});
12623
12624/**
12625 * Convert a value into the proper css writable value. The style name `name`
12626 * should be logical (no hyphens), as specified
12627 * in `CSSProperty.isUnitlessNumber`.
12628 *
12629 * @param {string} name CSS property name such as `topMargin`.
12630 * @param {*} value CSS property value such as `10px`.
12631 * @return {string} Normalized style value with dimensions applied.
12632 */
12633function dangerousStyleValue(name, value, isCustomProperty) {
12634 // Note that we've removed escapeTextForBrowser() calls here since the
12635 // whole string will be escaped when the attribute is injected into
12636 // the markup. If you provide unsafe user data here they can inject
12637 // arbitrary CSS which may be problematic (I couldn't repro this):
12638 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
12639 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
12640 // This is not an XSS hole but instead a potential CSS injection issue
12641 // which has lead to a greater discussion about how we're going to
12642 // trust URLs moving forward. See #2115901
12643
12644 var isEmpty = value == null || typeof value === 'boolean' || value === '';
12645 if (isEmpty) {
12646 return '';
12647 }
12648
12649 if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) {
12650 return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
12651 }
12652
12653 return ('' + value).trim();
12654}
12655
12656/**
12657 * Copyright (c) 2013-present, Facebook, Inc.
12658 *
12659 * This source code is licensed under the MIT license found in the
12660 * LICENSE file in the root directory of this source tree.
12661 *
12662 * @typechecks
12663 */
12664
12665var _uppercasePattern = /([A-Z])/g;
12666
12667/**
12668 * Hyphenates a camelcased string, for example:
12669 *
12670 * > hyphenate('backgroundColor')
12671 * < "background-color"
12672 *
12673 * For CSS style names, use `hyphenateStyleName` instead which works properly
12674 * with all vendor prefixes, including `ms`.
12675 *
12676 * @param {string} string
12677 * @return {string}
12678 */
12679function hyphenate(string) {
12680 return string.replace(_uppercasePattern, '-$1').toLowerCase();
12681}
12682
12683var hyphenate_1 = hyphenate;
12684
12685/**
12686 * Copyright (c) 2013-present, Facebook, Inc.
12687 *
12688 * This source code is licensed under the MIT license found in the
12689 * LICENSE file in the root directory of this source tree.
12690 *
12691 * @typechecks
12692 */
12693
12694
12695
12696
12697
12698var msPattern = /^ms-/;
12699
12700/**
12701 * Hyphenates a camelcased CSS property name, for example:
12702 *
12703 * > hyphenateStyleName('backgroundColor')
12704 * < "background-color"
12705 * > hyphenateStyleName('MozTransition')
12706 * < "-moz-transition"
12707 * > hyphenateStyleName('msTransition')
12708 * < "-ms-transition"
12709 *
12710 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
12711 * is converted to `-ms-`.
12712 *
12713 * @param {string} string
12714 * @return {string}
12715 */
12716function hyphenateStyleName(string) {
12717 return hyphenate_1(string).replace(msPattern, '-ms-');
12718}
12719
12720var hyphenateStyleName_1 = hyphenateStyleName;
12721
12722/**
12723 * Copyright (c) 2013-present, Facebook, Inc.
12724 *
12725 * This source code is licensed under the MIT license found in the
12726 * LICENSE file in the root directory of this source tree.
12727 *
12728 * @typechecks
12729 */
12730
12731var _hyphenPattern = /-(.)/g;
12732
12733/**
12734 * Camelcases a hyphenated string, for example:
12735 *
12736 * > camelize('background-color')
12737 * < "backgroundColor"
12738 *
12739 * @param {string} string
12740 * @return {string}
12741 */
12742function camelize(string) {
12743 return string.replace(_hyphenPattern, function (_, character) {
12744 return character.toUpperCase();
12745 });
12746}
12747
12748var camelize_1 = camelize;
12749
12750/**
12751 * Copyright (c) 2013-present, Facebook, Inc.
12752 *
12753 * This source code is licensed under the MIT license found in the
12754 * LICENSE file in the root directory of this source tree.
12755 *
12756 * @typechecks
12757 */
12758
12759
12760
12761
12762
12763var msPattern$1 = /^-ms-/;
12764
12765/**
12766 * Camelcases a hyphenated CSS property name, for example:
12767 *
12768 * > camelizeStyleName('background-color')
12769 * < "backgroundColor"
12770 * > camelizeStyleName('-moz-transition')
12771 * < "MozTransition"
12772 * > camelizeStyleName('-ms-transition')
12773 * < "msTransition"
12774 *
12775 * As Andi Smith suggests
12776 * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
12777 * is converted to lowercase `ms`.
12778 *
12779 * @param {string} string
12780 * @return {string}
12781 */
12782function camelizeStyleName(string) {
12783 return camelize_1(string.replace(msPattern$1, 'ms-'));
12784}
12785
12786var camelizeStyleName_1 = camelizeStyleName;
12787
12788var warnValidStyle = emptyFunction_1;
12789
12790{
12791 // 'msTransform' is correct, but the other prefixes should be capitalized
12792 var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
12793
12794 // style values shouldn't contain a semicolon
12795 var badStyleValueWithSemicolonPattern = /;\s*$/;
12796
12797 var warnedStyleNames = {};
12798 var warnedStyleValues = {};
12799 var warnedForNaNValue = false;
12800 var warnedForInfinityValue = false;
12801
12802 var warnHyphenatedStyleName = function (name, getStack) {
12803 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
12804 return;
12805 }
12806
12807 warnedStyleNames[name] = true;
12808 warning_1(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName_1(name), getStack());
12809 };
12810
12811 var warnBadVendoredStyleName = function (name, getStack) {
12812 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
12813 return;
12814 }
12815
12816 warnedStyleNames[name] = true;
12817 warning_1(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), getStack());
12818 };
12819
12820 var warnStyleValueWithSemicolon = function (name, value, getStack) {
12821 if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
12822 return;
12823 }
12824
12825 warnedStyleValues[value] = true;
12826 warning_1(false, "Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.%s', name, value.replace(badStyleValueWithSemicolonPattern, ''), getStack());
12827 };
12828
12829 var warnStyleValueIsNaN = function (name, value, getStack) {
12830 if (warnedForNaNValue) {
12831 return;
12832 }
12833
12834 warnedForNaNValue = true;
12835 warning_1(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, getStack());
12836 };
12837
12838 var warnStyleValueIsInfinity = function (name, value, getStack) {
12839 if (warnedForInfinityValue) {
12840 return;
12841 }
12842
12843 warnedForInfinityValue = true;
12844 warning_1(false, '`Infinity` is an invalid value for the `%s` css style property.%s', name, getStack());
12845 };
12846
12847 warnValidStyle = function (name, value, getStack) {
12848 if (name.indexOf('-') > -1) {
12849 warnHyphenatedStyleName(name, getStack);
12850 } else if (badVendoredStyleNamePattern.test(name)) {
12851 warnBadVendoredStyleName(name, getStack);
12852 } else if (badStyleValueWithSemicolonPattern.test(value)) {
12853 warnStyleValueWithSemicolon(name, value, getStack);
12854 }
12855
12856 if (typeof value === 'number') {
12857 if (isNaN(value)) {
12858 warnStyleValueIsNaN(name, value, getStack);
12859 } else if (!isFinite(value)) {
12860 warnStyleValueIsInfinity(name, value, getStack);
12861 }
12862 }
12863 };
12864}
12865
12866var warnValidStyle$1 = warnValidStyle;
12867
12868/**
12869 * Operations for dealing with CSS properties.
12870 */
12871
12872/**
12873 * This creates a string that is expected to be equivalent to the style
12874 * attribute generated by server-side rendering. It by-passes warnings and
12875 * security checks so it's not safe to use this value for anything other than
12876 * comparison. It is only used in DEV for SSR validation.
12877 */
12878function createDangerousStringForStyles(styles) {
12879 {
12880 var serialized = '';
12881 var delimiter = '';
12882 for (var styleName in styles) {
12883 if (!styles.hasOwnProperty(styleName)) {
12884 continue;
12885 }
12886 var styleValue = styles[styleName];
12887 if (styleValue != null) {
12888 var isCustomProperty = styleName.indexOf('--') === 0;
12889 serialized += delimiter + hyphenateStyleName_1(styleName) + ':';
12890 serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty);
12891
12892 delimiter = ';';
12893 }
12894 }
12895 return serialized || null;
12896 }
12897}
12898
12899/**
12900 * Sets the value for multiple styles on a node. If a value is specified as
12901 * '' (empty string), the corresponding style property will be unset.
12902 *
12903 * @param {DOMElement} node
12904 * @param {object} styles
12905 */
12906function setValueForStyles(node, styles, getStack) {
12907 var style = node.style;
12908 for (var styleName in styles) {
12909 if (!styles.hasOwnProperty(styleName)) {
12910 continue;
12911 }
12912 var isCustomProperty = styleName.indexOf('--') === 0;
12913 {
12914 if (!isCustomProperty) {
12915 warnValidStyle$1(styleName, styles[styleName], getStack);
12916 }
12917 }
12918 var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty);
12919 if (styleName === 'float') {
12920 styleName = 'cssFloat';
12921 }
12922 if (isCustomProperty) {
12923 style.setProperty(styleName, styleValue);
12924 } else {
12925 style[styleName] = styleValue;
12926 }
12927 }
12928}
12929
12930// For HTML, certain tags should omit their close tag. We keep a whitelist for
12931// those special-case tags.
12932
12933var omittedCloseTags = {
12934 area: true,
12935 base: true,
12936 br: true,
12937 col: true,
12938 embed: true,
12939 hr: true,
12940 img: true,
12941 input: true,
12942 keygen: true,
12943 link: true,
12944 meta: true,
12945 param: true,
12946 source: true,
12947 track: true,
12948 wbr: true
12949};
12950
12951// For HTML, certain tags cannot have children. This has the same purpose as
12952// `omittedCloseTags` except that `menuitem` should still have its closing tag.
12953
12954var voidElementTags = _assign({
12955 menuitem: true
12956}, omittedCloseTags);
12957
12958var HTML$1 = '__html';
12959
12960function assertValidProps(tag, props, getStack) {
12961 if (!props) {
12962 return;
12963 }
12964 // Note the use of `==` which checks for null or undefined.
12965 if (voidElementTags[tag]) {
12966 !(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;
12967 }
12968 if (props.dangerouslySetInnerHTML != null) {
12969 !(props.children == null) ? invariant_1(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : void 0;
12970 !(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;
12971 }
12972 {
12973 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());
12974 }
12975 !(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;
12976}
12977
12978function isCustomComponent(tagName, props) {
12979 if (tagName.indexOf('-') === -1) {
12980 return typeof props.is === 'string';
12981 }
12982 switch (tagName) {
12983 // These are reserved SVG and MathML elements.
12984 // We don't mind this whitelist too much because we expect it to never grow.
12985 // The alternative is to track the namespace in a few places which is convoluted.
12986 // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
12987 case 'annotation-xml':
12988 case 'color-profile':
12989 case 'font-face':
12990 case 'font-face-src':
12991 case 'font-face-uri':
12992 case 'font-face-format':
12993 case 'font-face-name':
12994 case 'missing-glyph':
12995 return false;
12996 default:
12997 return true;
12998 }
12999}
13000
13001// When adding attributes to the HTML or SVG whitelist, be sure to
13002// also add them to this module to ensure casing and incorrect name
13003// warnings.
13004var possibleStandardNames = {
13005 // HTML
13006 accept: 'accept',
13007 acceptcharset: 'acceptCharset',
13008 'accept-charset': 'acceptCharset',
13009 accesskey: 'accessKey',
13010 action: 'action',
13011 allowfullscreen: 'allowFullScreen',
13012 alt: 'alt',
13013 as: 'as',
13014 async: 'async',
13015 autocapitalize: 'autoCapitalize',
13016 autocomplete: 'autoComplete',
13017 autocorrect: 'autoCorrect',
13018 autofocus: 'autoFocus',
13019 autoplay: 'autoPlay',
13020 autosave: 'autoSave',
13021 capture: 'capture',
13022 cellpadding: 'cellPadding',
13023 cellspacing: 'cellSpacing',
13024 challenge: 'challenge',
13025 charset: 'charSet',
13026 checked: 'checked',
13027 children: 'children',
13028 cite: 'cite',
13029 'class': 'className',
13030 classid: 'classID',
13031 classname: 'className',
13032 cols: 'cols',
13033 colspan: 'colSpan',
13034 content: 'content',
13035 contenteditable: 'contentEditable',
13036 contextmenu: 'contextMenu',
13037 controls: 'controls',
13038 controlslist: 'controlsList',
13039 coords: 'coords',
13040 crossorigin: 'crossOrigin',
13041 dangerouslysetinnerhtml: 'dangerouslySetInnerHTML',
13042 data: 'data',
13043 datetime: 'dateTime',
13044 'default': 'default',
13045 defaultchecked: 'defaultChecked',
13046 defaultvalue: 'defaultValue',
13047 defer: 'defer',
13048 dir: 'dir',
13049 disabled: 'disabled',
13050 download: 'download',
13051 draggable: 'draggable',
13052 enctype: 'encType',
13053 'for': 'htmlFor',
13054 form: 'form',
13055 formmethod: 'formMethod',
13056 formaction: 'formAction',
13057 formenctype: 'formEncType',
13058 formnovalidate: 'formNoValidate',
13059 formtarget: 'formTarget',
13060 frameborder: 'frameBorder',
13061 headers: 'headers',
13062 height: 'height',
13063 hidden: 'hidden',
13064 high: 'high',
13065 href: 'href',
13066 hreflang: 'hrefLang',
13067 htmlfor: 'htmlFor',
13068 httpequiv: 'httpEquiv',
13069 'http-equiv': 'httpEquiv',
13070 icon: 'icon',
13071 id: 'id',
13072 innerhtml: 'innerHTML',
13073 inputmode: 'inputMode',
13074 integrity: 'integrity',
13075 is: 'is',
13076 itemid: 'itemID',
13077 itemprop: 'itemProp',
13078 itemref: 'itemRef',
13079 itemscope: 'itemScope',
13080 itemtype: 'itemType',
13081 keyparams: 'keyParams',
13082 keytype: 'keyType',
13083 kind: 'kind',
13084 label: 'label',
13085 lang: 'lang',
13086 list: 'list',
13087 loop: 'loop',
13088 low: 'low',
13089 manifest: 'manifest',
13090 marginwidth: 'marginWidth',
13091 marginheight: 'marginHeight',
13092 max: 'max',
13093 maxlength: 'maxLength',
13094 media: 'media',
13095 mediagroup: 'mediaGroup',
13096 method: 'method',
13097 min: 'min',
13098 minlength: 'minLength',
13099 multiple: 'multiple',
13100 muted: 'muted',
13101 name: 'name',
13102 nomodule: 'noModule',
13103 nonce: 'nonce',
13104 novalidate: 'noValidate',
13105 open: 'open',
13106 optimum: 'optimum',
13107 pattern: 'pattern',
13108 placeholder: 'placeholder',
13109 playsinline: 'playsInline',
13110 poster: 'poster',
13111 preload: 'preload',
13112 profile: 'profile',
13113 radiogroup: 'radioGroup',
13114 readonly: 'readOnly',
13115 referrerpolicy: 'referrerPolicy',
13116 rel: 'rel',
13117 required: 'required',
13118 reversed: 'reversed',
13119 role: 'role',
13120 rows: 'rows',
13121 rowspan: 'rowSpan',
13122 sandbox: 'sandbox',
13123 scope: 'scope',
13124 scoped: 'scoped',
13125 scrolling: 'scrolling',
13126 seamless: 'seamless',
13127 selected: 'selected',
13128 shape: 'shape',
13129 size: 'size',
13130 sizes: 'sizes',
13131 span: 'span',
13132 spellcheck: 'spellCheck',
13133 src: 'src',
13134 srcdoc: 'srcDoc',
13135 srclang: 'srcLang',
13136 srcset: 'srcSet',
13137 start: 'start',
13138 step: 'step',
13139 style: 'style',
13140 summary: 'summary',
13141 tabindex: 'tabIndex',
13142 target: 'target',
13143 title: 'title',
13144 type: 'type',
13145 usemap: 'useMap',
13146 value: 'value',
13147 width: 'width',
13148 wmode: 'wmode',
13149 wrap: 'wrap',
13150
13151 // SVG
13152 about: 'about',
13153 accentheight: 'accentHeight',
13154 'accent-height': 'accentHeight',
13155 accumulate: 'accumulate',
13156 additive: 'additive',
13157 alignmentbaseline: 'alignmentBaseline',
13158 'alignment-baseline': 'alignmentBaseline',
13159 allowreorder: 'allowReorder',
13160 alphabetic: 'alphabetic',
13161 amplitude: 'amplitude',
13162 arabicform: 'arabicForm',
13163 'arabic-form': 'arabicForm',
13164 ascent: 'ascent',
13165 attributename: 'attributeName',
13166 attributetype: 'attributeType',
13167 autoreverse: 'autoReverse',
13168 azimuth: 'azimuth',
13169 basefrequency: 'baseFrequency',
13170 baselineshift: 'baselineShift',
13171 'baseline-shift': 'baselineShift',
13172 baseprofile: 'baseProfile',
13173 bbox: 'bbox',
13174 begin: 'begin',
13175 bias: 'bias',
13176 by: 'by',
13177 calcmode: 'calcMode',
13178 capheight: 'capHeight',
13179 'cap-height': 'capHeight',
13180 clip: 'clip',
13181 clippath: 'clipPath',
13182 'clip-path': 'clipPath',
13183 clippathunits: 'clipPathUnits',
13184 cliprule: 'clipRule',
13185 'clip-rule': 'clipRule',
13186 color: 'color',
13187 colorinterpolation: 'colorInterpolation',
13188 'color-interpolation': 'colorInterpolation',
13189 colorinterpolationfilters: 'colorInterpolationFilters',
13190 'color-interpolation-filters': 'colorInterpolationFilters',
13191 colorprofile: 'colorProfile',
13192 'color-profile': 'colorProfile',
13193 colorrendering: 'colorRendering',
13194 'color-rendering': 'colorRendering',
13195 contentscripttype: 'contentScriptType',
13196 contentstyletype: 'contentStyleType',
13197 cursor: 'cursor',
13198 cx: 'cx',
13199 cy: 'cy',
13200 d: 'd',
13201 datatype: 'datatype',
13202 decelerate: 'decelerate',
13203 descent: 'descent',
13204 diffuseconstant: 'diffuseConstant',
13205 direction: 'direction',
13206 display: 'display',
13207 divisor: 'divisor',
13208 dominantbaseline: 'dominantBaseline',
13209 'dominant-baseline': 'dominantBaseline',
13210 dur: 'dur',
13211 dx: 'dx',
13212 dy: 'dy',
13213 edgemode: 'edgeMode',
13214 elevation: 'elevation',
13215 enablebackground: 'enableBackground',
13216 'enable-background': 'enableBackground',
13217 end: 'end',
13218 exponent: 'exponent',
13219 externalresourcesrequired: 'externalResourcesRequired',
13220 fill: 'fill',
13221 fillopacity: 'fillOpacity',
13222 'fill-opacity': 'fillOpacity',
13223 fillrule: 'fillRule',
13224 'fill-rule': 'fillRule',
13225 filter: 'filter',
13226 filterres: 'filterRes',
13227 filterunits: 'filterUnits',
13228 floodopacity: 'floodOpacity',
13229 'flood-opacity': 'floodOpacity',
13230 floodcolor: 'floodColor',
13231 'flood-color': 'floodColor',
13232 focusable: 'focusable',
13233 fontfamily: 'fontFamily',
13234 'font-family': 'fontFamily',
13235 fontsize: 'fontSize',
13236 'font-size': 'fontSize',
13237 fontsizeadjust: 'fontSizeAdjust',
13238 'font-size-adjust': 'fontSizeAdjust',
13239 fontstretch: 'fontStretch',
13240 'font-stretch': 'fontStretch',
13241 fontstyle: 'fontStyle',
13242 'font-style': 'fontStyle',
13243 fontvariant: 'fontVariant',
13244 'font-variant': 'fontVariant',
13245 fontweight: 'fontWeight',
13246 'font-weight': 'fontWeight',
13247 format: 'format',
13248 from: 'from',
13249 fx: 'fx',
13250 fy: 'fy',
13251 g1: 'g1',
13252 g2: 'g2',
13253 glyphname: 'glyphName',
13254 'glyph-name': 'glyphName',
13255 glyphorientationhorizontal: 'glyphOrientationHorizontal',
13256 'glyph-orientation-horizontal': 'glyphOrientationHorizontal',
13257 glyphorientationvertical: 'glyphOrientationVertical',
13258 'glyph-orientation-vertical': 'glyphOrientationVertical',
13259 glyphref: 'glyphRef',
13260 gradienttransform: 'gradientTransform',
13261 gradientunits: 'gradientUnits',
13262 hanging: 'hanging',
13263 horizadvx: 'horizAdvX',
13264 'horiz-adv-x': 'horizAdvX',
13265 horizoriginx: 'horizOriginX',
13266 'horiz-origin-x': 'horizOriginX',
13267 ideographic: 'ideographic',
13268 imagerendering: 'imageRendering',
13269 'image-rendering': 'imageRendering',
13270 in2: 'in2',
13271 'in': 'in',
13272 inlist: 'inlist',
13273 intercept: 'intercept',
13274 k1: 'k1',
13275 k2: 'k2',
13276 k3: 'k3',
13277 k4: 'k4',
13278 k: 'k',
13279 kernelmatrix: 'kernelMatrix',
13280 kernelunitlength: 'kernelUnitLength',
13281 kerning: 'kerning',
13282 keypoints: 'keyPoints',
13283 keysplines: 'keySplines',
13284 keytimes: 'keyTimes',
13285 lengthadjust: 'lengthAdjust',
13286 letterspacing: 'letterSpacing',
13287 'letter-spacing': 'letterSpacing',
13288 lightingcolor: 'lightingColor',
13289 'lighting-color': 'lightingColor',
13290 limitingconeangle: 'limitingConeAngle',
13291 local: 'local',
13292 markerend: 'markerEnd',
13293 'marker-end': 'markerEnd',
13294 markerheight: 'markerHeight',
13295 markermid: 'markerMid',
13296 'marker-mid': 'markerMid',
13297 markerstart: 'markerStart',
13298 'marker-start': 'markerStart',
13299 markerunits: 'markerUnits',
13300 markerwidth: 'markerWidth',
13301 mask: 'mask',
13302 maskcontentunits: 'maskContentUnits',
13303 maskunits: 'maskUnits',
13304 mathematical: 'mathematical',
13305 mode: 'mode',
13306 numoctaves: 'numOctaves',
13307 offset: 'offset',
13308 opacity: 'opacity',
13309 operator: 'operator',
13310 order: 'order',
13311 orient: 'orient',
13312 orientation: 'orientation',
13313 origin: 'origin',
13314 overflow: 'overflow',
13315 overlineposition: 'overlinePosition',
13316 'overline-position': 'overlinePosition',
13317 overlinethickness: 'overlineThickness',
13318 'overline-thickness': 'overlineThickness',
13319 paintorder: 'paintOrder',
13320 'paint-order': 'paintOrder',
13321 panose1: 'panose1',
13322 'panose-1': 'panose1',
13323 pathlength: 'pathLength',
13324 patterncontentunits: 'patternContentUnits',
13325 patterntransform: 'patternTransform',
13326 patternunits: 'patternUnits',
13327 pointerevents: 'pointerEvents',
13328 'pointer-events': 'pointerEvents',
13329 points: 'points',
13330 pointsatx: 'pointsAtX',
13331 pointsaty: 'pointsAtY',
13332 pointsatz: 'pointsAtZ',
13333 prefix: 'prefix',
13334 preservealpha: 'preserveAlpha',
13335 preserveaspectratio: 'preserveAspectRatio',
13336 primitiveunits: 'primitiveUnits',
13337 property: 'property',
13338 r: 'r',
13339 radius: 'radius',
13340 refx: 'refX',
13341 refy: 'refY',
13342 renderingintent: 'renderingIntent',
13343 'rendering-intent': 'renderingIntent',
13344 repeatcount: 'repeatCount',
13345 repeatdur: 'repeatDur',
13346 requiredextensions: 'requiredExtensions',
13347 requiredfeatures: 'requiredFeatures',
13348 resource: 'resource',
13349 restart: 'restart',
13350 result: 'result',
13351 results: 'results',
13352 rotate: 'rotate',
13353 rx: 'rx',
13354 ry: 'ry',
13355 scale: 'scale',
13356 security: 'security',
13357 seed: 'seed',
13358 shaperendering: 'shapeRendering',
13359 'shape-rendering': 'shapeRendering',
13360 slope: 'slope',
13361 spacing: 'spacing',
13362 specularconstant: 'specularConstant',
13363 specularexponent: 'specularExponent',
13364 speed: 'speed',
13365 spreadmethod: 'spreadMethod',
13366 startoffset: 'startOffset',
13367 stddeviation: 'stdDeviation',
13368 stemh: 'stemh',
13369 stemv: 'stemv',
13370 stitchtiles: 'stitchTiles',
13371 stopcolor: 'stopColor',
13372 'stop-color': 'stopColor',
13373 stopopacity: 'stopOpacity',
13374 'stop-opacity': 'stopOpacity',
13375 strikethroughposition: 'strikethroughPosition',
13376 'strikethrough-position': 'strikethroughPosition',
13377 strikethroughthickness: 'strikethroughThickness',
13378 'strikethrough-thickness': 'strikethroughThickness',
13379 string: 'string',
13380 stroke: 'stroke',
13381 strokedasharray: 'strokeDasharray',
13382 'stroke-dasharray': 'strokeDasharray',
13383 strokedashoffset: 'strokeDashoffset',
13384 'stroke-dashoffset': 'strokeDashoffset',
13385 strokelinecap: 'strokeLinecap',
13386 'stroke-linecap': 'strokeLinecap',
13387 strokelinejoin: 'strokeLinejoin',
13388 'stroke-linejoin': 'strokeLinejoin',
13389 strokemiterlimit: 'strokeMiterlimit',
13390 'stroke-miterlimit': 'strokeMiterlimit',
13391 strokewidth: 'strokeWidth',
13392 'stroke-width': 'strokeWidth',
13393 strokeopacity: 'strokeOpacity',
13394 'stroke-opacity': 'strokeOpacity',
13395 suppresscontenteditablewarning: 'suppressContentEditableWarning',
13396 suppresshydrationwarning: 'suppressHydrationWarning',
13397 surfacescale: 'surfaceScale',
13398 systemlanguage: 'systemLanguage',
13399 tablevalues: 'tableValues',
13400 targetx: 'targetX',
13401 targety: 'targetY',
13402 textanchor: 'textAnchor',
13403 'text-anchor': 'textAnchor',
13404 textdecoration: 'textDecoration',
13405 'text-decoration': 'textDecoration',
13406 textlength: 'textLength',
13407 textrendering: 'textRendering',
13408 'text-rendering': 'textRendering',
13409 to: 'to',
13410 transform: 'transform',
13411 'typeof': 'typeof',
13412 u1: 'u1',
13413 u2: 'u2',
13414 underlineposition: 'underlinePosition',
13415 'underline-position': 'underlinePosition',
13416 underlinethickness: 'underlineThickness',
13417 'underline-thickness': 'underlineThickness',
13418 unicode: 'unicode',
13419 unicodebidi: 'unicodeBidi',
13420 'unicode-bidi': 'unicodeBidi',
13421 unicoderange: 'unicodeRange',
13422 'unicode-range': 'unicodeRange',
13423 unitsperem: 'unitsPerEm',
13424 'units-per-em': 'unitsPerEm',
13425 unselectable: 'unselectable',
13426 valphabetic: 'vAlphabetic',
13427 'v-alphabetic': 'vAlphabetic',
13428 values: 'values',
13429 vectoreffect: 'vectorEffect',
13430 'vector-effect': 'vectorEffect',
13431 version: 'version',
13432 vertadvy: 'vertAdvY',
13433 'vert-adv-y': 'vertAdvY',
13434 vertoriginx: 'vertOriginX',
13435 'vert-origin-x': 'vertOriginX',
13436 vertoriginy: 'vertOriginY',
13437 'vert-origin-y': 'vertOriginY',
13438 vhanging: 'vHanging',
13439 'v-hanging': 'vHanging',
13440 videographic: 'vIdeographic',
13441 'v-ideographic': 'vIdeographic',
13442 viewbox: 'viewBox',
13443 viewtarget: 'viewTarget',
13444 visibility: 'visibility',
13445 vmathematical: 'vMathematical',
13446 'v-mathematical': 'vMathematical',
13447 vocab: 'vocab',
13448 widths: 'widths',
13449 wordspacing: 'wordSpacing',
13450 'word-spacing': 'wordSpacing',
13451 writingmode: 'writingMode',
13452 'writing-mode': 'writingMode',
13453 x1: 'x1',
13454 x2: 'x2',
13455 x: 'x',
13456 xchannelselector: 'xChannelSelector',
13457 xheight: 'xHeight',
13458 'x-height': 'xHeight',
13459 xlinkactuate: 'xlinkActuate',
13460 'xlink:actuate': 'xlinkActuate',
13461 xlinkarcrole: 'xlinkArcrole',
13462 'xlink:arcrole': 'xlinkArcrole',
13463 xlinkhref: 'xlinkHref',
13464 'xlink:href': 'xlinkHref',
13465 xlinkrole: 'xlinkRole',
13466 'xlink:role': 'xlinkRole',
13467 xlinkshow: 'xlinkShow',
13468 'xlink:show': 'xlinkShow',
13469 xlinktitle: 'xlinkTitle',
13470 'xlink:title': 'xlinkTitle',
13471 xlinktype: 'xlinkType',
13472 'xlink:type': 'xlinkType',
13473 xmlbase: 'xmlBase',
13474 'xml:base': 'xmlBase',
13475 xmllang: 'xmlLang',
13476 'xml:lang': 'xmlLang',
13477 xmlns: 'xmlns',
13478 'xml:space': 'xmlSpace',
13479 xmlnsxlink: 'xmlnsXlink',
13480 'xmlns:xlink': 'xmlnsXlink',
13481 xmlspace: 'xmlSpace',
13482 y1: 'y1',
13483 y2: 'y2',
13484 y: 'y',
13485 ychannelselector: 'yChannelSelector',
13486 z: 'z',
13487 zoomandpan: 'zoomAndPan'
13488};
13489
13490var ariaProperties = {
13491 'aria-current': 0, // state
13492 'aria-details': 0,
13493 'aria-disabled': 0, // state
13494 'aria-hidden': 0, // state
13495 'aria-invalid': 0, // state
13496 'aria-keyshortcuts': 0,
13497 'aria-label': 0,
13498 'aria-roledescription': 0,
13499 // Widget Attributes
13500 'aria-autocomplete': 0,
13501 'aria-checked': 0,
13502 'aria-expanded': 0,
13503 'aria-haspopup': 0,
13504 'aria-level': 0,
13505 'aria-modal': 0,
13506 'aria-multiline': 0,
13507 'aria-multiselectable': 0,
13508 'aria-orientation': 0,
13509 'aria-placeholder': 0,
13510 'aria-pressed': 0,
13511 'aria-readonly': 0,
13512 'aria-required': 0,
13513 'aria-selected': 0,
13514 'aria-sort': 0,
13515 'aria-valuemax': 0,
13516 'aria-valuemin': 0,
13517 'aria-valuenow': 0,
13518 'aria-valuetext': 0,
13519 // Live Region Attributes
13520 'aria-atomic': 0,
13521 'aria-busy': 0,
13522 'aria-live': 0,
13523 'aria-relevant': 0,
13524 // Drag-and-Drop Attributes
13525 'aria-dropeffect': 0,
13526 'aria-grabbed': 0,
13527 // Relationship Attributes
13528 'aria-activedescendant': 0,
13529 'aria-colcount': 0,
13530 'aria-colindex': 0,
13531 'aria-colspan': 0,
13532 'aria-controls': 0,
13533 'aria-describedby': 0,
13534 'aria-errormessage': 0,
13535 'aria-flowto': 0,
13536 'aria-labelledby': 0,
13537 'aria-owns': 0,
13538 'aria-posinset': 0,
13539 'aria-rowcount': 0,
13540 'aria-rowindex': 0,
13541 'aria-rowspan': 0,
13542 'aria-setsize': 0
13543};
13544
13545var warnedProperties = {};
13546var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
13547var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
13548
13549var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
13550
13551function getStackAddendum() {
13552 var stack = ReactDebugCurrentFrame.getStackAddendum();
13553 return stack != null ? stack : '';
13554}
13555
13556function validateProperty(tagName, name) {
13557 if (hasOwnProperty$1.call(warnedProperties, name) && warnedProperties[name]) {
13558 return true;
13559 }
13560
13561 if (rARIACamel.test(name)) {
13562 var ariaName = 'aria-' + name.slice(4).toLowerCase();
13563 var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null;
13564
13565 // If this is an aria-* attribute, but is not listed in the known DOM
13566 // DOM properties, then it is an invalid aria-* attribute.
13567 if (correctName == null) {
13568 warning_1(false, 'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.%s', name, getStackAddendum());
13569 warnedProperties[name] = true;
13570 return true;
13571 }
13572 // aria-* attributes should be lowercase; suggest the lowercase version.
13573 if (name !== correctName) {
13574 warning_1(false, 'Invalid ARIA attribute `%s`. Did you mean `%s`?%s', name, correctName, getStackAddendum());
13575 warnedProperties[name] = true;
13576 return true;
13577 }
13578 }
13579
13580 if (rARIA.test(name)) {
13581 var lowerCasedName = name.toLowerCase();
13582 var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null;
13583
13584 // If this is an aria-* attribute, but is not listed in the known DOM
13585 // DOM properties, then it is an invalid aria-* attribute.
13586 if (standardName == null) {
13587 warnedProperties[name] = true;
13588 return false;
13589 }
13590 // aria-* attributes should be lowercase; suggest the lowercase version.
13591 if (name !== standardName) {
13592 warning_1(false, 'Unknown ARIA attribute `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum());
13593 warnedProperties[name] = true;
13594 return true;
13595 }
13596 }
13597
13598 return true;
13599}
13600
13601function warnInvalidARIAProps(type, props) {
13602 var invalidProps = [];
13603
13604 for (var key in props) {
13605 var isValid = validateProperty(type, key);
13606 if (!isValid) {
13607 invalidProps.push(key);
13608 }
13609 }
13610
13611 var unknownPropString = invalidProps.map(function (prop) {
13612 return '`' + prop + '`';
13613 }).join(', ');
13614
13615 if (invalidProps.length === 1) {
13616 warning_1(false, 'Invalid aria prop %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum());
13617 } else if (invalidProps.length > 1) {
13618 warning_1(false, 'Invalid aria props %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum());
13619 }
13620}
13621
13622function validateProperties(type, props) {
13623 if (isCustomComponent(type, props)) {
13624 return;
13625 }
13626 warnInvalidARIAProps(type, props);
13627}
13628
13629var didWarnValueNull = false;
13630
13631function getStackAddendum$1() {
13632 var stack = ReactDebugCurrentFrame.getStackAddendum();
13633 return stack != null ? stack : '';
13634}
13635
13636function validateProperties$1(type, props) {
13637 if (type !== 'input' && type !== 'textarea' && type !== 'select') {
13638 return;
13639 }
13640
13641 if (props != null && props.value === null && !didWarnValueNull) {
13642 didWarnValueNull = true;
13643 if (type === 'select' && props.multiple) {
13644 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());
13645 } else {
13646 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());
13647 }
13648 }
13649}
13650
13651function getStackAddendum$2() {
13652 var stack = ReactDebugCurrentFrame.getStackAddendum();
13653 return stack != null ? stack : '';
13654}
13655
13656var validateProperty$1 = function () {};
13657
13658{
13659 var warnedProperties$1 = {};
13660 var _hasOwnProperty = Object.prototype.hasOwnProperty;
13661 var EVENT_NAME_REGEX = /^on./;
13662 var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;
13663 var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
13664 var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
13665
13666 validateProperty$1 = function (tagName, name, value, canUseEventSystem) {
13667 if (_hasOwnProperty.call(warnedProperties$1, name) && warnedProperties$1[name]) {
13668 return true;
13669 }
13670
13671 var lowerCasedName = name.toLowerCase();
13672 if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') {
13673 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.');
13674 warnedProperties$1[name] = true;
13675 return true;
13676 }
13677
13678 // We can't rely on the event system being injected on the server.
13679 if (canUseEventSystem) {
13680 if (registrationNameModules.hasOwnProperty(name)) {
13681 return true;
13682 }
13683 var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null;
13684 if (registrationName != null) {
13685 warning_1(false, 'Invalid event handler property `%s`. Did you mean `%s`?%s', name, registrationName, getStackAddendum$2());
13686 warnedProperties$1[name] = true;
13687 return true;
13688 }
13689 if (EVENT_NAME_REGEX.test(name)) {
13690 warning_1(false, 'Unknown event handler property `%s`. It will be ignored.%s', name, getStackAddendum$2());
13691 warnedProperties$1[name] = true;
13692 return true;
13693 }
13694 } else if (EVENT_NAME_REGEX.test(name)) {
13695 // If no event plugins have been injected, we are in a server environment.
13696 // So we can't tell if the event name is correct for sure, but we can filter
13697 // out known bad ones like `onclick`. We can't suggest a specific replacement though.
13698 if (INVALID_EVENT_NAME_REGEX.test(name)) {
13699 warning_1(false, 'Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.%s', name, getStackAddendum$2());
13700 }
13701 warnedProperties$1[name] = true;
13702 return true;
13703 }
13704
13705 // Let the ARIA attribute hook validate ARIA attributes
13706 if (rARIA$1.test(name) || rARIACamel$1.test(name)) {
13707 return true;
13708 }
13709
13710 if (lowerCasedName === 'innerhtml') {
13711 warning_1(false, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.');
13712 warnedProperties$1[name] = true;
13713 return true;
13714 }
13715
13716 if (lowerCasedName === 'aria') {
13717 warning_1(false, 'The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.');
13718 warnedProperties$1[name] = true;
13719 return true;
13720 }
13721
13722 if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') {
13723 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());
13724 warnedProperties$1[name] = true;
13725 return true;
13726 }
13727
13728 if (typeof value === 'number' && isNaN(value)) {
13729 warning_1(false, 'Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.%s', name, getStackAddendum$2());
13730 warnedProperties$1[name] = true;
13731 return true;
13732 }
13733
13734 var propertyInfo = getPropertyInfo(name);
13735 var isReserved = propertyInfo !== null && propertyInfo.type === RESERVED;
13736
13737 // Known attributes should match the casing specified in the property config.
13738 if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
13739 var standardName = possibleStandardNames[lowerCasedName];
13740 if (standardName !== name) {
13741 warning_1(false, 'Invalid DOM property `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum$2());
13742 warnedProperties$1[name] = true;
13743 return true;
13744 }
13745 } else if (!isReserved && name !== lowerCasedName) {
13746 // Unknown attributes should have lowercase casing since that's how they
13747 // will be cased anyway with server rendering.
13748 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());
13749 warnedProperties$1[name] = true;
13750 return true;
13751 }
13752
13753 if (typeof value === 'boolean' && shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) {
13754 if (value) {
13755 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());
13756 } else {
13757 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());
13758 }
13759 warnedProperties$1[name] = true;
13760 return true;
13761 }
13762
13763 // Now that we've validated casing, do not validate
13764 // data types for reserved props
13765 if (isReserved) {
13766 return true;
13767 }
13768
13769 // Warn when a known attribute is a bad type
13770 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) {
13771 warnedProperties$1[name] = true;
13772 return false;
13773 }
13774
13775 return true;
13776 };
13777}
13778
13779var warnUnknownProperties = function (type, props, canUseEventSystem) {
13780 var unknownProps = [];
13781 for (var key in props) {
13782 var isValid = validateProperty$1(type, key, props[key], canUseEventSystem);
13783 if (!isValid) {
13784 unknownProps.push(key);
13785 }
13786 }
13787
13788 var unknownPropString = unknownProps.map(function (prop) {
13789 return '`' + prop + '`';
13790 }).join(', ');
13791 if (unknownProps.length === 1) {
13792 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());
13793 } else if (unknownProps.length > 1) {
13794 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());
13795 }
13796};
13797
13798function validateProperties$2(type, props, canUseEventSystem) {
13799 if (isCustomComponent(type, props)) {
13800 return;
13801 }
13802 warnUnknownProperties(type, props, canUseEventSystem);
13803}
13804
13805// TODO: direct imports like some-package/src/* are bad. Fix me.
13806var getCurrentFiberOwnerName$2 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
13807var getCurrentFiberStackAddendum$3 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
13808
13809var didWarnInvalidHydration = false;
13810var didWarnShadyDOM = false;
13811
13812var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
13813var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
13814var SUPPRESS_HYDRATION_WARNING$1 = 'suppressHydrationWarning';
13815var AUTOFOCUS = 'autoFocus';
13816var CHILDREN = 'children';
13817var STYLE = 'style';
13818var HTML = '__html';
13819
13820var HTML_NAMESPACE = Namespaces.html;
13821
13822
13823var getStack = emptyFunction_1.thatReturns('');
13824
13825var warnedUnknownTags = void 0;
13826var suppressHydrationWarning = void 0;
13827
13828var validatePropertiesInDevelopment = void 0;
13829var warnForTextDifference = void 0;
13830var warnForPropDifference = void 0;
13831var warnForExtraAttributes = void 0;
13832var warnForInvalidEventListener = void 0;
13833
13834var normalizeMarkupForTextOrAttribute = void 0;
13835var normalizeHTML = void 0;
13836
13837{
13838 getStack = getCurrentFiberStackAddendum$3;
13839
13840 warnedUnknownTags = {
13841 // Chrome is the only major browser not shipping <time>. But as of July
13842 // 2017 it intends to ship it due to widespread usage. We intentionally
13843 // *don't* warn for <time> even if it's unrecognized by Chrome because
13844 // it soon will be, and many apps have been using it anyway.
13845 time: true,
13846 // There are working polyfills for <dialog>. Let people use it.
13847 dialog: true
13848 };
13849
13850 validatePropertiesInDevelopment = function (type, props) {
13851 validateProperties(type, props);
13852 validateProperties$1(type, props);
13853 validateProperties$2(type, props, /* canUseEventSystem */true);
13854 };
13855
13856 // HTML parsing normalizes CR and CRLF to LF.
13857 // It also can turn \u0000 into \uFFFD inside attributes.
13858 // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream
13859 // If we have a mismatch, it might be caused by that.
13860 // We will still patch up in this case but not fire the warning.
13861 var NORMALIZE_NEWLINES_REGEX = /\r\n?/g;
13862 var NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g;
13863
13864 normalizeMarkupForTextOrAttribute = function (markup) {
13865 var markupString = typeof markup === 'string' ? markup : '' + markup;
13866 return markupString.replace(NORMALIZE_NEWLINES_REGEX, '\n').replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, '');
13867 };
13868
13869 warnForTextDifference = function (serverText, clientText) {
13870 if (didWarnInvalidHydration) {
13871 return;
13872 }
13873 var normalizedClientText = normalizeMarkupForTextOrAttribute(clientText);
13874 var normalizedServerText = normalizeMarkupForTextOrAttribute(serverText);
13875 if (normalizedServerText === normalizedClientText) {
13876 return;
13877 }
13878 didWarnInvalidHydration = true;
13879 warning_1(false, 'Text content did not match. Server: "%s" Client: "%s"', normalizedServerText, normalizedClientText);
13880 };
13881
13882 warnForPropDifference = function (propName, serverValue, clientValue) {
13883 if (didWarnInvalidHydration) {
13884 return;
13885 }
13886 var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue);
13887 var normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);
13888 if (normalizedServerValue === normalizedClientValue) {
13889 return;
13890 }
13891 didWarnInvalidHydration = true;
13892 warning_1(false, 'Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue));
13893 };
13894
13895 warnForExtraAttributes = function (attributeNames) {
13896 if (didWarnInvalidHydration) {
13897 return;
13898 }
13899 didWarnInvalidHydration = true;
13900 var names = [];
13901 attributeNames.forEach(function (name) {
13902 names.push(name);
13903 });
13904 warning_1(false, 'Extra attributes from the server: %s', names);
13905 };
13906
13907 warnForInvalidEventListener = function (registrationName, listener) {
13908 if (listener === false) {
13909 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());
13910 } else {
13911 warning_1(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.%s', registrationName, typeof listener, getCurrentFiberStackAddendum$3());
13912 }
13913 };
13914
13915 // Parse the HTML and read it back to normalize the HTML string so that it
13916 // can be used for comparison.
13917 normalizeHTML = function (parent, html) {
13918 // We could have created a separate document here to avoid
13919 // re-initializing custom elements if they exist. But this breaks
13920 // how <noscript> is being handled. So we use the same document.
13921 // See the discussion in https://github.com/facebook/react/pull/11157.
13922 var testElement = parent.namespaceURI === HTML_NAMESPACE ? parent.ownerDocument.createElement(parent.tagName) : parent.ownerDocument.createElementNS(parent.namespaceURI, parent.tagName);
13923 testElement.innerHTML = html;
13924 return testElement.innerHTML;
13925 };
13926}
13927
13928function ensureListeningTo(rootContainerElement, registrationName) {
13929 var isDocumentOrFragment = rootContainerElement.nodeType === DOCUMENT_NODE || rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE;
13930 var doc = isDocumentOrFragment ? rootContainerElement : rootContainerElement.ownerDocument;
13931 listenTo(registrationName, doc);
13932}
13933
13934function getOwnerDocumentFromRootContainer(rootContainerElement) {
13935 return rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument;
13936}
13937
13938// There are so many media events, it makes sense to just
13939// maintain a list rather than create a `trapBubbledEvent` for each
13940var mediaEvents = {
13941 topAbort: 'abort',
13942 topCanPlay: 'canplay',
13943 topCanPlayThrough: 'canplaythrough',
13944 topDurationChange: 'durationchange',
13945 topEmptied: 'emptied',
13946 topEncrypted: 'encrypted',
13947 topEnded: 'ended',
13948 topError: 'error',
13949 topLoadedData: 'loadeddata',
13950 topLoadedMetadata: 'loadedmetadata',
13951 topLoadStart: 'loadstart',
13952 topPause: 'pause',
13953 topPlay: 'play',
13954 topPlaying: 'playing',
13955 topProgress: 'progress',
13956 topRateChange: 'ratechange',
13957 topSeeked: 'seeked',
13958 topSeeking: 'seeking',
13959 topStalled: 'stalled',
13960 topSuspend: 'suspend',
13961 topTimeUpdate: 'timeupdate',
13962 topVolumeChange: 'volumechange',
13963 topWaiting: 'waiting'
13964};
13965
13966function trapClickOnNonInteractiveElement(node) {
13967 // Mobile Safari does not fire properly bubble click events on
13968 // non-interactive elements, which means delegated click listeners do not
13969 // fire. The workaround for this bug involves attaching an empty click
13970 // listener on the target node.
13971 // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
13972 // Just set it using the onclick property so that we don't have to manage any
13973 // bookkeeping for it. Not sure if we need to clear it when the listener is
13974 // removed.
13975 // TODO: Only do this for the relevant Safaris maybe?
13976 node.onclick = emptyFunction_1;
13977}
13978
13979function setInitialDOMProperties(tag, domElement, rootContainerElement, nextProps, isCustomComponentTag) {
13980 for (var propKey in nextProps) {
13981 if (!nextProps.hasOwnProperty(propKey)) {
13982 continue;
13983 }
13984 var nextProp = nextProps[propKey];
13985 if (propKey === STYLE) {
13986 {
13987 if (nextProp) {
13988 // Freeze the next style object so that we can assume it won't be
13989 // mutated. We have already warned for this in the past.
13990 Object.freeze(nextProp);
13991 }
13992 }
13993 // Relies on `updateStylesByID` not mutating `styleUpdates`.
13994 setValueForStyles(domElement, nextProp, getStack);
13995 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
13996 var nextHtml = nextProp ? nextProp[HTML] : undefined;
13997 if (nextHtml != null) {
13998 setInnerHTML(domElement, nextHtml);
13999 }
14000 } else if (propKey === CHILDREN) {
14001 if (typeof nextProp === 'string') {
14002 // Avoid setting initial textContent when the text is empty. In IE11 setting
14003 // textContent on a <textarea> will cause the placeholder to not
14004 // show within the <textarea> until it has been focused and blurred again.
14005 // https://github.com/facebook/react/issues/6731#issuecomment-254874553
14006 var canSetTextContent = tag !== 'textarea' || nextProp !== '';
14007 if (canSetTextContent) {
14008 setTextContent(domElement, nextProp);
14009 }
14010 } else if (typeof nextProp === 'number') {
14011 setTextContent(domElement, '' + nextProp);
14012 }
14013 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
14014 // Noop
14015 } else if (propKey === AUTOFOCUS) {
14016 // We polyfill it separately on the client during commit.
14017 // We blacklist it here rather than in the property list because we emit it in SSR.
14018 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14019 if (nextProp != null) {
14020 if (true && typeof nextProp !== 'function') {
14021 warnForInvalidEventListener(propKey, nextProp);
14022 }
14023 ensureListeningTo(rootContainerElement, propKey);
14024 }
14025 } else if (nextProp != null) {
14026 setValueForProperty(domElement, propKey, nextProp, isCustomComponentTag);
14027 }
14028 }
14029}
14030
14031function updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag) {
14032 // TODO: Handle wasCustomComponentTag
14033 for (var i = 0; i < updatePayload.length; i += 2) {
14034 var propKey = updatePayload[i];
14035 var propValue = updatePayload[i + 1];
14036 if (propKey === STYLE) {
14037 setValueForStyles(domElement, propValue, getStack);
14038 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14039 setInnerHTML(domElement, propValue);
14040 } else if (propKey === CHILDREN) {
14041 setTextContent(domElement, propValue);
14042 } else {
14043 setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);
14044 }
14045 }
14046}
14047
14048function createElement$1(type, props, rootContainerElement, parentNamespace) {
14049 var isCustomComponentTag = void 0;
14050
14051 // We create tags in the namespace of their parent container, except HTML
14052 // tags get no namespace.
14053 var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement);
14054 var domElement = void 0;
14055 var namespaceURI = parentNamespace;
14056 if (namespaceURI === HTML_NAMESPACE) {
14057 namespaceURI = getIntrinsicNamespace(type);
14058 }
14059 if (namespaceURI === HTML_NAMESPACE) {
14060 {
14061 isCustomComponentTag = isCustomComponent(type, props);
14062 // Should this check be gated by parent namespace? Not sure we want to
14063 // allow <SVG> or <mATH>.
14064 warning_1(isCustomComponentTag || type === type.toLowerCase(), '<%s /> is using uppercase HTML. Always use lowercase HTML tags ' + 'in React.', type);
14065 }
14066
14067 if (type === 'script') {
14068 // Create the script via .innerHTML so its "parser-inserted" flag is
14069 // set to true and it does not execute
14070 var div = ownerDocument.createElement('div');
14071 div.innerHTML = '<script><' + '/script>'; // eslint-disable-line
14072 // This is guaranteed to yield a script element.
14073 var firstChild = div.firstChild;
14074 domElement = div.removeChild(firstChild);
14075 } else if (typeof props.is === 'string') {
14076 // $FlowIssue `createElement` should be updated for Web Components
14077 domElement = ownerDocument.createElement(type, { is: props.is });
14078 } else {
14079 // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
14080 // See discussion in https://github.com/facebook/react/pull/6896
14081 // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
14082 domElement = ownerDocument.createElement(type);
14083 }
14084 } else {
14085 domElement = ownerDocument.createElementNS(namespaceURI, type);
14086 }
14087
14088 {
14089 if (namespaceURI === HTML_NAMESPACE) {
14090 if (!isCustomComponentTag && Object.prototype.toString.call(domElement) === '[object HTMLUnknownElement]' && !Object.prototype.hasOwnProperty.call(warnedUnknownTags, type)) {
14091 warnedUnknownTags[type] = true;
14092 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);
14093 }
14094 }
14095 }
14096
14097 return domElement;
14098}
14099
14100function createTextNode$1(text, rootContainerElement) {
14101 return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(text);
14102}
14103
14104function setInitialProperties$1(domElement, tag, rawProps, rootContainerElement) {
14105 var isCustomComponentTag = isCustomComponent(tag, rawProps);
14106 {
14107 validatePropertiesInDevelopment(tag, rawProps);
14108 if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
14109 warning_1(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName$2() || 'A component');
14110 didWarnShadyDOM = true;
14111 }
14112 }
14113
14114 // TODO: Make sure that we check isMounted before firing any of these events.
14115 var props = void 0;
14116 switch (tag) {
14117 case 'iframe':
14118 case 'object':
14119 trapBubbledEvent('topLoad', 'load', domElement);
14120 props = rawProps;
14121 break;
14122 case 'video':
14123 case 'audio':
14124 // Create listener for each media event
14125 for (var event in mediaEvents) {
14126 if (mediaEvents.hasOwnProperty(event)) {
14127 trapBubbledEvent(event, mediaEvents[event], domElement);
14128 }
14129 }
14130 props = rawProps;
14131 break;
14132 case 'source':
14133 trapBubbledEvent('topError', 'error', domElement);
14134 props = rawProps;
14135 break;
14136 case 'img':
14137 case 'image':
14138 case 'link':
14139 trapBubbledEvent('topError', 'error', domElement);
14140 trapBubbledEvent('topLoad', 'load', domElement);
14141 props = rawProps;
14142 break;
14143 case 'form':
14144 trapBubbledEvent('topReset', 'reset', domElement);
14145 trapBubbledEvent('topSubmit', 'submit', domElement);
14146 props = rawProps;
14147 break;
14148 case 'details':
14149 trapBubbledEvent('topToggle', 'toggle', domElement);
14150 props = rawProps;
14151 break;
14152 case 'input':
14153 initWrapperState(domElement, rawProps);
14154 props = getHostProps(domElement, rawProps);
14155 trapBubbledEvent('topInvalid', 'invalid', domElement);
14156 // For controlled components we always need to ensure we're listening
14157 // to onChange. Even if there is no listener.
14158 ensureListeningTo(rootContainerElement, 'onChange');
14159 break;
14160 case 'option':
14161 validateProps(domElement, rawProps);
14162 props = getHostProps$1(domElement, rawProps);
14163 break;
14164 case 'select':
14165 initWrapperState$1(domElement, rawProps);
14166 props = getHostProps$2(domElement, rawProps);
14167 trapBubbledEvent('topInvalid', 'invalid', domElement);
14168 // For controlled components we always need to ensure we're listening
14169 // to onChange. Even if there is no listener.
14170 ensureListeningTo(rootContainerElement, 'onChange');
14171 break;
14172 case 'textarea':
14173 initWrapperState$2(domElement, rawProps);
14174 props = getHostProps$3(domElement, rawProps);
14175 trapBubbledEvent('topInvalid', 'invalid', domElement);
14176 // For controlled components we always need to ensure we're listening
14177 // to onChange. Even if there is no listener.
14178 ensureListeningTo(rootContainerElement, 'onChange');
14179 break;
14180 default:
14181 props = rawProps;
14182 }
14183
14184 assertValidProps(tag, props, getStack);
14185
14186 setInitialDOMProperties(tag, domElement, rootContainerElement, props, isCustomComponentTag);
14187
14188 switch (tag) {
14189 case 'input':
14190 // TODO: Make sure we check if this is still unmounted or do any clean
14191 // up necessary since we never stop tracking anymore.
14192 track(domElement);
14193 postMountWrapper(domElement, rawProps);
14194 break;
14195 case 'textarea':
14196 // TODO: Make sure we check if this is still unmounted or do any clean
14197 // up necessary since we never stop tracking anymore.
14198 track(domElement);
14199 postMountWrapper$3(domElement, rawProps);
14200 break;
14201 case 'option':
14202 postMountWrapper$1(domElement, rawProps);
14203 break;
14204 case 'select':
14205 postMountWrapper$2(domElement, rawProps);
14206 break;
14207 default:
14208 if (typeof props.onClick === 'function') {
14209 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14210 trapClickOnNonInteractiveElement(domElement);
14211 }
14212 break;
14213 }
14214}
14215
14216// Calculate the diff between the two objects.
14217function diffProperties$1(domElement, tag, lastRawProps, nextRawProps, rootContainerElement) {
14218 {
14219 validatePropertiesInDevelopment(tag, nextRawProps);
14220 }
14221
14222 var updatePayload = null;
14223
14224 var lastProps = void 0;
14225 var nextProps = void 0;
14226 switch (tag) {
14227 case 'input':
14228 lastProps = getHostProps(domElement, lastRawProps);
14229 nextProps = getHostProps(domElement, nextRawProps);
14230 updatePayload = [];
14231 break;
14232 case 'option':
14233 lastProps = getHostProps$1(domElement, lastRawProps);
14234 nextProps = getHostProps$1(domElement, nextRawProps);
14235 updatePayload = [];
14236 break;
14237 case 'select':
14238 lastProps = getHostProps$2(domElement, lastRawProps);
14239 nextProps = getHostProps$2(domElement, nextRawProps);
14240 updatePayload = [];
14241 break;
14242 case 'textarea':
14243 lastProps = getHostProps$3(domElement, lastRawProps);
14244 nextProps = getHostProps$3(domElement, nextRawProps);
14245 updatePayload = [];
14246 break;
14247 default:
14248 lastProps = lastRawProps;
14249 nextProps = nextRawProps;
14250 if (typeof lastProps.onClick !== 'function' && typeof nextProps.onClick === 'function') {
14251 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14252 trapClickOnNonInteractiveElement(domElement);
14253 }
14254 break;
14255 }
14256
14257 assertValidProps(tag, nextProps, getStack);
14258
14259 var propKey = void 0;
14260 var styleName = void 0;
14261 var styleUpdates = null;
14262 for (propKey in lastProps) {
14263 if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
14264 continue;
14265 }
14266 if (propKey === STYLE) {
14267 var lastStyle = lastProps[propKey];
14268 for (styleName in lastStyle) {
14269 if (lastStyle.hasOwnProperty(styleName)) {
14270 if (!styleUpdates) {
14271 styleUpdates = {};
14272 }
14273 styleUpdates[styleName] = '';
14274 }
14275 }
14276 } else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN) {
14277 // Noop. This is handled by the clear text mechanism.
14278 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
14279 // Noop
14280 } else if (propKey === AUTOFOCUS) {
14281 // Noop. It doesn't work on updates anyway.
14282 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14283 // This is a special case. If any listener updates we need to ensure
14284 // that the "current" fiber pointer gets updated so we need a commit
14285 // to update this element.
14286 if (!updatePayload) {
14287 updatePayload = [];
14288 }
14289 } else {
14290 // For all other deleted properties we add it to the queue. We use
14291 // the whitelist in the commit phase instead.
14292 (updatePayload = updatePayload || []).push(propKey, null);
14293 }
14294 }
14295 for (propKey in nextProps) {
14296 var nextProp = nextProps[propKey];
14297 var lastProp = lastProps != null ? lastProps[propKey] : undefined;
14298 if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
14299 continue;
14300 }
14301 if (propKey === STYLE) {
14302 {
14303 if (nextProp) {
14304 // Freeze the next style object so that we can assume it won't be
14305 // mutated. We have already warned for this in the past.
14306 Object.freeze(nextProp);
14307 }
14308 }
14309 if (lastProp) {
14310 // Unset styles on `lastProp` but not on `nextProp`.
14311 for (styleName in lastProp) {
14312 if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
14313 if (!styleUpdates) {
14314 styleUpdates = {};
14315 }
14316 styleUpdates[styleName] = '';
14317 }
14318 }
14319 // Update styles that changed since `lastProp`.
14320 for (styleName in nextProp) {
14321 if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
14322 if (!styleUpdates) {
14323 styleUpdates = {};
14324 }
14325 styleUpdates[styleName] = nextProp[styleName];
14326 }
14327 }
14328 } else {
14329 // Relies on `updateStylesByID` not mutating `styleUpdates`.
14330 if (!styleUpdates) {
14331 if (!updatePayload) {
14332 updatePayload = [];
14333 }
14334 updatePayload.push(propKey, styleUpdates);
14335 }
14336 styleUpdates = nextProp;
14337 }
14338 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14339 var nextHtml = nextProp ? nextProp[HTML] : undefined;
14340 var lastHtml = lastProp ? lastProp[HTML] : undefined;
14341 if (nextHtml != null) {
14342 if (lastHtml !== nextHtml) {
14343 (updatePayload = updatePayload || []).push(propKey, '' + nextHtml);
14344 }
14345 } else {
14346 // TODO: It might be too late to clear this if we have children
14347 // inserted already.
14348 }
14349 } else if (propKey === CHILDREN) {
14350 if (lastProp !== nextProp && (typeof nextProp === 'string' || typeof nextProp === 'number')) {
14351 (updatePayload = updatePayload || []).push(propKey, '' + nextProp);
14352 }
14353 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
14354 // Noop
14355 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14356 if (nextProp != null) {
14357 // We eagerly listen to this even though we haven't committed yet.
14358 if (true && typeof nextProp !== 'function') {
14359 warnForInvalidEventListener(propKey, nextProp);
14360 }
14361 ensureListeningTo(rootContainerElement, propKey);
14362 }
14363 if (!updatePayload && lastProp !== nextProp) {
14364 // This is a special case. If any listener updates we need to ensure
14365 // that the "current" props pointer gets updated so we need a commit
14366 // to update this element.
14367 updatePayload = [];
14368 }
14369 } else {
14370 // For any other property we always add it to the queue and then we
14371 // filter it out using the whitelist during the commit.
14372 (updatePayload = updatePayload || []).push(propKey, nextProp);
14373 }
14374 }
14375 if (styleUpdates) {
14376 (updatePayload = updatePayload || []).push(STYLE, styleUpdates);
14377 }
14378 return updatePayload;
14379}
14380
14381// Apply the diff.
14382function updateProperties$1(domElement, updatePayload, tag, lastRawProps, nextRawProps) {
14383 // Update checked *before* name.
14384 // In the middle of an update, it is possible to have multiple checked.
14385 // When a checked radio tries to change name, browser makes another radio's checked false.
14386 if (tag === 'input' && nextRawProps.type === 'radio' && nextRawProps.name != null) {
14387 updateChecked(domElement, nextRawProps);
14388 }
14389
14390 var wasCustomComponentTag = isCustomComponent(tag, lastRawProps);
14391 var isCustomComponentTag = isCustomComponent(tag, nextRawProps);
14392 // Apply the diff.
14393 updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag);
14394
14395 // TODO: Ensure that an update gets scheduled if any of the special props
14396 // changed.
14397 switch (tag) {
14398 case 'input':
14399 // Update the wrapper around inputs *after* updating props. This has to
14400 // happen after `updateDOMProperties`. Otherwise HTML5 input validations
14401 // raise warnings and prevent the new value from being assigned.
14402 updateWrapper(domElement, nextRawProps);
14403 break;
14404 case 'textarea':
14405 updateWrapper$1(domElement, nextRawProps);
14406 break;
14407 case 'select':
14408 // <select> value update needs to occur after <option> children
14409 // reconciliation
14410 postUpdateWrapper(domElement, nextRawProps);
14411 break;
14412 }
14413}
14414
14415function getPossibleStandardName(propName) {
14416 {
14417 var lowerCasedName = propName.toLowerCase();
14418 if (!possibleStandardNames.hasOwnProperty(lowerCasedName)) {
14419 return null;
14420 }
14421 return possibleStandardNames[lowerCasedName] || null;
14422 }
14423 return null;
14424}
14425
14426function diffHydratedProperties$1(domElement, tag, rawProps, parentNamespace, rootContainerElement) {
14427 var isCustomComponentTag = void 0;
14428 var extraAttributeNames = void 0;
14429
14430 {
14431 suppressHydrationWarning = rawProps[SUPPRESS_HYDRATION_WARNING$1] === true;
14432 isCustomComponentTag = isCustomComponent(tag, rawProps);
14433 validatePropertiesInDevelopment(tag, rawProps);
14434 if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
14435 warning_1(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName$2() || 'A component');
14436 didWarnShadyDOM = true;
14437 }
14438 }
14439
14440 // TODO: Make sure that we check isMounted before firing any of these events.
14441 switch (tag) {
14442 case 'iframe':
14443 case 'object':
14444 trapBubbledEvent('topLoad', 'load', domElement);
14445 break;
14446 case 'video':
14447 case 'audio':
14448 // Create listener for each media event
14449 for (var event in mediaEvents) {
14450 if (mediaEvents.hasOwnProperty(event)) {
14451 trapBubbledEvent(event, mediaEvents[event], domElement);
14452 }
14453 }
14454 break;
14455 case 'source':
14456 trapBubbledEvent('topError', 'error', domElement);
14457 break;
14458 case 'img':
14459 case 'image':
14460 case 'link':
14461 trapBubbledEvent('topError', 'error', domElement);
14462 trapBubbledEvent('topLoad', 'load', domElement);
14463 break;
14464 case 'form':
14465 trapBubbledEvent('topReset', 'reset', domElement);
14466 trapBubbledEvent('topSubmit', 'submit', domElement);
14467 break;
14468 case 'details':
14469 trapBubbledEvent('topToggle', 'toggle', domElement);
14470 break;
14471 case 'input':
14472 initWrapperState(domElement, rawProps);
14473 trapBubbledEvent('topInvalid', 'invalid', domElement);
14474 // For controlled components we always need to ensure we're listening
14475 // to onChange. Even if there is no listener.
14476 ensureListeningTo(rootContainerElement, 'onChange');
14477 break;
14478 case 'option':
14479 validateProps(domElement, rawProps);
14480 break;
14481 case 'select':
14482 initWrapperState$1(domElement, rawProps);
14483 trapBubbledEvent('topInvalid', 'invalid', domElement);
14484 // For controlled components we always need to ensure we're listening
14485 // to onChange. Even if there is no listener.
14486 ensureListeningTo(rootContainerElement, 'onChange');
14487 break;
14488 case 'textarea':
14489 initWrapperState$2(domElement, rawProps);
14490 trapBubbledEvent('topInvalid', 'invalid', domElement);
14491 // For controlled components we always need to ensure we're listening
14492 // to onChange. Even if there is no listener.
14493 ensureListeningTo(rootContainerElement, 'onChange');
14494 break;
14495 }
14496
14497 assertValidProps(tag, rawProps, getStack);
14498
14499 {
14500 extraAttributeNames = new Set();
14501 var attributes = domElement.attributes;
14502 for (var i = 0; i < attributes.length; i++) {
14503 var name = attributes[i].name.toLowerCase();
14504 switch (name) {
14505 // Built-in SSR attribute is whitelisted
14506 case 'data-reactroot':
14507 break;
14508 // Controlled attributes are not validated
14509 // TODO: Only ignore them on controlled tags.
14510 case 'value':
14511 break;
14512 case 'checked':
14513 break;
14514 case 'selected':
14515 break;
14516 default:
14517 // Intentionally use the original name.
14518 // See discussion in https://github.com/facebook/react/pull/10676.
14519 extraAttributeNames.add(attributes[i].name);
14520 }
14521 }
14522 }
14523
14524 var updatePayload = null;
14525 for (var propKey in rawProps) {
14526 if (!rawProps.hasOwnProperty(propKey)) {
14527 continue;
14528 }
14529 var nextProp = rawProps[propKey];
14530 if (propKey === CHILDREN) {
14531 // For text content children we compare against textContent. This
14532 // might match additional HTML that is hidden when we read it using
14533 // textContent. E.g. "foo" will match "f<span>oo</span>" but that still
14534 // satisfies our requirement. Our requirement is not to produce perfect
14535 // HTML and attributes. Ideally we should preserve structure but it's
14536 // ok not to if the visible content is still enough to indicate what
14537 // even listeners these nodes might be wired up to.
14538 // TODO: Warn if there is more than a single textNode as a child.
14539 // TODO: Should we use domElement.firstChild.nodeValue to compare?
14540 if (typeof nextProp === 'string') {
14541 if (domElement.textContent !== nextProp) {
14542 if (true && !suppressHydrationWarning) {
14543 warnForTextDifference(domElement.textContent, nextProp);
14544 }
14545 updatePayload = [CHILDREN, nextProp];
14546 }
14547 } else if (typeof nextProp === 'number') {
14548 if (domElement.textContent !== '' + nextProp) {
14549 if (true && !suppressHydrationWarning) {
14550 warnForTextDifference(domElement.textContent, nextProp);
14551 }
14552 updatePayload = [CHILDREN, '' + nextProp];
14553 }
14554 }
14555 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14556 if (nextProp != null) {
14557 if (true && typeof nextProp !== 'function') {
14558 warnForInvalidEventListener(propKey, nextProp);
14559 }
14560 ensureListeningTo(rootContainerElement, propKey);
14561 }
14562 } else if (true &&
14563 // Convince Flow we've calculated it (it's DEV-only in this method.)
14564 typeof isCustomComponentTag === 'boolean') {
14565 // Validate that the properties correspond to their expected values.
14566 var serverValue = void 0;
14567 var propertyInfo = getPropertyInfo(propKey);
14568 if (suppressHydrationWarning) {
14569 // Don't bother comparing. We're ignoring all these warnings.
14570 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1 ||
14571 // Controlled attributes are not validated
14572 // TODO: Only ignore them on controlled tags.
14573 propKey === 'value' || propKey === 'checked' || propKey === 'selected') {
14574 // Noop
14575 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14576 var rawHtml = nextProp ? nextProp[HTML] || '' : '';
14577 var serverHTML = domElement.innerHTML;
14578 var expectedHTML = normalizeHTML(domElement, rawHtml);
14579 if (expectedHTML !== serverHTML) {
14580 warnForPropDifference(propKey, serverHTML, expectedHTML);
14581 }
14582 } else if (propKey === STYLE) {
14583 // $FlowFixMe - Should be inferred as not undefined.
14584 extraAttributeNames['delete'](propKey);
14585 var expectedStyle = createDangerousStringForStyles(nextProp);
14586 serverValue = domElement.getAttribute('style');
14587 if (expectedStyle !== serverValue) {
14588 warnForPropDifference(propKey, serverValue, expectedStyle);
14589 }
14590 } else if (isCustomComponentTag) {
14591 // $FlowFixMe - Should be inferred as not undefined.
14592 extraAttributeNames['delete'](propKey.toLowerCase());
14593 serverValue = getValueForAttribute(domElement, propKey, nextProp);
14594
14595 if (nextProp !== serverValue) {
14596 warnForPropDifference(propKey, serverValue, nextProp);
14597 }
14598 } else if (!shouldIgnoreAttribute(propKey, propertyInfo, isCustomComponentTag) && !shouldRemoveAttribute(propKey, nextProp, propertyInfo, isCustomComponentTag)) {
14599 var isMismatchDueToBadCasing = false;
14600 if (propertyInfo !== null) {
14601 // $FlowFixMe - Should be inferred as not undefined.
14602 extraAttributeNames['delete'](propertyInfo.attributeName);
14603 serverValue = getValueForProperty(domElement, propKey, nextProp, propertyInfo);
14604 } else {
14605 var ownNamespace = parentNamespace;
14606 if (ownNamespace === HTML_NAMESPACE) {
14607 ownNamespace = getIntrinsicNamespace(tag);
14608 }
14609 if (ownNamespace === HTML_NAMESPACE) {
14610 // $FlowFixMe - Should be inferred as not undefined.
14611 extraAttributeNames['delete'](propKey.toLowerCase());
14612 } else {
14613 var standardName = getPossibleStandardName(propKey);
14614 if (standardName !== null && standardName !== propKey) {
14615 // If an SVG prop is supplied with bad casing, it will
14616 // be successfully parsed from HTML, but will produce a mismatch
14617 // (and would be incorrectly rendered on the client).
14618 // However, we already warn about bad casing elsewhere.
14619 // So we'll skip the misleading extra mismatch warning in this case.
14620 isMismatchDueToBadCasing = true;
14621 // $FlowFixMe - Should be inferred as not undefined.
14622 extraAttributeNames['delete'](standardName);
14623 }
14624 // $FlowFixMe - Should be inferred as not undefined.
14625 extraAttributeNames['delete'](propKey);
14626 }
14627 serverValue = getValueForAttribute(domElement, propKey, nextProp);
14628 }
14629
14630 if (nextProp !== serverValue && !isMismatchDueToBadCasing) {
14631 warnForPropDifference(propKey, serverValue, nextProp);
14632 }
14633 }
14634 }
14635 }
14636
14637 {
14638 // $FlowFixMe - Should be inferred as not undefined.
14639 if (extraAttributeNames.size > 0 && !suppressHydrationWarning) {
14640 // $FlowFixMe - Should be inferred as not undefined.
14641 warnForExtraAttributes(extraAttributeNames);
14642 }
14643 }
14644
14645 switch (tag) {
14646 case 'input':
14647 // TODO: Make sure we check if this is still unmounted or do any clean
14648 // up necessary since we never stop tracking anymore.
14649 track(domElement);
14650 postMountWrapper(domElement, rawProps);
14651 break;
14652 case 'textarea':
14653 // TODO: Make sure we check if this is still unmounted or do any clean
14654 // up necessary since we never stop tracking anymore.
14655 track(domElement);
14656 postMountWrapper$3(domElement, rawProps);
14657 break;
14658 case 'select':
14659 case 'option':
14660 // For input and textarea we current always set the value property at
14661 // post mount to force it to diverge from attributes. However, for
14662 // option and select we don't quite do the same thing and select
14663 // is not resilient to the DOM state changing so we don't do that here.
14664 // TODO: Consider not doing this for input and textarea.
14665 break;
14666 default:
14667 if (typeof rawProps.onClick === 'function') {
14668 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14669 trapClickOnNonInteractiveElement(domElement);
14670 }
14671 break;
14672 }
14673
14674 return updatePayload;
14675}
14676
14677function diffHydratedText$1(textNode, text) {
14678 var isDifferent = textNode.nodeValue !== text;
14679 return isDifferent;
14680}
14681
14682function warnForUnmatchedText$1(textNode, text) {
14683 {
14684 warnForTextDifference(textNode.nodeValue, text);
14685 }
14686}
14687
14688function warnForDeletedHydratableElement$1(parentNode, child) {
14689 {
14690 if (didWarnInvalidHydration) {
14691 return;
14692 }
14693 didWarnInvalidHydration = true;
14694 warning_1(false, 'Did not expect server HTML to contain a <%s> in <%s>.', child.nodeName.toLowerCase(), parentNode.nodeName.toLowerCase());
14695 }
14696}
14697
14698function warnForDeletedHydratableText$1(parentNode, child) {
14699 {
14700 if (didWarnInvalidHydration) {
14701 return;
14702 }
14703 didWarnInvalidHydration = true;
14704 warning_1(false, 'Did not expect server HTML to contain the text node "%s" in <%s>.', child.nodeValue, parentNode.nodeName.toLowerCase());
14705 }
14706}
14707
14708function warnForInsertedHydratedElement$1(parentNode, tag, props) {
14709 {
14710 if (didWarnInvalidHydration) {
14711 return;
14712 }
14713 didWarnInvalidHydration = true;
14714 warning_1(false, 'Expected server HTML to contain a matching <%s> in <%s>.', tag, parentNode.nodeName.toLowerCase());
14715 }
14716}
14717
14718function warnForInsertedHydratedText$1(parentNode, text) {
14719 {
14720 if (text === '') {
14721 // We expect to insert empty text nodes since they're not represented in
14722 // the HTML.
14723 // TODO: Remove this special case if we can just avoid inserting empty
14724 // text nodes.
14725 return;
14726 }
14727 if (didWarnInvalidHydration) {
14728 return;
14729 }
14730 didWarnInvalidHydration = true;
14731 warning_1(false, 'Expected server HTML to contain a matching text node for "%s" in <%s>.', text, parentNode.nodeName.toLowerCase());
14732 }
14733}
14734
14735function restoreControlledState$1(domElement, tag, props) {
14736 switch (tag) {
14737 case 'input':
14738 restoreControlledState(domElement, props);
14739 return;
14740 case 'textarea':
14741 restoreControlledState$3(domElement, props);
14742 return;
14743 case 'select':
14744 restoreControlledState$2(domElement, props);
14745 return;
14746 }
14747}
14748
14749var ReactDOMFiberComponent = Object.freeze({
14750 createElement: createElement$1,
14751 createTextNode: createTextNode$1,
14752 setInitialProperties: setInitialProperties$1,
14753 diffProperties: diffProperties$1,
14754 updateProperties: updateProperties$1,
14755 diffHydratedProperties: diffHydratedProperties$1,
14756 diffHydratedText: diffHydratedText$1,
14757 warnForUnmatchedText: warnForUnmatchedText$1,
14758 warnForDeletedHydratableElement: warnForDeletedHydratableElement$1,
14759 warnForDeletedHydratableText: warnForDeletedHydratableText$1,
14760 warnForInsertedHydratedElement: warnForInsertedHydratedElement$1,
14761 warnForInsertedHydratedText: warnForInsertedHydratedText$1,
14762 restoreControlledState: restoreControlledState$1
14763});
14764
14765// TODO: direct imports like some-package/src/* are bad. Fix me.
14766var getCurrentFiberStackAddendum$6 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
14767
14768var validateDOMNesting = emptyFunction_1;
14769
14770{
14771 // This validation code was written based on the HTML5 parsing spec:
14772 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
14773 //
14774 // Note: this does not catch all invalid nesting, nor does it try to (as it's
14775 // not clear what practical benefit doing so provides); instead, we warn only
14776 // for cases where the parser will give a parse tree differing from what React
14777 // intended. For example, <b><div></div></b> is invalid but we don't warn
14778 // because it still parses correctly; we do warn for other cases like nested
14779 // <p> tags where the beginning of the second element implicitly closes the
14780 // first, causing a confusing mess.
14781
14782 // https://html.spec.whatwg.org/multipage/syntax.html#special
14783 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'];
14784
14785 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
14786 var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
14787
14788 // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
14789 // TODO: Distinguish by namespace here -- for <title>, including it here
14790 // errs on the side of fewer warnings
14791 'foreignObject', 'desc', 'title'];
14792
14793 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
14794 var buttonScopeTags = inScopeTags.concat(['button']);
14795
14796 // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
14797 var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
14798
14799 var emptyAncestorInfo = {
14800 current: null,
14801
14802 formTag: null,
14803 aTagInScope: null,
14804 buttonTagInScope: null,
14805 nobrTagInScope: null,
14806 pTagInButtonScope: null,
14807
14808 listItemTagAutoclosing: null,
14809 dlItemTagAutoclosing: null
14810 };
14811
14812 var updatedAncestorInfo$1 = function (oldInfo, tag, instance) {
14813 var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);
14814 var info = { tag: tag, instance: instance };
14815
14816 if (inScopeTags.indexOf(tag) !== -1) {
14817 ancestorInfo.aTagInScope = null;
14818 ancestorInfo.buttonTagInScope = null;
14819 ancestorInfo.nobrTagInScope = null;
14820 }
14821 if (buttonScopeTags.indexOf(tag) !== -1) {
14822 ancestorInfo.pTagInButtonScope = null;
14823 }
14824
14825 // See rules for 'li', 'dd', 'dt' start tags in
14826 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
14827 if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
14828 ancestorInfo.listItemTagAutoclosing = null;
14829 ancestorInfo.dlItemTagAutoclosing = null;
14830 }
14831
14832 ancestorInfo.current = info;
14833
14834 if (tag === 'form') {
14835 ancestorInfo.formTag = info;
14836 }
14837 if (tag === 'a') {
14838 ancestorInfo.aTagInScope = info;
14839 }
14840 if (tag === 'button') {
14841 ancestorInfo.buttonTagInScope = info;
14842 }
14843 if (tag === 'nobr') {
14844 ancestorInfo.nobrTagInScope = info;
14845 }
14846 if (tag === 'p') {
14847 ancestorInfo.pTagInButtonScope = info;
14848 }
14849 if (tag === 'li') {
14850 ancestorInfo.listItemTagAutoclosing = info;
14851 }
14852 if (tag === 'dd' || tag === 'dt') {
14853 ancestorInfo.dlItemTagAutoclosing = info;
14854 }
14855
14856 return ancestorInfo;
14857 };
14858
14859 /**
14860 * Returns whether
14861 */
14862 var isTagValidWithParent = function (tag, parentTag) {
14863 // First, let's check if we're in an unusual parsing mode...
14864 switch (parentTag) {
14865 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
14866 case 'select':
14867 return tag === 'option' || tag === 'optgroup' || tag === '#text';
14868 case 'optgroup':
14869 return tag === 'option' || tag === '#text';
14870 // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
14871 // but
14872 case 'option':
14873 return tag === '#text';
14874 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
14875 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
14876 // No special behavior since these rules fall back to "in body" mode for
14877 // all except special table nodes which cause bad parsing behavior anyway.
14878
14879 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
14880 case 'tr':
14881 return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
14882 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
14883 case 'tbody':
14884 case 'thead':
14885 case 'tfoot':
14886 return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
14887 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
14888 case 'colgroup':
14889 return tag === 'col' || tag === 'template';
14890 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
14891 case 'table':
14892 return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
14893 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
14894 case 'head':
14895 return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
14896 // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
14897 case 'html':
14898 return tag === 'head' || tag === 'body';
14899 case '#document':
14900 return tag === 'html';
14901 }
14902
14903 // Probably in the "in body" parsing mode, so we outlaw only tag combos
14904 // where the parsing rules cause implicit opens or closes to be added.
14905 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
14906 switch (tag) {
14907 case 'h1':
14908 case 'h2':
14909 case 'h3':
14910 case 'h4':
14911 case 'h5':
14912 case 'h6':
14913 return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
14914
14915 case 'rp':
14916 case 'rt':
14917 return impliedEndTags.indexOf(parentTag) === -1;
14918
14919 case 'body':
14920 case 'caption':
14921 case 'col':
14922 case 'colgroup':
14923 case 'frame':
14924 case 'head':
14925 case 'html':
14926 case 'tbody':
14927 case 'td':
14928 case 'tfoot':
14929 case 'th':
14930 case 'thead':
14931 case 'tr':
14932 // These tags are only valid with a few parents that have special child
14933 // parsing rules -- if we're down here, then none of those matched and
14934 // so we allow it only if we don't know what the parent is, as all other
14935 // cases are invalid.
14936 return parentTag == null;
14937 }
14938
14939 return true;
14940 };
14941
14942 /**
14943 * Returns whether
14944 */
14945 var findInvalidAncestorForTag = function (tag, ancestorInfo) {
14946 switch (tag) {
14947 case 'address':
14948 case 'article':
14949 case 'aside':
14950 case 'blockquote':
14951 case 'center':
14952 case 'details':
14953 case 'dialog':
14954 case 'dir':
14955 case 'div':
14956 case 'dl':
14957 case 'fieldset':
14958 case 'figcaption':
14959 case 'figure':
14960 case 'footer':
14961 case 'header':
14962 case 'hgroup':
14963 case 'main':
14964 case 'menu':
14965 case 'nav':
14966 case 'ol':
14967 case 'p':
14968 case 'section':
14969 case 'summary':
14970 case 'ul':
14971 case 'pre':
14972 case 'listing':
14973 case 'table':
14974 case 'hr':
14975 case 'xmp':
14976 case 'h1':
14977 case 'h2':
14978 case 'h3':
14979 case 'h4':
14980 case 'h5':
14981 case 'h6':
14982 return ancestorInfo.pTagInButtonScope;
14983
14984 case 'form':
14985 return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
14986
14987 case 'li':
14988 return ancestorInfo.listItemTagAutoclosing;
14989
14990 case 'dd':
14991 case 'dt':
14992 return ancestorInfo.dlItemTagAutoclosing;
14993
14994 case 'button':
14995 return ancestorInfo.buttonTagInScope;
14996
14997 case 'a':
14998 // Spec says something about storing a list of markers, but it sounds
14999 // equivalent to this check.
15000 return ancestorInfo.aTagInScope;
15001
15002 case 'nobr':
15003 return ancestorInfo.nobrTagInScope;
15004 }
15005
15006 return null;
15007 };
15008
15009 var didWarn = {};
15010
15011 validateDOMNesting = function (childTag, childText, ancestorInfo) {
15012 ancestorInfo = ancestorInfo || emptyAncestorInfo;
15013 var parentInfo = ancestorInfo.current;
15014 var parentTag = parentInfo && parentInfo.tag;
15015
15016 if (childText != null) {
15017 warning_1(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null');
15018 childTag = '#text';
15019 }
15020
15021 var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
15022 var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
15023 var invalidParentOrAncestor = invalidParent || invalidAncestor;
15024 if (!invalidParentOrAncestor) {
15025 return;
15026 }
15027
15028 var ancestorTag = invalidParentOrAncestor.tag;
15029 var addendum = getCurrentFiberStackAddendum$6();
15030
15031 var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + addendum;
15032 if (didWarn[warnKey]) {
15033 return;
15034 }
15035 didWarn[warnKey] = true;
15036
15037 var tagDisplayName = childTag;
15038 var whitespaceInfo = '';
15039 if (childTag === '#text') {
15040 if (/\S/.test(childText)) {
15041 tagDisplayName = 'Text nodes';
15042 } else {
15043 tagDisplayName = 'Whitespace text nodes';
15044 whitespaceInfo = " Make sure you don't have any extra whitespace between tags on " + 'each line of your source code.';
15045 }
15046 } else {
15047 tagDisplayName = '<' + childTag + '>';
15048 }
15049
15050 if (invalidParent) {
15051 var info = '';
15052 if (ancestorTag === 'table' && childTag === 'tr') {
15053 info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
15054 }
15055 warning_1(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>.%s%s%s', tagDisplayName, ancestorTag, whitespaceInfo, info, addendum);
15056 } else {
15057 warning_1(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>.%s', tagDisplayName, ancestorTag, addendum);
15058 }
15059 };
15060
15061 // TODO: turn this into a named export
15062 validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo$1;
15063}
15064
15065var validateDOMNesting$1 = validateDOMNesting;
15066
15067// TODO: This type is shared between the reconciler and ReactDOM, but will
15068// eventually be lifted out to the renderer.
15069
15070// TODO: direct imports like some-package/src/* are bad. Fix me.
15071var createElement = createElement$1;
15072var createTextNode = createTextNode$1;
15073var setInitialProperties = setInitialProperties$1;
15074var diffProperties = diffProperties$1;
15075var updateProperties = updateProperties$1;
15076var diffHydratedProperties = diffHydratedProperties$1;
15077var diffHydratedText = diffHydratedText$1;
15078var warnForUnmatchedText = warnForUnmatchedText$1;
15079var warnForDeletedHydratableElement = warnForDeletedHydratableElement$1;
15080var warnForDeletedHydratableText = warnForDeletedHydratableText$1;
15081var warnForInsertedHydratedElement = warnForInsertedHydratedElement$1;
15082var warnForInsertedHydratedText = warnForInsertedHydratedText$1;
15083var updatedAncestorInfo = validateDOMNesting$1.updatedAncestorInfo;
15084var precacheFiberNode = precacheFiberNode$1;
15085var updateFiberProps = updateFiberProps$1;
15086
15087
15088var SUPPRESS_HYDRATION_WARNING = void 0;
15089var topLevelUpdateWarnings = void 0;
15090var warnOnInvalidCallback = void 0;
15091var didWarnAboutUnstableCreatePortal = false;
15092
15093{
15094 SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
15095 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') {
15096 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');
15097 }
15098
15099 topLevelUpdateWarnings = function (container) {
15100 if (container._reactRootContainer && container.nodeType !== COMMENT_NODE) {
15101 var hostInstance = DOMRenderer.findHostInstanceWithNoPortals(container._reactRootContainer._internalRoot.current);
15102 if (hostInstance) {
15103 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.');
15104 }
15105 }
15106
15107 var isRootRenderedBySomeReact = !!container._reactRootContainer;
15108 var rootEl = getReactRootElementInContainer(container);
15109 var hasNonRootReactChild = !!(rootEl && getInstanceFromNode$1(rootEl));
15110
15111 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.');
15112
15113 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.');
15114 };
15115
15116 warnOnInvalidCallback = function (callback, callerName) {
15117 warning_1(callback === null || typeof callback === 'function', '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
15118 };
15119}
15120
15121injection$2.injectFiberControlledHostComponent(ReactDOMFiberComponent);
15122
15123var eventsEnabled = null;
15124var selectionInformation = null;
15125
15126function ReactBatch(root) {
15127 var expirationTime = DOMRenderer.computeUniqueAsyncExpiration();
15128 this._expirationTime = expirationTime;
15129 this._root = root;
15130 this._next = null;
15131 this._callbacks = null;
15132 this._didComplete = false;
15133 this._hasChildren = false;
15134 this._children = null;
15135 this._defer = true;
15136}
15137ReactBatch.prototype.render = function (children) {
15138 !this._defer ? invariant_1(false, 'batch.render: Cannot render a batch that already committed.') : void 0;
15139 this._hasChildren = true;
15140 this._children = children;
15141 var internalRoot = this._root._internalRoot;
15142 var expirationTime = this._expirationTime;
15143 var work = new ReactWork();
15144 DOMRenderer.updateContainerAtExpirationTime(children, internalRoot, null, expirationTime, work._onCommit);
15145 return work;
15146};
15147ReactBatch.prototype.then = function (onComplete) {
15148 if (this._didComplete) {
15149 onComplete();
15150 return;
15151 }
15152 var callbacks = this._callbacks;
15153 if (callbacks === null) {
15154 callbacks = this._callbacks = [];
15155 }
15156 callbacks.push(onComplete);
15157};
15158ReactBatch.prototype.commit = function () {
15159 var internalRoot = this._root._internalRoot;
15160 var firstBatch = internalRoot.firstBatch;
15161 !(this._defer && firstBatch !== null) ? invariant_1(false, 'batch.commit: Cannot commit a batch multiple times.') : void 0;
15162
15163 if (!this._hasChildren) {
15164 // This batch is empty. Return.
15165 this._next = null;
15166 this._defer = false;
15167 return;
15168 }
15169
15170 var expirationTime = this._expirationTime;
15171
15172 // Ensure this is the first batch in the list.
15173 if (firstBatch !== this) {
15174 // This batch is not the earliest batch. We need to move it to the front.
15175 // Update its expiration time to be the expiration time of the earliest
15176 // batch, so that we can flush it without flushing the other batches.
15177 if (this._hasChildren) {
15178 expirationTime = this._expirationTime = firstBatch._expirationTime;
15179 // Rendering this batch again ensures its children will be the final state
15180 // when we flush (updates are processed in insertion order: last
15181 // update wins).
15182 // TODO: This forces a restart. Should we print a warning?
15183 this.render(this._children);
15184 }
15185
15186 // Remove the batch from the list.
15187 var previous = null;
15188 var batch = firstBatch;
15189 while (batch !== this) {
15190 previous = batch;
15191 batch = batch._next;
15192 }
15193 !(previous !== null) ? invariant_1(false, 'batch.commit: Cannot commit a batch multiple times.') : void 0;
15194 previous._next = batch._next;
15195
15196 // Add it to the front.
15197 this._next = firstBatch;
15198 firstBatch = internalRoot.firstBatch = this;
15199 }
15200
15201 // Synchronously flush all the work up to this batch's expiration time.
15202 this._defer = false;
15203 DOMRenderer.flushRoot(internalRoot, expirationTime);
15204
15205 // Pop the batch from the list.
15206 var next = this._next;
15207 this._next = null;
15208 firstBatch = internalRoot.firstBatch = next;
15209
15210 // Append the next earliest batch's children to the update queue.
15211 if (firstBatch !== null && firstBatch._hasChildren) {
15212 firstBatch.render(firstBatch._children);
15213 }
15214};
15215ReactBatch.prototype._onComplete = function () {
15216 if (this._didComplete) {
15217 return;
15218 }
15219 this._didComplete = true;
15220 var callbacks = this._callbacks;
15221 if (callbacks === null) {
15222 return;
15223 }
15224 // TODO: Error handling.
15225 for (var i = 0; i < callbacks.length; i++) {
15226 var _callback = callbacks[i];
15227 _callback();
15228 }
15229};
15230
15231function ReactWork() {
15232 this._callbacks = null;
15233 this._didCommit = false;
15234 // TODO: Avoid need to bind by replacing callbacks in the update queue with
15235 // list of Work objects.
15236 this._onCommit = this._onCommit.bind(this);
15237}
15238ReactWork.prototype.then = function (onCommit) {
15239 if (this._didCommit) {
15240 onCommit();
15241 return;
15242 }
15243 var callbacks = this._callbacks;
15244 if (callbacks === null) {
15245 callbacks = this._callbacks = [];
15246 }
15247 callbacks.push(onCommit);
15248};
15249ReactWork.prototype._onCommit = function () {
15250 if (this._didCommit) {
15251 return;
15252 }
15253 this._didCommit = true;
15254 var callbacks = this._callbacks;
15255 if (callbacks === null) {
15256 return;
15257 }
15258 // TODO: Error handling.
15259 for (var i = 0; i < callbacks.length; i++) {
15260 var _callback2 = callbacks[i];
15261 !(typeof _callback2 === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback2) : void 0;
15262 _callback2();
15263 }
15264};
15265
15266function ReactRoot(container, isAsync, hydrate) {
15267 var root = DOMRenderer.createContainer(container, isAsync, hydrate);
15268 this._internalRoot = root;
15269}
15270ReactRoot.prototype.render = function (children, callback) {
15271 var root = this._internalRoot;
15272 var work = new ReactWork();
15273 callback = callback === undefined ? null : callback;
15274 {
15275 warnOnInvalidCallback(callback, 'render');
15276 }
15277 if (callback !== null) {
15278 work.then(callback);
15279 }
15280 DOMRenderer.updateContainer(children, root, null, work._onCommit);
15281 return work;
15282};
15283ReactRoot.prototype.unmount = function (callback) {
15284 var root = this._internalRoot;
15285 var work = new ReactWork();
15286 callback = callback === undefined ? null : callback;
15287 {
15288 warnOnInvalidCallback(callback, 'render');
15289 }
15290 if (callback !== null) {
15291 work.then(callback);
15292 }
15293 DOMRenderer.updateContainer(null, root, null, work._onCommit);
15294 return work;
15295};
15296ReactRoot.prototype.legacy_renderSubtreeIntoContainer = function (parentComponent, children, callback) {
15297 var root = this._internalRoot;
15298 var work = new ReactWork();
15299 callback = callback === undefined ? null : callback;
15300 {
15301 warnOnInvalidCallback(callback, 'render');
15302 }
15303 if (callback !== null) {
15304 work.then(callback);
15305 }
15306 DOMRenderer.updateContainer(children, root, parentComponent, work._onCommit);
15307 return work;
15308};
15309ReactRoot.prototype.createBatch = function () {
15310 var batch = new ReactBatch(this);
15311 var expirationTime = batch._expirationTime;
15312
15313 var internalRoot = this._internalRoot;
15314 var firstBatch = internalRoot.firstBatch;
15315 if (firstBatch === null) {
15316 internalRoot.firstBatch = batch;
15317 batch._next = null;
15318 } else {
15319 // Insert sorted by expiration time then insertion order
15320 var insertAfter = null;
15321 var insertBefore = firstBatch;
15322 while (insertBefore !== null && insertBefore._expirationTime <= expirationTime) {
15323 insertAfter = insertBefore;
15324 insertBefore = insertBefore._next;
15325 }
15326 batch._next = insertBefore;
15327 if (insertAfter !== null) {
15328 insertAfter._next = batch;
15329 }
15330 }
15331
15332 return batch;
15333};
15334
15335/**
15336 * True if the supplied DOM node is a valid node element.
15337 *
15338 * @param {?DOMElement} node The candidate DOM node.
15339 * @return {boolean} True if the DOM is a valid DOM node.
15340 * @internal
15341 */
15342function isValidContainer(node) {
15343 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 '));
15344}
15345
15346function getReactRootElementInContainer(container) {
15347 if (!container) {
15348 return null;
15349 }
15350
15351 if (container.nodeType === DOCUMENT_NODE) {
15352 return container.documentElement;
15353 } else {
15354 return container.firstChild;
15355 }
15356}
15357
15358function shouldHydrateDueToLegacyHeuristic(container) {
15359 var rootElement = getReactRootElementInContainer(container);
15360 return !!(rootElement && rootElement.nodeType === ELEMENT_NODE && rootElement.hasAttribute(ROOT_ATTRIBUTE_NAME));
15361}
15362
15363function shouldAutoFocusHostComponent(type, props) {
15364 switch (type) {
15365 case 'button':
15366 case 'input':
15367 case 'select':
15368 case 'textarea':
15369 return !!props.autoFocus;
15370 }
15371 return false;
15372}
15373
15374var DOMRenderer = reactReconciler({
15375 getRootHostContext: function (rootContainerInstance) {
15376 var type = void 0;
15377 var namespace = void 0;
15378 var nodeType = rootContainerInstance.nodeType;
15379 switch (nodeType) {
15380 case DOCUMENT_NODE:
15381 case DOCUMENT_FRAGMENT_NODE:
15382 {
15383 type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment';
15384 var root = rootContainerInstance.documentElement;
15385 namespace = root ? root.namespaceURI : getChildNamespace(null, '');
15386 break;
15387 }
15388 default:
15389 {
15390 var container = nodeType === COMMENT_NODE ? rootContainerInstance.parentNode : rootContainerInstance;
15391 var ownNamespace = container.namespaceURI || null;
15392 type = container.tagName;
15393 namespace = getChildNamespace(ownNamespace, type);
15394 break;
15395 }
15396 }
15397 {
15398 var validatedTag = type.toLowerCase();
15399 var _ancestorInfo = updatedAncestorInfo(null, validatedTag, null);
15400 return { namespace: namespace, ancestorInfo: _ancestorInfo };
15401 }
15402 return namespace;
15403 },
15404 getChildHostContext: function (parentHostContext, type) {
15405 {
15406 var parentHostContextDev = parentHostContext;
15407 var _namespace = getChildNamespace(parentHostContextDev.namespace, type);
15408 var _ancestorInfo2 = updatedAncestorInfo(parentHostContextDev.ancestorInfo, type, null);
15409 return { namespace: _namespace, ancestorInfo: _ancestorInfo2 };
15410 }
15411 var parentNamespace = parentHostContext;
15412 return getChildNamespace(parentNamespace, type);
15413 },
15414 getPublicInstance: function (instance) {
15415 return instance;
15416 },
15417 prepareForCommit: function () {
15418 eventsEnabled = isEnabled();
15419 selectionInformation = getSelectionInformation();
15420 setEnabled(false);
15421 },
15422 resetAfterCommit: function () {
15423 restoreSelection(selectionInformation);
15424 selectionInformation = null;
15425 setEnabled(eventsEnabled);
15426 eventsEnabled = null;
15427 },
15428 createInstance: function (type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
15429 var parentNamespace = void 0;
15430 {
15431 // TODO: take namespace into account when validating.
15432 var hostContextDev = hostContext;
15433 validateDOMNesting$1(type, null, hostContextDev.ancestorInfo);
15434 if (typeof props.children === 'string' || typeof props.children === 'number') {
15435 var string = '' + props.children;
15436 var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type, null);
15437 validateDOMNesting$1(null, string, ownAncestorInfo);
15438 }
15439 parentNamespace = hostContextDev.namespace;
15440 }
15441 var domElement = createElement(type, props, rootContainerInstance, parentNamespace);
15442 precacheFiberNode(internalInstanceHandle, domElement);
15443 updateFiberProps(domElement, props);
15444 return domElement;
15445 },
15446 appendInitialChild: function (parentInstance, child) {
15447 parentInstance.appendChild(child);
15448 },
15449 finalizeInitialChildren: function (domElement, type, props, rootContainerInstance) {
15450 setInitialProperties(domElement, type, props, rootContainerInstance);
15451 return shouldAutoFocusHostComponent(type, props);
15452 },
15453 prepareUpdate: function (domElement, type, oldProps, newProps, rootContainerInstance, hostContext) {
15454 {
15455 var hostContextDev = hostContext;
15456 if (typeof newProps.children !== typeof oldProps.children && (typeof newProps.children === 'string' || typeof newProps.children === 'number')) {
15457 var string = '' + newProps.children;
15458 var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type, null);
15459 validateDOMNesting$1(null, string, ownAncestorInfo);
15460 }
15461 }
15462 return diffProperties(domElement, type, oldProps, newProps, rootContainerInstance);
15463 },
15464 shouldSetTextContent: function (type, props) {
15465 return type === 'textarea' || typeof props.children === 'string' || typeof props.children === 'number' || typeof props.dangerouslySetInnerHTML === 'object' && props.dangerouslySetInnerHTML !== null && typeof props.dangerouslySetInnerHTML.__html === 'string';
15466 },
15467 shouldDeprioritizeSubtree: function (type, props) {
15468 return !!props.hidden;
15469 },
15470 createTextInstance: function (text, rootContainerInstance, hostContext, internalInstanceHandle) {
15471 {
15472 var hostContextDev = hostContext;
15473 validateDOMNesting$1(null, text, hostContextDev.ancestorInfo);
15474 }
15475 var textNode = createTextNode(text, rootContainerInstance);
15476 precacheFiberNode(internalInstanceHandle, textNode);
15477 return textNode;
15478 },
15479
15480
15481 now: now,
15482
15483 mutation: {
15484 commitMount: function (domElement, type, newProps, internalInstanceHandle) {
15485 // Despite the naming that might imply otherwise, this method only
15486 // fires if there is an `Update` effect scheduled during mounting.
15487 // This happens if `finalizeInitialChildren` returns `true` (which it
15488 // does to implement the `autoFocus` attribute on the client). But
15489 // there are also other cases when this might happen (such as patching
15490 // up text content during hydration mismatch). So we'll check this again.
15491 if (shouldAutoFocusHostComponent(type, newProps)) {
15492 domElement.focus();
15493 }
15494 },
15495 commitUpdate: function (domElement, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
15496 // Update the props handle so that we know which props are the ones with
15497 // with current event handlers.
15498 updateFiberProps(domElement, newProps);
15499 // Apply the diff to the DOM node.
15500 updateProperties(domElement, updatePayload, type, oldProps, newProps);
15501 },
15502 resetTextContent: function (domElement) {
15503 setTextContent(domElement, '');
15504 },
15505 commitTextUpdate: function (textInstance, oldText, newText) {
15506 textInstance.nodeValue = newText;
15507 },
15508 appendChild: function (parentInstance, child) {
15509 parentInstance.appendChild(child);
15510 },
15511 appendChildToContainer: function (container, child) {
15512 if (container.nodeType === COMMENT_NODE) {
15513 container.parentNode.insertBefore(child, container);
15514 } else {
15515 container.appendChild(child);
15516 }
15517 },
15518 insertBefore: function (parentInstance, child, beforeChild) {
15519 parentInstance.insertBefore(child, beforeChild);
15520 },
15521 insertInContainerBefore: function (container, child, beforeChild) {
15522 if (container.nodeType === COMMENT_NODE) {
15523 container.parentNode.insertBefore(child, beforeChild);
15524 } else {
15525 container.insertBefore(child, beforeChild);
15526 }
15527 },
15528 removeChild: function (parentInstance, child) {
15529 parentInstance.removeChild(child);
15530 },
15531 removeChildFromContainer: function (container, child) {
15532 if (container.nodeType === COMMENT_NODE) {
15533 container.parentNode.removeChild(child);
15534 } else {
15535 container.removeChild(child);
15536 }
15537 }
15538 },
15539
15540 hydration: {
15541 canHydrateInstance: function (instance, type, props) {
15542 if (instance.nodeType !== ELEMENT_NODE || type.toLowerCase() !== instance.nodeName.toLowerCase()) {
15543 return null;
15544 }
15545 // This has now been refined to an element node.
15546 return instance;
15547 },
15548 canHydrateTextInstance: function (instance, text) {
15549 if (text === '' || instance.nodeType !== TEXT_NODE) {
15550 // Empty strings are not parsed by HTML so there won't be a correct match here.
15551 return null;
15552 }
15553 // This has now been refined to a text node.
15554 return instance;
15555 },
15556 getNextHydratableSibling: function (instance) {
15557 var node = instance.nextSibling;
15558 // Skip non-hydratable nodes.
15559 while (node && node.nodeType !== ELEMENT_NODE && node.nodeType !== TEXT_NODE) {
15560 node = node.nextSibling;
15561 }
15562 return node;
15563 },
15564 getFirstHydratableChild: function (parentInstance) {
15565 var next = parentInstance.firstChild;
15566 // Skip non-hydratable nodes.
15567 while (next && next.nodeType !== ELEMENT_NODE && next.nodeType !== TEXT_NODE) {
15568 next = next.nextSibling;
15569 }
15570 return next;
15571 },
15572 hydrateInstance: function (instance, type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
15573 precacheFiberNode(internalInstanceHandle, instance);
15574 // TODO: Possibly defer this until the commit phase where all the events
15575 // get attached.
15576 updateFiberProps(instance, props);
15577 var parentNamespace = void 0;
15578 {
15579 var hostContextDev = hostContext;
15580 parentNamespace = hostContextDev.namespace;
15581 }
15582 return diffHydratedProperties(instance, type, props, parentNamespace, rootContainerInstance);
15583 },
15584 hydrateTextInstance: function (textInstance, text, internalInstanceHandle) {
15585 precacheFiberNode(internalInstanceHandle, textInstance);
15586 return diffHydratedText(textInstance, text);
15587 },
15588 didNotMatchHydratedContainerTextInstance: function (parentContainer, textInstance, text) {
15589 {
15590 warnForUnmatchedText(textInstance, text);
15591 }
15592 },
15593 didNotMatchHydratedTextInstance: function (parentType, parentProps, parentInstance, textInstance, text) {
15594 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15595 warnForUnmatchedText(textInstance, text);
15596 }
15597 },
15598 didNotHydrateContainerInstance: function (parentContainer, instance) {
15599 {
15600 if (instance.nodeType === 1) {
15601 warnForDeletedHydratableElement(parentContainer, instance);
15602 } else {
15603 warnForDeletedHydratableText(parentContainer, instance);
15604 }
15605 }
15606 },
15607 didNotHydrateInstance: function (parentType, parentProps, parentInstance, instance) {
15608 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15609 if (instance.nodeType === 1) {
15610 warnForDeletedHydratableElement(parentInstance, instance);
15611 } else {
15612 warnForDeletedHydratableText(parentInstance, instance);
15613 }
15614 }
15615 },
15616 didNotFindHydratableContainerInstance: function (parentContainer, type, props) {
15617 {
15618 warnForInsertedHydratedElement(parentContainer, type, props);
15619 }
15620 },
15621 didNotFindHydratableContainerTextInstance: function (parentContainer, text) {
15622 {
15623 warnForInsertedHydratedText(parentContainer, text);
15624 }
15625 },
15626 didNotFindHydratableInstance: function (parentType, parentProps, parentInstance, type, props) {
15627 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15628 warnForInsertedHydratedElement(parentInstance, type, props);
15629 }
15630 },
15631 didNotFindHydratableTextInstance: function (parentType, parentProps, parentInstance, text) {
15632 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15633 warnForInsertedHydratedText(parentInstance, text);
15634 }
15635 }
15636 },
15637
15638 scheduleDeferredCallback: rIC,
15639 cancelDeferredCallback: cIC,
15640
15641 useSyncScheduling: !enableAsyncSchedulingByDefaultInReactDOM
15642});
15643
15644injection$3.injectFiberBatchedUpdates(DOMRenderer.batchedUpdates);
15645
15646var warnedAboutHydrateAPI = false;
15647
15648function legacyCreateRootFromDOMContainer(container, forceHydrate) {
15649 var shouldHydrate = forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
15650 // First clear any existing content.
15651 if (!shouldHydrate) {
15652 var warned = false;
15653 var rootSibling = void 0;
15654 while (rootSibling = container.lastChild) {
15655 {
15656 if (!warned && rootSibling.nodeType === ELEMENT_NODE && rootSibling.hasAttribute(ROOT_ATTRIBUTE_NAME)) {
15657 warned = true;
15658 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.');
15659 }
15660 }
15661 container.removeChild(rootSibling);
15662 }
15663 }
15664 {
15665 if (shouldHydrate && !forceHydrate && !warnedAboutHydrateAPI) {
15666 warnedAboutHydrateAPI = true;
15667 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.');
15668 }
15669 }
15670 // Legacy roots are not async by default.
15671 var isAsync = false;
15672 return new ReactRoot(container, isAsync, shouldHydrate);
15673}
15674
15675function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {
15676 // TODO: Ensure all entry points contain this check
15677 !isValidContainer(container) ? invariant_1(false, 'Target container is not a DOM element.') : void 0;
15678
15679 {
15680 topLevelUpdateWarnings(container);
15681 }
15682
15683 // TODO: Without `any` type, Flow says "Property cannot be accessed on any
15684 // member of intersection type." Whyyyyyy.
15685 var root = container._reactRootContainer;
15686 if (!root) {
15687 // Initial mount
15688 root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate);
15689 if (typeof callback === 'function') {
15690 var originalCallback = callback;
15691 callback = function () {
15692 var instance = DOMRenderer.getPublicRootInstance(root._internalRoot);
15693 originalCallback.call(instance);
15694 };
15695 }
15696 // Initial mount should not be batched.
15697 DOMRenderer.unbatchedUpdates(function () {
15698 if (parentComponent != null) {
15699 root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
15700 } else {
15701 root.render(children, callback);
15702 }
15703 });
15704 } else {
15705 if (typeof callback === 'function') {
15706 var _originalCallback = callback;
15707 callback = function () {
15708 var instance = DOMRenderer.getPublicRootInstance(root._internalRoot);
15709 _originalCallback.call(instance);
15710 };
15711 }
15712 // Update
15713 if (parentComponent != null) {
15714 root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
15715 } else {
15716 root.render(children, callback);
15717 }
15718 }
15719 return DOMRenderer.getPublicRootInstance(root._internalRoot);
15720}
15721
15722function createPortal(children, container) {
15723 var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
15724
15725 !isValidContainer(container) ? invariant_1(false, 'Target container is not a DOM element.') : void 0;
15726 // TODO: pass ReactDOM portal implementation as third argument
15727 return createPortal$1(children, container, null, key);
15728}
15729
15730var ReactDOM = {
15731 createPortal: createPortal,
15732
15733 findDOMNode: function (componentOrElement) {
15734 {
15735 var owner = ReactCurrentOwner.current;
15736 if (owner !== null) {
15737 var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender;
15738 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');
15739 owner.stateNode._warnedAboutRefsInRender = true;
15740 }
15741 }
15742 if (componentOrElement == null) {
15743 return null;
15744 }
15745 if (componentOrElement.nodeType === ELEMENT_NODE) {
15746 return componentOrElement;
15747 }
15748
15749 var inst = get(componentOrElement);
15750 if (inst) {
15751 return DOMRenderer.findHostInstance(inst);
15752 }
15753
15754 if (typeof componentOrElement.render === 'function') {
15755 invariant_1(false, 'Unable to find node on an unmounted component.');
15756 } else {
15757 invariant_1(false, 'Element appears to be neither ReactComponent nor DOMNode. Keys: %s', Object.keys(componentOrElement));
15758 }
15759 },
15760 hydrate: function (element, container, callback) {
15761 // TODO: throw or warn if we couldn't hydrate?
15762 return legacyRenderSubtreeIntoContainer(null, element, container, true, callback);
15763 },
15764 render: function (element, container, callback) {
15765 return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
15766 },
15767 unstable_renderSubtreeIntoContainer: function (parentComponent, element, containerNode, callback) {
15768 !(parentComponent != null && has(parentComponent)) ? invariant_1(false, 'parentComponent must be a valid React Component') : void 0;
15769 return legacyRenderSubtreeIntoContainer(parentComponent, element, containerNode, false, callback);
15770 },
15771 unmountComponentAtNode: function (container) {
15772 !isValidContainer(container) ? invariant_1(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : void 0;
15773
15774 if (container._reactRootContainer) {
15775 {
15776 var rootEl = getReactRootElementInContainer(container);
15777 var renderedByDifferentReact = rootEl && !getInstanceFromNode$1(rootEl);
15778 warning_1(!renderedByDifferentReact, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.');
15779 }
15780
15781 // Unmount should not be batched.
15782 DOMRenderer.unbatchedUpdates(function () {
15783 legacyRenderSubtreeIntoContainer(null, null, container, false, function () {
15784 container._reactRootContainer = null;
15785 });
15786 });
15787 // If you call unmountComponentAtNode twice in quick succession, you'll
15788 // get `true` twice. That's probably fine?
15789 return true;
15790 } else {
15791 {
15792 var _rootEl = getReactRootElementInContainer(container);
15793 var hasNonRootReactChild = !!(_rootEl && getInstanceFromNode$1(_rootEl));
15794
15795 // Check if the container itself is a React root node.
15796 var isContainerReactRoot = container.nodeType === 1 && isValidContainer(container.parentNode) && !!container.parentNode._reactRootContainer;
15797
15798 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.');
15799 }
15800
15801 return false;
15802 }
15803 },
15804
15805
15806 // Temporary alias since we already shipped React 16 RC with it.
15807 // TODO: remove in React 17.
15808 unstable_createPortal: function () {
15809 if (!didWarnAboutUnstableCreatePortal) {
15810 didWarnAboutUnstableCreatePortal = true;
15811 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.');
15812 }
15813 return createPortal.apply(undefined, arguments);
15814 },
15815
15816
15817 unstable_batchedUpdates: batchedUpdates,
15818
15819 unstable_deferredUpdates: DOMRenderer.deferredUpdates,
15820
15821 flushSync: DOMRenderer.flushSync,
15822
15823 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
15824 // For TapEventPlugin which is popular in open source
15825 EventPluginHub: EventPluginHub,
15826 // Used by test-utils
15827 EventPluginRegistry: EventPluginRegistry,
15828 EventPropagators: EventPropagators,
15829 ReactControlledComponent: ReactControlledComponent,
15830 ReactDOMComponentTree: ReactDOMComponentTree,
15831 ReactDOMEventListener: ReactDOMEventListener
15832 }
15833};
15834
15835{
15836 // Show deprecation warnings as we don't want to support injection forever.
15837 // We do it now to let the internal injection happen without warnings.
15838 // https://github.com/facebook/react/issues/11689
15839 enableWarningOnInjection();
15840}
15841
15842if (enableCreateRoot) {
15843 ReactDOM.createRoot = function createRoot(container, options) {
15844 var hydrate = options != null && options.hydrate === true;
15845 return new ReactRoot(container, true, hydrate);
15846 };
15847}
15848
15849var foundDevTools = DOMRenderer.injectIntoDevTools({
15850 findFiberByHostInstance: getClosestInstanceFromNode,
15851 bundleType: 1,
15852 version: ReactVersion,
15853 rendererPackageName: 'react-dom'
15854});
15855
15856{
15857 if (!foundDevTools && ExecutionEnvironment_1.canUseDOM && window.top === window.self) {
15858 // If we're in Chrome or Firefox, provide a download link if not installed.
15859 if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
15860 var protocol = window.location.protocol;
15861 // Don't warn in exotic cases like chrome-extension://.
15862 if (/^(https?|file):$/.test(protocol)) {
15863 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');
15864 }
15865 }
15866 }
15867}
15868
15869
15870
15871var ReactDOM$2 = Object.freeze({
15872 default: ReactDOM
15873});
15874
15875var ReactDOM$3 = ( ReactDOM$2 && ReactDOM ) || ReactDOM$2;
15876
15877// TODO: decide on the top-level export form.
15878// This is hacky but makes it work with both Rollup and Jest.
15879var reactDom = ReactDOM$3['default'] ? ReactDOM$3['default'] : ReactDOM$3;
15880
15881return reactDom;
15882
15883})));