· 8 years ago · Jan 12, 2018, 07:58 AM
1/** @license React v16.2.0
2 * react-dom.development.js
3 *
4 * Copyright (c) 2013-present, Facebook, Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE file in the root directory of this source tree.
8 */
9
10'use strict';
11
12(function (global, factory) {
13 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
14 typeof define === 'function' && define.amd ? define(['react'], factory) :
15 (global.ReactDOM = factory(global.React));
16}(this, (function (React) { 'use strict';
17
18/**
19 * WARNING: DO NOT manually require this module.
20 * This is a replacement for `invariant(...)` used by the error code system
21 * and will _only_ be required by the corresponding babel pass.
22 * It always throws.
23 */
24
25/**
26 * Copyright (c) 2013-present, Facebook, Inc.
27 *
28 * This source code is licensed under the MIT license found in the
29 * LICENSE file in the root directory of this source tree.
30 *
31 */
32
33
34
35/**
36 * Use invariant() to assert state which your program assumes to be true.
37 *
38 * Provide sprintf-style format (only %s is supported) and arguments
39 * to provide information about what broke and what you were
40 * expecting.
41 *
42 * The invariant message will be stripped in production, but the invariant
43 * will remain to ensure logic does not differ in production.
44 */
45
46var validateFormat = function validateFormat(format) {};
47
48{
49 validateFormat = function validateFormat(format) {
50 if (format === undefined) {
51 throw new Error('invariant requires an error message argument');
52 }
53 };
54}
55
56function invariant(condition, format, a, b, c, d, e, f) {
57 validateFormat(format);
58
59 if (!condition) {
60 var error;
61 if (format === undefined) {
62 error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
63 } else {
64 var args = [a, b, c, d, e, f];
65 var argIndex = 0;
66 error = new Error(format.replace(/%s/g, function () {
67 return args[argIndex++];
68 }));
69 error.name = 'Invariant Violation';
70 }
71
72 error.framesToPop = 1; // we don't care about invariant's own frame
73 throw error;
74 }
75}
76
77var invariant_1 = invariant;
78
79!React ? invariant_1(false, 'ReactDOM was loaded before React. Make sure you load the React package before loading ReactDOM.') : void 0;
80
81var invokeGuardedCallback = function (name, func, context, a, b, c, d, e, f) {
82 this._hasCaughtError = false;
83 this._caughtError = null;
84 var funcArgs = Array.prototype.slice.call(arguments, 3);
85 try {
86 func.apply(context, funcArgs);
87 } catch (error) {
88 this._caughtError = error;
89 this._hasCaughtError = true;
90 }
91};
92
93{
94 // In DEV mode, we swap out invokeGuardedCallback for a special version
95 // that plays more nicely with the browser's DevTools. The idea is to preserve
96 // "Pause on exceptions" behavior. Because React wraps all user-provided
97 // functions in invokeGuardedCallback, and the production version of
98 // invokeGuardedCallback uses a try-catch, all user exceptions are treated
99 // like caught exceptions, and the DevTools won't pause unless the developer
100 // takes the extra step of enabling pause on caught exceptions. This is
101 // untintuitive, though, because even though React has caught the error, from
102 // the developer's perspective, the error is uncaught.
103 //
104 // To preserve the expected "Pause on exceptions" behavior, we don't use a
105 // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake
106 // DOM node, and call the user-provided callback from inside an event handler
107 // for that fake event. If the callback throws, the error is "captured" using
108 // a global event handler. But because the error happens in a different
109 // event loop context, it does not interrupt the normal program flow.
110 // Effectively, this gives us try-catch behavior without actually using
111 // try-catch. Neat!
112
113 // Check that the browser supports the APIs we need to implement our special
114 // DEV version of invokeGuardedCallback
115 if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {
116 var fakeNode = document.createElement('react');
117
118 var invokeGuardedCallbackDev = function (name, func, context, a, b, c, d, e, f) {
119 // If document doesn't exist we know for sure we will crash in this method
120 // when we call document.createEvent(). However this can cause confusing
121 // errors: https://github.com/facebookincubator/create-react-app/issues/3482
122 // So we preemptively throw with a better message instead.
123 !(typeof document !== 'undefined') ? invariant_1(false, 'The `document` global was defined when React was initialized, but is not defined anymore. This can happen in a test environment if a component schedules an update from an asynchronous callback, but the test has already finished running. To solve this, you can either unmount the component at the end of your test (and ensure that any asynchronous operations get canceled in `componentWillUnmount`), or you can change the test itself to be asynchronous.') : void 0;
124 var evt = document.createEvent('Event');
125
126 // Keeps track of whether the user-provided callback threw an error. We
127 // set this to true at the beginning, then set it to false right after
128 // calling the function. If the function errors, `didError` will never be
129 // set to false. This strategy works even if the browser is flaky and
130 // fails to call our global error handler, because it doesn't rely on
131 // the error event at all.
132 var didError = true;
133
134 // Create an event handler for our fake event. We will synchronously
135 // dispatch our fake event using `dispatchEvent`. Inside the handler, we
136 // call the user-provided callback.
137 var funcArgs = Array.prototype.slice.call(arguments, 3);
138 function callCallback() {
139 // We immediately remove the callback from event listeners so that
140 // nested `invokeGuardedCallback` calls do not clash. Otherwise, a
141 // nested call would trigger the fake event handlers of any call higher
142 // in the stack.
143 fakeNode.removeEventListener(evtType, callCallback, false);
144 func.apply(context, funcArgs);
145 didError = false;
146 }
147
148 // Create a global error event handler. We use this to capture the value
149 // that was thrown. It's possible that this error handler will fire more
150 // than once; for example, if non-React code also calls `dispatchEvent`
151 // and a handler for that event throws. We should be resilient to most of
152 // those cases. Even if our error event handler fires more than once, the
153 // last error event is always used. If the callback actually does error,
154 // we know that the last error event is the correct one, because it's not
155 // possible for anything else to have happened in between our callback
156 // erroring and the code that follows the `dispatchEvent` call below. If
157 // the callback doesn't error, but the error event was fired, we know to
158 // ignore it because `didError` will be false, as described above.
159 var error = void 0;
160 // Use this to track whether the error event is ever called.
161 var didSetError = false;
162 var isCrossOriginError = false;
163
164 function onError(event) {
165 error = event.error;
166 didSetError = true;
167 if (error === null && event.colno === 0 && event.lineno === 0) {
168 isCrossOriginError = true;
169 }
170 }
171
172 // Create a fake event type.
173 var evtType = 'react-' + (name ? name : 'invokeguardedcallback');
174
175 // Attach our event handlers
176 window.addEventListener('error', onError);
177 fakeNode.addEventListener(evtType, callCallback, false);
178
179 // Synchronously dispatch our fake event. If the user-provided function
180 // errors, it will trigger our global error handler.
181 evt.initEvent(evtType, false, false);
182 fakeNode.dispatchEvent(evt);
183
184 if (didError) {
185 if (!didSetError) {
186 // The callback errored, but the error event never fired.
187 error = new Error('An error was thrown inside one of your components, but React ' + "doesn't know what it was. This is likely due to browser " + 'flakiness. React does its best to preserve the "Pause on ' + 'exceptions" behavior of the DevTools, which requires some ' + "DEV-mode only tricks. It's possible that these don't work in " + 'your browser. Try triggering the error in production mode, ' + 'or switching to a modern browser. If you suspect that this is ' + 'actually an issue with React, please file an issue.');
188 } else if (isCrossOriginError) {
189 error = new Error("A cross-origin error was thrown. React doesn't have access to " + 'the actual error object in development. ' + 'See https://fb.me/react-crossorigin-error for more information.');
190 }
191 this._hasCaughtError = true;
192 this._caughtError = error;
193 } else {
194 this._hasCaughtError = false;
195 this._caughtError = null;
196 }
197
198 // Remove our event listeners
199 window.removeEventListener('error', onError);
200 };
201
202 invokeGuardedCallback = invokeGuardedCallbackDev;
203 }
204}
205
206var invokeGuardedCallback$1 = invokeGuardedCallback;
207
208var ReactErrorUtils = {
209 // Used by Fiber to simulate a try-catch.
210 _caughtError: null,
211 _hasCaughtError: false,
212
213 // Used by event system to capture/rethrow the first error.
214 _rethrowError: null,
215 _hasRethrowError: false,
216
217 /**
218 * Call a function while guarding against errors that happens within it.
219 * Returns an error if it throws, otherwise null.
220 *
221 * In production, this is implemented using a try-catch. The reason we don't
222 * use a try-catch directly is so that we can swap out a different
223 * implementation in DEV mode.
224 *
225 * @param {String} name of the guard to use for logging or debugging
226 * @param {Function} func The function to invoke
227 * @param {*} context The context to use when calling the function
228 * @param {...*} args Arguments for function
229 */
230 invokeGuardedCallback: function (name, func, context, a, b, c, d, e, f) {
231 invokeGuardedCallback$1.apply(ReactErrorUtils, arguments);
232 },
233
234 /**
235 * Same as invokeGuardedCallback, but instead of returning an error, it stores
236 * it in a global so it can be rethrown by `rethrowCaughtError` later.
237 * TODO: See if _caughtError and _rethrowError can be unified.
238 *
239 * @param {String} name of the guard to use for logging or debugging
240 * @param {Function} func The function to invoke
241 * @param {*} context The context to use when calling the function
242 * @param {...*} args Arguments for function
243 */
244 invokeGuardedCallbackAndCatchFirstError: function (name, func, context, a, b, c, d, e, f) {
245 ReactErrorUtils.invokeGuardedCallback.apply(this, arguments);
246 if (ReactErrorUtils.hasCaughtError()) {
247 var error = ReactErrorUtils.clearCaughtError();
248 if (!ReactErrorUtils._hasRethrowError) {
249 ReactErrorUtils._hasRethrowError = true;
250 ReactErrorUtils._rethrowError = error;
251 }
252 }
253 },
254
255 /**
256 * During execution of guarded functions we will capture the first error which
257 * we will rethrow to be handled by the top level error handler.
258 */
259 rethrowCaughtError: function () {
260 return rethrowCaughtError.apply(ReactErrorUtils, arguments);
261 },
262
263 hasCaughtError: function () {
264 return ReactErrorUtils._hasCaughtError;
265 },
266
267 clearCaughtError: function () {
268 if (ReactErrorUtils._hasCaughtError) {
269 var error = ReactErrorUtils._caughtError;
270 ReactErrorUtils._caughtError = null;
271 ReactErrorUtils._hasCaughtError = false;
272 return error;
273 } else {
274 invariant_1(false, 'clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue.');
275 }
276 }
277};
278
279var rethrowCaughtError = function () {
280 if (ReactErrorUtils._hasRethrowError) {
281 var error = ReactErrorUtils._rethrowError;
282 ReactErrorUtils._rethrowError = null;
283 ReactErrorUtils._hasRethrowError = false;
284 throw error;
285 }
286};
287
288/**
289 * Forked from fbjs/warning:
290 * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js
291 *
292 * Only change is we use console.warn instead of console.error,
293 * and do nothing when 'console' is not supported.
294 * This really simplifies the code.
295 * ---
296 * Similar to invariant but only logs a warning if the condition is not met.
297 * This can be used to log issues in development environments in critical
298 * paths. Removing the logging code for production environments will keep the
299 * same logic and follow the same code paths.
300 */
301
302var lowPriorityWarning = function () {};
303
304{
305 var printWarning = function (format) {
306 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
307 args[_key - 1] = arguments[_key];
308 }
309
310 var argIndex = 0;
311 var message = 'Warning: ' + format.replace(/%s/g, function () {
312 return args[argIndex++];
313 });
314 if (typeof console !== 'undefined') {
315 console.warn(message);
316 }
317 try {
318 // --- Welcome to debugging React ---
319 // This error was thrown as a convenience so that you can use this stack
320 // to find the callsite that caused this warning to fire.
321 throw new Error(message);
322 } catch (x) {}
323 };
324
325 lowPriorityWarning = function (condition, format) {
326 if (format === undefined) {
327 throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
328 }
329 if (!condition) {
330 for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
331 args[_key2 - 2] = arguments[_key2];
332 }
333
334 printWarning.apply(undefined, [format].concat(args));
335 }
336 };
337}
338
339var lowPriorityWarning$1 = lowPriorityWarning;
340
341var shouldWarnOnInjection = false;
342
343/**
344 * Injectable ordering of event plugins.
345 */
346var eventPluginOrder = null;
347
348/**
349 * Injectable mapping from names to event plugin modules.
350 */
351var namesToPlugins = {};
352
353function enableWarningOnInjection() {
354 shouldWarnOnInjection = true;
355}
356
357/**
358 * Recomputes the plugin list using the injected plugins and plugin ordering.
359 *
360 * @private
361 */
362function recomputePluginOrdering() {
363 if (!eventPluginOrder) {
364 // Wait until an `eventPluginOrder` is injected.
365 return;
366 }
367 for (var pluginName in namesToPlugins) {
368 var pluginModule = namesToPlugins[pluginName];
369 var pluginIndex = eventPluginOrder.indexOf(pluginName);
370 !(pluginIndex > -1) ? invariant_1(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : void 0;
371 if (plugins[pluginIndex]) {
372 continue;
373 }
374 !pluginModule.extractEvents ? invariant_1(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : void 0;
375 plugins[pluginIndex] = pluginModule;
376 var publishedEvents = pluginModule.eventTypes;
377 for (var eventName in publishedEvents) {
378 !publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) ? invariant_1(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : void 0;
379 }
380 }
381}
382
383/**
384 * Publishes an event so that it can be dispatched by the supplied plugin.
385 *
386 * @param {object} dispatchConfig Dispatch configuration for the event.
387 * @param {object} PluginModule Plugin publishing the event.
388 * @return {boolean} True if the event was successfully published.
389 * @private
390 */
391function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
392 !!eventNameDispatchConfigs.hasOwnProperty(eventName) ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : void 0;
393 eventNameDispatchConfigs[eventName] = dispatchConfig;
394
395 var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
396 if (phasedRegistrationNames) {
397 for (var phaseName in phasedRegistrationNames) {
398 if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
399 var phasedRegistrationName = phasedRegistrationNames[phaseName];
400 publishRegistrationName(phasedRegistrationName, pluginModule, eventName);
401 }
402 }
403 return true;
404 } else if (dispatchConfig.registrationName) {
405 publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName);
406 return true;
407 }
408 return false;
409}
410
411/**
412 * Publishes a registration name that is used to identify dispatched events.
413 *
414 * @param {string} registrationName Registration name to add.
415 * @param {object} PluginModule Plugin publishing the event.
416 * @private
417 */
418function publishRegistrationName(registrationName, pluginModule, eventName) {
419 !!registrationNameModules[registrationName] ? invariant_1(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : void 0;
420 registrationNameModules[registrationName] = pluginModule;
421 registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies;
422
423 {
424 var lowerCasedName = registrationName.toLowerCase();
425 possibleRegistrationNames[lowerCasedName] = registrationName;
426
427 if (registrationName === 'onDoubleClick') {
428 possibleRegistrationNames.ondblclick = registrationName;
429 }
430 }
431}
432
433/**
434 * Registers plugins so that they can extract and dispatch events.
435 *
436 * @see {EventPluginHub}
437 */
438
439/**
440 * Ordered list of injected plugins.
441 */
442var plugins = [];
443
444/**
445 * Mapping from event name to dispatch config
446 */
447var eventNameDispatchConfigs = {};
448
449/**
450 * Mapping from registration name to plugin module
451 */
452var registrationNameModules = {};
453
454/**
455 * Mapping from registration name to event name
456 */
457var registrationNameDependencies = {};
458
459/**
460 * Mapping from lowercase registration names to the properly cased version,
461 * used to warn in the case of missing event handlers. Available
462 * only in true.
463 * @type {Object}
464 */
465var possibleRegistrationNames = {};
466// Trust the developer to only use possibleRegistrationNames in true
467
468/**
469 * Injects an ordering of plugins (by plugin name). This allows the ordering
470 * to be decoupled from injection of the actual plugins so that ordering is
471 * always deterministic regardless of packaging, on-the-fly injection, etc.
472 *
473 * @param {array} InjectedEventPluginOrder
474 * @internal
475 * @see {EventPluginHub.injection.injectEventPluginOrder}
476 */
477function injectEventPluginOrder(injectedEventPluginOrder) {
478 !!eventPluginOrder ? invariant_1(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : void 0;
479 // Clone the ordering so it cannot be dynamically mutated.
480 eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder);
481 recomputePluginOrdering();
482}
483
484/**
485 * Injects plugins to be used by `EventPluginHub`. The plugin names must be
486 * in the ordering injected by `injectEventPluginOrder`.
487 *
488 * Plugins can be injected as part of page initialization or on-the-fly.
489 *
490 * @param {object} injectedNamesToPlugins Map from names to plugin modules.
491 * @internal
492 * @see {EventPluginHub.injection.injectEventPluginsByName}
493 */
494function injectEventPluginsByName(injectedNamesToPlugins) {
495 {
496 if (shouldWarnOnInjection) {
497 var names = Object.keys(injectedNamesToPlugins).join(', ');
498 lowPriorityWarning$1(false, 'Injecting custom event plugins (%s) is deprecated ' + 'and will not work in React 17+. Please update your code ' + 'to not depend on React internals. The stack trace for this ' + 'warning should reveal the library that is using them. ' + 'See https://github.com/facebook/react/issues/11689 for a discussion.', names);
499 }
500 }
501
502 var isOrderingDirty = false;
503 for (var pluginName in injectedNamesToPlugins) {
504 if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
505 continue;
506 }
507 var pluginModule = injectedNamesToPlugins[pluginName];
508 if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) {
509 !!namesToPlugins[pluginName] ? invariant_1(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : void 0;
510 namesToPlugins[pluginName] = pluginModule;
511 isOrderingDirty = true;
512 }
513 }
514 if (isOrderingDirty) {
515 recomputePluginOrdering();
516 }
517}
518
519var EventPluginRegistry = Object.freeze({
520 enableWarningOnInjection: enableWarningOnInjection,
521 plugins: plugins,
522 eventNameDispatchConfigs: eventNameDispatchConfigs,
523 registrationNameModules: registrationNameModules,
524 registrationNameDependencies: registrationNameDependencies,
525 possibleRegistrationNames: possibleRegistrationNames,
526 injectEventPluginOrder: injectEventPluginOrder,
527 injectEventPluginsByName: injectEventPluginsByName
528});
529
530/**
531 * Copyright (c) 2013-present, Facebook, Inc.
532 *
533 * This source code is licensed under the MIT license found in the
534 * LICENSE file in the root directory of this source tree.
535 *
536 *
537 */
538
539function makeEmptyFunction(arg) {
540 return function () {
541 return arg;
542 };
543}
544
545/**
546 * This function accepts and discards inputs; it has no side effects. This is
547 * primarily useful idiomatically for overridable function endpoints which
548 * always need to be callable, since JS lacks a null-call idiom ala Cocoa.
549 */
550var emptyFunction = function emptyFunction() {};
551
552emptyFunction.thatReturns = makeEmptyFunction;
553emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
554emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
555emptyFunction.thatReturnsNull = makeEmptyFunction(null);
556emptyFunction.thatReturnsThis = function () {
557 return this;
558};
559emptyFunction.thatReturnsArgument = function (arg) {
560 return arg;
561};
562
563var emptyFunction_1 = emptyFunction;
564
565/**
566 * Copyright (c) 2014-present, Facebook, Inc.
567 *
568 * This source code is licensed under the MIT license found in the
569 * LICENSE file in the root directory of this source tree.
570 *
571 */
572
573
574
575
576
577/**
578 * Similar to invariant but only logs a warning if the condition is not met.
579 * This can be used to log issues in development environments in critical
580 * paths. Removing the logging code for production environments will keep the
581 * same logic and follow the same code paths.
582 */
583
584var warning = emptyFunction_1;
585
586{
587 var printWarning$1 = function printWarning(format) {
588 for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
589 args[_key - 1] = arguments[_key];
590 }
591
592 var argIndex = 0;
593 var message = 'Warning: ' + format.replace(/%s/g, function () {
594 return args[argIndex++];
595 });
596 if (typeof console !== 'undefined') {
597 console.error(message);
598 }
599 try {
600 // --- Welcome to debugging React ---
601 // This error was thrown as a convenience so that you can use this stack
602 // to find the callsite that caused this warning to fire.
603 throw new Error(message);
604 } catch (x) {}
605 };
606
607 warning = function warning(condition, format) {
608 if (format === undefined) {
609 throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
610 }
611
612 if (format.indexOf('Failed Composite propType: ') === 0) {
613 return; // Ignore CompositeComponent proptype check.
614 }
615
616 if (!condition) {
617 for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
618 args[_key2 - 2] = arguments[_key2];
619 }
620
621 printWarning$1.apply(undefined, [format].concat(args));
622 }
623 };
624}
625
626var warning_1 = warning;
627
628var getFiberCurrentPropsFromNode = null;
629var getInstanceFromNode = null;
630var getNodeFromInstance = null;
631
632var injection$1 = {
633 injectComponentTree: function (Injected) {
634 getFiberCurrentPropsFromNode = Injected.getFiberCurrentPropsFromNode;
635 getInstanceFromNode = Injected.getInstanceFromNode;
636 getNodeFromInstance = Injected.getNodeFromInstance;
637
638 {
639 warning_1(getNodeFromInstance && getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.');
640 }
641 }
642};
643
644
645
646
647
648
649var validateEventDispatches = void 0;
650{
651 validateEventDispatches = function (event) {
652 var dispatchListeners = event._dispatchListeners;
653 var dispatchInstances = event._dispatchInstances;
654
655 var listenersIsArr = Array.isArray(dispatchListeners);
656 var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
657
658 var instancesIsArr = Array.isArray(dispatchInstances);
659 var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
660
661 warning_1(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.');
662 };
663}
664
665/**
666 * Dispatch the event to the listener.
667 * @param {SyntheticEvent} event SyntheticEvent to handle
668 * @param {boolean} simulated If the event is simulated (changes exn behavior)
669 * @param {function} listener Application-level callback
670 * @param {*} inst Internal component instance
671 */
672function executeDispatch(event, simulated, listener, inst) {
673 var type = event.type || 'unknown-event';
674 event.currentTarget = getNodeFromInstance(inst);
675 ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event);
676 event.currentTarget = null;
677}
678
679/**
680 * Standard/simple iteration through an event's collected dispatches.
681 */
682function executeDispatchesInOrder(event, simulated) {
683 var dispatchListeners = event._dispatchListeners;
684 var dispatchInstances = event._dispatchInstances;
685 {
686 validateEventDispatches(event);
687 }
688 if (Array.isArray(dispatchListeners)) {
689 for (var i = 0; i < dispatchListeners.length; i++) {
690 if (event.isPropagationStopped()) {
691 break;
692 }
693 // Listeners and Instances are two parallel arrays that are always in sync.
694 executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);
695 }
696 } else if (dispatchListeners) {
697 executeDispatch(event, simulated, dispatchListeners, dispatchInstances);
698 }
699 event._dispatchListeners = null;
700 event._dispatchInstances = null;
701}
702
703/**
704 * @see executeDispatchesInOrderStopAtTrueImpl
705 */
706
707
708/**
709 * Execution of a "direct" dispatch - there must be at most one dispatch
710 * accumulated on the event or it is considered an error. It doesn't really make
711 * sense for an event with multiple dispatches (bubbled) to keep track of the
712 * return values at each dispatch execution, but it does tend to make sense when
713 * dealing with "direct" dispatches.
714 *
715 * @return {*} The return value of executing the single dispatch.
716 */
717
718
719/**
720 * @param {SyntheticEvent} event
721 * @return {boolean} True iff number of dispatches accumulated is greater than 0.
722 */
723
724/**
725 * Accumulates items that must not be null or undefined into the first one. This
726 * is used to conserve memory by avoiding array allocations, and thus sacrifices
727 * API cleanness. Since `current` can be null before being passed in and not
728 * null after this function, make sure to assign it back to `current`:
729 *
730 * `a = accumulateInto(a, b);`
731 *
732 * This API should be sparingly used. Try `accumulate` for something cleaner.
733 *
734 * @return {*|array<*>} An accumulation of items.
735 */
736
737function accumulateInto(current, next) {
738 !(next != null) ? invariant_1(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : void 0;
739
740 if (current == null) {
741 return next;
742 }
743
744 // Both are not empty. Warning: Never call x.concat(y) when you are not
745 // certain that x is an Array (x could be a string with concat method).
746 if (Array.isArray(current)) {
747 if (Array.isArray(next)) {
748 current.push.apply(current, next);
749 return current;
750 }
751 current.push(next);
752 return current;
753 }
754
755 if (Array.isArray(next)) {
756 // A bit too dangerous to mutate `next`.
757 return [current].concat(next);
758 }
759
760 return [current, next];
761}
762
763/**
764 * @param {array} arr an "accumulation" of items which is either an Array or
765 * a single item. Useful when paired with the `accumulate` module. This is a
766 * simple utility that allows us to reason about a collection of items, but
767 * handling the case when there is exactly one item (and we do not need to
768 * allocate an array).
769 * @param {function} cb Callback invoked with each element or a collection.
770 * @param {?} [scope] Scope used as `this` in a callback.
771 */
772function forEachAccumulated(arr, cb, scope) {
773 if (Array.isArray(arr)) {
774 arr.forEach(cb, scope);
775 } else if (arr) {
776 cb.call(scope, arr);
777 }
778}
779
780/**
781 * Internal queue of events that have accumulated their dispatches and are
782 * waiting to have their dispatches executed.
783 */
784var eventQueue = null;
785
786/**
787 * Dispatches an event and releases it back into the pool, unless persistent.
788 *
789 * @param {?object} event Synthetic event to be dispatched.
790 * @param {boolean} simulated If the event is simulated (changes exn behavior)
791 * @private
792 */
793var executeDispatchesAndRelease = function (event, simulated) {
794 if (event) {
795 executeDispatchesInOrder(event, simulated);
796
797 if (!event.isPersistent()) {
798 event.constructor.release(event);
799 }
800 }
801};
802var executeDispatchesAndReleaseSimulated = function (e) {
803 return executeDispatchesAndRelease(e, true);
804};
805var executeDispatchesAndReleaseTopLevel = function (e) {
806 return executeDispatchesAndRelease(e, false);
807};
808
809function isInteractive(tag) {
810 return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
811}
812
813function shouldPreventMouseEvent(name, type, props) {
814 switch (name) {
815 case 'onClick':
816 case 'onClickCapture':
817 case 'onDoubleClick':
818 case 'onDoubleClickCapture':
819 case 'onMouseDown':
820 case 'onMouseDownCapture':
821 case 'onMouseMove':
822 case 'onMouseMoveCapture':
823 case 'onMouseUp':
824 case 'onMouseUpCapture':
825 return !!(props.disabled && isInteractive(type));
826 default:
827 return false;
828 }
829}
830
831/**
832 * This is a unified interface for event plugins to be installed and configured.
833 *
834 * Event plugins can implement the following properties:
835 *
836 * `extractEvents` {function(string, DOMEventTarget, string, object): *}
837 * Required. When a top-level event is fired, this method is expected to
838 * extract synthetic events that will in turn be queued and dispatched.
839 *
840 * `eventTypes` {object}
841 * Optional, plugins that fire events must publish a mapping of registration
842 * names that are used to register listeners. Values of this mapping must
843 * be objects that contain `registrationName` or `phasedRegistrationNames`.
844 *
845 * `executeDispatch` {function(object, function, string)}
846 * Optional, allows plugins to override how an event gets dispatched. By
847 * default, the listener is simply invoked.
848 *
849 * Each plugin that is injected into `EventsPluginHub` is immediately operable.
850 *
851 * @public
852 */
853
854/**
855 * Methods for injecting dependencies.
856 */
857var injection = {
858 /**
859 * @param {array} InjectedEventPluginOrder
860 * @public
861 */
862 injectEventPluginOrder: injectEventPluginOrder,
863
864 /**
865 * @param {object} injectedNamesToPlugins Map from names to plugin modules.
866 */
867 injectEventPluginsByName: injectEventPluginsByName
868};
869
870/**
871 * @param {object} inst The instance, which is the source of events.
872 * @param {string} registrationName Name of listener (e.g. `onClick`).
873 * @return {?function} The stored callback.
874 */
875function getListener(inst, registrationName) {
876 var listener = void 0;
877
878 // TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
879 // live here; needs to be moved to a better place soon
880 var stateNode = inst.stateNode;
881 if (!stateNode) {
882 // Work in progress (ex: onload events in incremental mode).
883 return null;
884 }
885 var props = getFiberCurrentPropsFromNode(stateNode);
886 if (!props) {
887 // Work in progress.
888 return null;
889 }
890 listener = props[registrationName];
891 if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
892 return null;
893 }
894 !(!listener || typeof listener === 'function') ? invariant_1(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener) : void 0;
895 return listener;
896}
897
898/**
899 * Allows registered plugins an opportunity to extract events from top-level
900 * native browser events.
901 *
902 * @return {*} An accumulation of synthetic events.
903 * @internal
904 */
905function extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
906 var events = 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' or audio/video events which don't consistently
4312 * bubble (which we trap at a lower node than `document`), binding
4313 * at `document` would cause duplicate events so we don't include them here.
4314 */
4315var topLevelTypes = {
4316 topAnimationEnd: getVendorPrefixedEventName('animationend'),
4317 topAnimationIteration: getVendorPrefixedEventName('animationiteration'),
4318 topAnimationStart: getVendorPrefixedEventName('animationstart'),
4319 topBlur: 'blur',
4320 topCancel: 'cancel',
4321 topChange: 'change',
4322 topClick: 'click',
4323 topClose: 'close',
4324 topCompositionEnd: 'compositionend',
4325 topCompositionStart: 'compositionstart',
4326 topCompositionUpdate: 'compositionupdate',
4327 topContextMenu: 'contextmenu',
4328 topCopy: 'copy',
4329 topCut: 'cut',
4330 topDoubleClick: 'dblclick',
4331 topDrag: 'drag',
4332 topDragEnd: 'dragend',
4333 topDragEnter: 'dragenter',
4334 topDragExit: 'dragexit',
4335 topDragLeave: 'dragleave',
4336 topDragOver: 'dragover',
4337 topDragStart: 'dragstart',
4338 topDrop: 'drop',
4339 topFocus: 'focus',
4340 topInput: 'input',
4341 topKeyDown: 'keydown',
4342 topKeyPress: 'keypress',
4343 topKeyUp: 'keyup',
4344 topLoad: 'load',
4345 topLoadStart: 'loadstart',
4346 topMouseDown: 'mousedown',
4347 topMouseMove: 'mousemove',
4348 topMouseOut: 'mouseout',
4349 topMouseOver: 'mouseover',
4350 topMouseUp: 'mouseup',
4351 topPaste: 'paste',
4352 topScroll: 'scroll',
4353 topSelectionChange: 'selectionchange',
4354 topTextInput: 'textInput',
4355 topToggle: 'toggle',
4356 topTouchCancel: 'touchcancel',
4357 topTouchEnd: 'touchend',
4358 topTouchMove: 'touchmove',
4359 topTouchStart: 'touchstart',
4360 topTransitionEnd: getVendorPrefixedEventName('transitionend'),
4361 topWheel: 'wheel'
4362};
4363
4364// There are so many media events, it makes sense to just
4365// maintain a list of them. Note these aren't technically
4366// "top-level" since they don't bubble. We should come up
4367// with a better naming convention if we come to refactoring
4368// the event system.
4369var mediaEventTypes = {
4370 topAbort: 'abort',
4371 topCanPlay: 'canplay',
4372 topCanPlayThrough: 'canplaythrough',
4373 topDurationChange: 'durationchange',
4374 topEmptied: 'emptied',
4375 topEncrypted: 'encrypted',
4376 topEnded: 'ended',
4377 topError: 'error',
4378 topLoadedData: 'loadeddata',
4379 topLoadedMetadata: 'loadedmetadata',
4380 topLoadStart: 'loadstart',
4381 topPause: 'pause',
4382 topPlay: 'play',
4383 topPlaying: 'playing',
4384 topProgress: 'progress',
4385 topRateChange: 'ratechange',
4386 topSeeked: 'seeked',
4387 topSeeking: 'seeking',
4388 topStalled: 'stalled',
4389 topSuspend: 'suspend',
4390 topTimeUpdate: 'timeupdate',
4391 topVolumeChange: 'volumechange',
4392 topWaiting: 'waiting'
4393};
4394
4395/**
4396 * Summary of `ReactBrowserEventEmitter` event handling:
4397 *
4398 * - Top-level delegation is used to trap most native browser events. This
4399 * may only occur in the main thread and is the responsibility of
4400 * ReactDOMEventListener, which is injected and can therefore support
4401 * pluggable event sources. This is the only work that occurs in the main
4402 * thread.
4403 *
4404 * - We normalize and de-duplicate events to account for browser quirks. This
4405 * may be done in the worker thread.
4406 *
4407 * - Forward these native events (with the associated top-level type used to
4408 * trap it) to `EventPluginHub`, which in turn will ask plugins if they want
4409 * to extract any synthetic events.
4410 *
4411 * - The `EventPluginHub` will then process each event by annotating them with
4412 * "dispatches", a sequence of listeners and IDs that care about that event.
4413 *
4414 * - The `EventPluginHub` then dispatches the events.
4415 *
4416 * Overview of React and the event system:
4417 *
4418 * +------------+ .
4419 * | DOM | .
4420 * +------------+ .
4421 * | .
4422 * v .
4423 * +------------+ .
4424 * | ReactEvent | .
4425 * | Listener | .
4426 * +------------+ . +-----------+
4427 * | . +--------+|SimpleEvent|
4428 * | . | |Plugin |
4429 * +-----|------+ . v +-----------+
4430 * | | | . +--------------+ +------------+
4431 * | +-----------.--->|EventPluginHub| | Event |
4432 * | | . | | +-----------+ | Propagators|
4433 * | ReactEvent | . | | |TapEvent | |------------|
4434 * | Emitter | . | |<---+|Plugin | |other plugin|
4435 * | | . | | +-----------+ | utilities |
4436 * | +-----------.--->| | +------------+
4437 * | | | . +--------------+
4438 * +-----|------+ . ^ +-----------+
4439 * | . | |Enter/Leave|
4440 * + . +-------+|Plugin |
4441 * +-------------+ . +-----------+
4442 * | application | .
4443 * |-------------| .
4444 * | | .
4445 * | | .
4446 * +-------------+ .
4447 * .
4448 * React Core . General Purpose Event Plugin System
4449 */
4450
4451var alreadyListeningTo = {};
4452var reactTopListenersCounter = 0;
4453
4454/**
4455 * To ensure no conflicts with other potential React instances on the page
4456 */
4457var topListenersIDKey = '_reactListenersID' + ('' + Math.random()).slice(2);
4458
4459function getListeningForDocument(mountAt) {
4460 // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`
4461 // directly.
4462 if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {
4463 mountAt[topListenersIDKey] = reactTopListenersCounter++;
4464 alreadyListeningTo[mountAt[topListenersIDKey]] = {};
4465 }
4466 return alreadyListeningTo[mountAt[topListenersIDKey]];
4467}
4468
4469/**
4470 * We listen for bubbled touch events on the document object.
4471 *
4472 * Firefox v8.01 (and possibly others) exhibited strange behavior when
4473 * mounting `onmousemove` events at some node that was not the document
4474 * element. The symptoms were that if your mouse is not moving over something
4475 * contained within that mount point (for example on the background) the
4476 * top-level listeners for `onmousemove` won't be called. However, if you
4477 * register the `mousemove` on the document object, then it will of course
4478 * catch all `mousemove`s. This along with iOS quirks, justifies restricting
4479 * top-level listeners to the document object only, at least for these
4480 * movement types of events and possibly all events.
4481 *
4482 * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
4483 *
4484 * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
4485 * they bubble to document.
4486 *
4487 * @param {string} registrationName Name of listener (e.g. `onClick`).
4488 * @param {object} contentDocumentHandle Document which owns the container
4489 */
4490function listenTo(registrationName, contentDocumentHandle) {
4491 var mountAt = contentDocumentHandle;
4492 var isListening = getListeningForDocument(mountAt);
4493 var dependencies = registrationNameDependencies[registrationName];
4494
4495 for (var i = 0; i < dependencies.length; i++) {
4496 var dependency = dependencies[i];
4497 if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
4498 if (dependency === 'topScroll') {
4499 trapCapturedEvent('topScroll', 'scroll', mountAt);
4500 } else if (dependency === 'topFocus' || dependency === 'topBlur') {
4501 trapCapturedEvent('topFocus', 'focus', mountAt);
4502 trapCapturedEvent('topBlur', 'blur', mountAt);
4503
4504 // to make sure blur and focus event listeners are only attached once
4505 isListening.topBlur = true;
4506 isListening.topFocus = true;
4507 } else if (dependency === 'topCancel') {
4508 if (isEventSupported('cancel', true)) {
4509 trapCapturedEvent('topCancel', 'cancel', mountAt);
4510 }
4511 isListening.topCancel = true;
4512 } else if (dependency === 'topClose') {
4513 if (isEventSupported('close', true)) {
4514 trapCapturedEvent('topClose', 'close', mountAt);
4515 }
4516 isListening.topClose = true;
4517 } else if (topLevelTypes.hasOwnProperty(dependency)) {
4518 trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt);
4519 }
4520
4521 isListening[dependency] = true;
4522 }
4523 }
4524}
4525
4526function isListeningToAllDependencies(registrationName, mountAt) {
4527 var isListening = getListeningForDocument(mountAt);
4528 var dependencies = registrationNameDependencies[registrationName];
4529 for (var i = 0; i < dependencies.length; i++) {
4530 var dependency = dependencies[i];
4531 if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
4532 return false;
4533 }
4534 }
4535 return true;
4536}
4537
4538/**
4539 * Copyright (c) 2013-present, Facebook, Inc.
4540 *
4541 * This source code is licensed under the MIT license found in the
4542 * LICENSE file in the root directory of this source tree.
4543 *
4544 * @typechecks
4545 */
4546
4547/**
4548 * @param {*} object The object to check.
4549 * @return {boolean} Whether or not the object is a DOM node.
4550 */
4551function isNode(object) {
4552 var doc = object ? object.ownerDocument || object : document;
4553 var defaultView = doc.defaultView || window;
4554 return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));
4555}
4556
4557var isNode_1 = isNode;
4558
4559/**
4560 * Copyright (c) 2013-present, Facebook, Inc.
4561 *
4562 * This source code is licensed under the MIT license found in the
4563 * LICENSE file in the root directory of this source tree.
4564 *
4565 * @typechecks
4566 */
4567
4568
4569
4570/**
4571 * @param {*} object The object to check.
4572 * @return {boolean} Whether or not the object is a DOM text node.
4573 */
4574function isTextNode(object) {
4575 return isNode_1(object) && object.nodeType == 3;
4576}
4577
4578var isTextNode_1 = isTextNode;
4579
4580/**
4581 * Copyright (c) 2013-present, Facebook, Inc.
4582 *
4583 * This source code is licensed under the MIT license found in the
4584 * LICENSE file in the root directory of this source tree.
4585 *
4586 *
4587 */
4588
4589
4590
4591/*eslint-disable no-bitwise */
4592
4593/**
4594 * Checks if a given DOM node contains or is another DOM node.
4595 */
4596function containsNode(outerNode, innerNode) {
4597 if (!outerNode || !innerNode) {
4598 return false;
4599 } else if (outerNode === innerNode) {
4600 return true;
4601 } else if (isTextNode_1(outerNode)) {
4602 return false;
4603 } else if (isTextNode_1(innerNode)) {
4604 return containsNode(outerNode, innerNode.parentNode);
4605 } else if ('contains' in outerNode) {
4606 return outerNode.contains(innerNode);
4607 } else if (outerNode.compareDocumentPosition) {
4608 return !!(outerNode.compareDocumentPosition(innerNode) & 16);
4609 } else {
4610 return false;
4611 }
4612}
4613
4614var containsNode_1 = containsNode;
4615
4616/**
4617 * Given any node return the first leaf node without children.
4618 *
4619 * @param {DOMElement|DOMTextNode} node
4620 * @return {DOMElement|DOMTextNode}
4621 */
4622function getLeafNode(node) {
4623 while (node && node.firstChild) {
4624 node = node.firstChild;
4625 }
4626 return node;
4627}
4628
4629/**
4630 * Get the next sibling within a container. This will walk up the
4631 * DOM if a node's siblings have been exhausted.
4632 *
4633 * @param {DOMElement|DOMTextNode} node
4634 * @return {?DOMElement|DOMTextNode}
4635 */
4636function getSiblingNode(node) {
4637 while (node) {
4638 if (node.nextSibling) {
4639 return node.nextSibling;
4640 }
4641 node = node.parentNode;
4642 }
4643}
4644
4645/**
4646 * Get object describing the nodes which contain characters at offset.
4647 *
4648 * @param {DOMElement|DOMTextNode} root
4649 * @param {number} offset
4650 * @return {?object}
4651 */
4652function getNodeForCharacterOffset(root, offset) {
4653 var node = getLeafNode(root);
4654 var nodeStart = 0;
4655 var nodeEnd = 0;
4656
4657 while (node) {
4658 if (node.nodeType === TEXT_NODE) {
4659 nodeEnd = nodeStart + node.textContent.length;
4660
4661 if (nodeStart <= offset && nodeEnd >= offset) {
4662 return {
4663 node: node,
4664 offset: offset - nodeStart
4665 };
4666 }
4667
4668 nodeStart = nodeEnd;
4669 }
4670
4671 node = getLeafNode(getSiblingNode(node));
4672 }
4673}
4674
4675/**
4676 * @param {DOMElement} outerNode
4677 * @return {?object}
4678 */
4679function getOffsets(outerNode) {
4680 var selection = window.getSelection && window.getSelection();
4681
4682 if (!selection || selection.rangeCount === 0) {
4683 return null;
4684 }
4685
4686 var anchorNode = selection.anchorNode,
4687 anchorOffset = selection.anchorOffset,
4688 focusNode = selection.focusNode,
4689 focusOffset = selection.focusOffset;
4690
4691 // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the
4692 // up/down buttons on an <input type="number">. Anonymous divs do not seem to
4693 // expose properties, triggering a "Permission denied error" if any of its
4694 // properties are accessed. The only seemingly possible way to avoid erroring
4695 // is to access a property that typically works for non-anonymous divs and
4696 // catch any error that may otherwise arise. See
4697 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
4698
4699 try {
4700 /* eslint-disable no-unused-expressions */
4701 anchorNode.nodeType;
4702 focusNode.nodeType;
4703 /* eslint-enable no-unused-expressions */
4704 } catch (e) {
4705 return null;
4706 }
4707
4708 return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset);
4709}
4710
4711/**
4712 * Returns {start, end} where `start` is the character/codepoint index of
4713 * (anchorNode, anchorOffset) within the textContent of `outerNode`, and
4714 * `end` is the index of (focusNode, focusOffset).
4715 *
4716 * Returns null if you pass in garbage input but we should probably just crash.
4717 *
4718 * Exported only for testing.
4719 */
4720function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) {
4721 var length = 0;
4722 var start = -1;
4723 var end = -1;
4724 var indexWithinAnchor = 0;
4725 var indexWithinFocus = 0;
4726 var node = outerNode;
4727 var parentNode = null;
4728
4729 outer: while (true) {
4730 var next = null;
4731
4732 while (true) {
4733 if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) {
4734 start = length + anchorOffset;
4735 }
4736 if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) {
4737 end = length + focusOffset;
4738 }
4739
4740 if (node.nodeType === TEXT_NODE) {
4741 length += node.nodeValue.length;
4742 }
4743
4744 if ((next = node.firstChild) === null) {
4745 break;
4746 }
4747 // Moving from `node` to its first child `next`.
4748 parentNode = node;
4749 node = next;
4750 }
4751
4752 while (true) {
4753 if (node === outerNode) {
4754 // If `outerNode` has children, this is always the second time visiting
4755 // it. If it has no children, this is still the first loop, and the only
4756 // valid selection is anchorNode and focusNode both equal to this node
4757 // and both offsets 0, in which case we will have handled above.
4758 break outer;
4759 }
4760 if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) {
4761 start = length;
4762 }
4763 if (parentNode === focusNode && ++indexWithinFocus === focusOffset) {
4764 end = length;
4765 }
4766 if ((next = node.nextSibling) !== null) {
4767 break;
4768 }
4769 node = parentNode;
4770 parentNode = node.parentNode;
4771 }
4772
4773 // Moving from `node` to its next sibling `next`.
4774 node = next;
4775 }
4776
4777 if (start === -1 || end === -1) {
4778 // This should never happen. (Would happen if the anchor/focus nodes aren't
4779 // actually inside the passed-in node.)
4780 return null;
4781 }
4782
4783 return {
4784 start: start,
4785 end: end
4786 };
4787}
4788
4789/**
4790 * In modern non-IE browsers, we can support both forward and backward
4791 * selections.
4792 *
4793 * Note: IE10+ supports the Selection object, but it does not support
4794 * the `extend` method, which means that even in modern IE, it's not possible
4795 * to programmatically create a backward selection. Thus, for all IE
4796 * versions, we use the old IE API to create our selections.
4797 *
4798 * @param {DOMElement|DOMTextNode} node
4799 * @param {object} offsets
4800 */
4801function setOffsets(node, offsets) {
4802 if (!window.getSelection) {
4803 return;
4804 }
4805
4806 var selection = window.getSelection();
4807 var length = node[getTextContentAccessor()].length;
4808 var start = Math.min(offsets.start, length);
4809 var end = offsets.end === undefined ? start : Math.min(offsets.end, length);
4810
4811 // IE 11 uses modern selection, but doesn't support the extend method.
4812 // Flip backward selections, so we can set with a single range.
4813 if (!selection.extend && start > end) {
4814 var temp = end;
4815 end = start;
4816 start = temp;
4817 }
4818
4819 var startMarker = getNodeForCharacterOffset(node, start);
4820 var endMarker = getNodeForCharacterOffset(node, end);
4821
4822 if (startMarker && endMarker) {
4823 if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) {
4824 return;
4825 }
4826 var range = document.createRange();
4827 range.setStart(startMarker.node, startMarker.offset);
4828 selection.removeAllRanges();
4829
4830 if (start > end) {
4831 selection.addRange(range);
4832 selection.extend(endMarker.node, endMarker.offset);
4833 } else {
4834 range.setEnd(endMarker.node, endMarker.offset);
4835 selection.addRange(range);
4836 }
4837 }
4838}
4839
4840function isInDocument(node) {
4841 return containsNode_1(document.documentElement, node);
4842}
4843
4844/**
4845 * @ReactInputSelection: React input selection module. Based on Selection.js,
4846 * but modified to be suitable for react and has a couple of bug fixes (doesn't
4847 * assume buttons have range selections allowed).
4848 * Input selection module for React.
4849 */
4850
4851function hasSelectionCapabilities(elem) {
4852 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
4853 return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');
4854}
4855
4856function getSelectionInformation() {
4857 var focusedElem = getActiveElement_1();
4858 return {
4859 focusedElem: focusedElem,
4860 selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection$1(focusedElem) : null
4861 };
4862}
4863
4864/**
4865 * @restoreSelection: If any selection information was potentially lost,
4866 * restore it. This is useful when performing operations that could remove dom
4867 * nodes and place them back in, resulting in focus being lost.
4868 */
4869function restoreSelection(priorSelectionInformation) {
4870 var curFocusedElem = getActiveElement_1();
4871 var priorFocusedElem = priorSelectionInformation.focusedElem;
4872 var priorSelectionRange = priorSelectionInformation.selectionRange;
4873 if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
4874 if (hasSelectionCapabilities(priorFocusedElem)) {
4875 setSelection(priorFocusedElem, priorSelectionRange);
4876 }
4877
4878 // Focusing a node can change the scroll position, which is undesirable
4879 var ancestors = [];
4880 var ancestor = priorFocusedElem;
4881 while (ancestor = ancestor.parentNode) {
4882 if (ancestor.nodeType === ELEMENT_NODE) {
4883 ancestors.push({
4884 element: ancestor,
4885 left: ancestor.scrollLeft,
4886 top: ancestor.scrollTop
4887 });
4888 }
4889 }
4890
4891 priorFocusedElem.focus();
4892
4893 for (var i = 0; i < ancestors.length; i++) {
4894 var info = ancestors[i];
4895 info.element.scrollLeft = info.left;
4896 info.element.scrollTop = info.top;
4897 }
4898 }
4899}
4900
4901/**
4902 * @getSelection: Gets the selection bounds of a focused textarea, input or
4903 * contentEditable node.
4904 * -@input: Look up selection bounds of this input
4905 * -@return {start: selectionStart, end: selectionEnd}
4906 */
4907function getSelection$1(input) {
4908 var selection = void 0;
4909
4910 if ('selectionStart' in input) {
4911 // Modern browser with input or textarea.
4912 selection = {
4913 start: input.selectionStart,
4914 end: input.selectionEnd
4915 };
4916 } else {
4917 // Content editable or old IE textarea.
4918 selection = getOffsets(input);
4919 }
4920
4921 return selection || { start: 0, end: 0 };
4922}
4923
4924/**
4925 * @setSelection: Sets the selection bounds of a textarea or input and focuses
4926 * the input.
4927 * -@input Set selection bounds of this input or textarea
4928 * -@offsets Object of same form that is returned from get*
4929 */
4930function setSelection(input, offsets) {
4931 var start = offsets.start,
4932 end = offsets.end;
4933
4934 if (end === undefined) {
4935 end = start;
4936 }
4937
4938 if ('selectionStart' in input) {
4939 input.selectionStart = start;
4940 input.selectionEnd = Math.min(end, input.value.length);
4941 } else {
4942 setOffsets(input, offsets);
4943 }
4944}
4945
4946var skipSelectionChangeEvent = ExecutionEnvironment_1.canUseDOM && 'documentMode' in document && document.documentMode <= 11;
4947
4948var eventTypes$3 = {
4949 select: {
4950 phasedRegistrationNames: {
4951 bubbled: 'onSelect',
4952 captured: 'onSelectCapture'
4953 },
4954 dependencies: ['topBlur', 'topContextMenu', 'topFocus', 'topKeyDown', 'topKeyUp', 'topMouseDown', 'topMouseUp', 'topSelectionChange']
4955 }
4956};
4957
4958var activeElement$1 = null;
4959var activeElementInst$1 = null;
4960var lastSelection = null;
4961var mouseDown = false;
4962
4963/**
4964 * Get an object which is a unique representation of the current selection.
4965 *
4966 * The return value will not be consistent across nodes or browsers, but
4967 * two identical selections on the same node will return identical objects.
4968 *
4969 * @param {DOMElement} node
4970 * @return {object}
4971 */
4972function getSelection(node) {
4973 if ('selectionStart' in node && hasSelectionCapabilities(node)) {
4974 return {
4975 start: node.selectionStart,
4976 end: node.selectionEnd
4977 };
4978 } else if (window.getSelection) {
4979 var selection = window.getSelection();
4980 return {
4981 anchorNode: selection.anchorNode,
4982 anchorOffset: selection.anchorOffset,
4983 focusNode: selection.focusNode,
4984 focusOffset: selection.focusOffset
4985 };
4986 }
4987}
4988
4989/**
4990 * Poll selection to see whether it's changed.
4991 *
4992 * @param {object} nativeEvent
4993 * @return {?SyntheticEvent}
4994 */
4995function constructSelectEvent(nativeEvent, nativeEventTarget) {
4996 // Ensure we have the right element, and that the user is not dragging a
4997 // selection (this matches native `select` event behavior). In HTML5, select
4998 // fires only on input and textarea thus if there's no focused element we
4999 // won't dispatch.
5000 if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement_1()) {
5001 return null;
5002 }
5003
5004 // Only fire when selection has actually changed.
5005 var currentSelection = getSelection(activeElement$1);
5006 if (!lastSelection || !shallowEqual_1(lastSelection, currentSelection)) {
5007 lastSelection = currentSelection;
5008
5009 var syntheticEvent = SyntheticEvent$1.getPooled(eventTypes$3.select, activeElementInst$1, nativeEvent, nativeEventTarget);
5010
5011 syntheticEvent.type = 'select';
5012 syntheticEvent.target = activeElement$1;
5013
5014 accumulateTwoPhaseDispatches(syntheticEvent);
5015
5016 return syntheticEvent;
5017 }
5018
5019 return null;
5020}
5021
5022/**
5023 * This plugin creates an `onSelect` event that normalizes select events
5024 * across form elements.
5025 *
5026 * Supported elements are:
5027 * - input (see `isTextInputElement`)
5028 * - textarea
5029 * - contentEditable
5030 *
5031 * This differs from native browser implementations in the following ways:
5032 * - Fires on contentEditable fields as well as inputs.
5033 * - Fires for collapsed selection.
5034 * - Fires after user input.
5035 */
5036var SelectEventPlugin = {
5037 eventTypes: eventTypes$3,
5038
5039 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
5040 var doc = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget.document : nativeEventTarget.nodeType === DOCUMENT_NODE ? nativeEventTarget : nativeEventTarget.ownerDocument;
5041 // Track whether all listeners exists for this plugin. If none exist, we do
5042 // not extract events. See #3639.
5043 if (!doc || !isListeningToAllDependencies('onSelect', doc)) {
5044 return null;
5045 }
5046
5047 var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window;
5048
5049 switch (topLevelType) {
5050 // Track the input node that has focus.
5051 case 'topFocus':
5052 if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {
5053 activeElement$1 = targetNode;
5054 activeElementInst$1 = targetInst;
5055 lastSelection = null;
5056 }
5057 break;
5058 case 'topBlur':
5059 activeElement$1 = null;
5060 activeElementInst$1 = null;
5061 lastSelection = null;
5062 break;
5063 // Don't fire the event while the user is dragging. This matches the
5064 // semantics of the native select event.
5065 case 'topMouseDown':
5066 mouseDown = true;
5067 break;
5068 case 'topContextMenu':
5069 case 'topMouseUp':
5070 mouseDown = false;
5071 return constructSelectEvent(nativeEvent, nativeEventTarget);
5072 // Chrome and IE fire non-standard event when selection is changed (and
5073 // sometimes when it hasn't). IE's event fires out of order with respect
5074 // to key and input events on deletion, so we discard it.
5075 //
5076 // Firefox doesn't support selectionchange, so check selection status
5077 // after each key entry. The selection changes after keydown and before
5078 // keyup, but we check on keydown as well in the case of holding down a
5079 // key, when multiple keydown events are fired but only one keyup is.
5080 // This is also our approach for IE handling, for the reason above.
5081 case 'topSelectionChange':
5082 if (skipSelectionChangeEvent) {
5083 break;
5084 }
5085 // falls through
5086 case 'topKeyDown':
5087 case 'topKeyUp':
5088 return constructSelectEvent(nativeEvent, nativeEventTarget);
5089 }
5090
5091 return null;
5092 }
5093};
5094
5095/**
5096 * @interface Event
5097 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface
5098 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent
5099 */
5100var SyntheticAnimationEvent = SyntheticEvent$1.extend({
5101 animationName: null,
5102 elapsedTime: null,
5103 pseudoElement: null
5104});
5105
5106/**
5107 * @interface Event
5108 * @see http://www.w3.org/TR/clipboard-apis/
5109 */
5110var SyntheticClipboardEvent = SyntheticEvent$1.extend({
5111 clipboardData: function (event) {
5112 return 'clipboardData' in event ? event.clipboardData : window.clipboardData;
5113 }
5114});
5115
5116/**
5117 * @interface FocusEvent
5118 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5119 */
5120var SyntheticFocusEvent = SyntheticUIEvent.extend({
5121 relatedTarget: null
5122});
5123
5124/**
5125 * `charCode` represents the actual "character code" and is safe to use with
5126 * `String.fromCharCode`. As such, only keys that correspond to printable
5127 * characters produce a valid `charCode`, the only exception to this is Enter.
5128 * The Tab-key is considered non-printable and does not have a `charCode`,
5129 * presumably because it does not produce a tab-character in browsers.
5130 *
5131 * @param {object} nativeEvent Native browser event.
5132 * @return {number} Normalized `charCode` property.
5133 */
5134function getEventCharCode(nativeEvent) {
5135 var charCode = void 0;
5136 var keyCode = nativeEvent.keyCode;
5137
5138 if ('charCode' in nativeEvent) {
5139 charCode = nativeEvent.charCode;
5140
5141 // FF does not set `charCode` for the Enter-key, check against `keyCode`.
5142 if (charCode === 0 && keyCode === 13) {
5143 charCode = 13;
5144 }
5145 } else {
5146 // IE8 does not implement `charCode`, but `keyCode` has the correct value.
5147 charCode = keyCode;
5148 }
5149
5150 // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux)
5151 // report Enter as charCode 10 when ctrl is pressed.
5152 if (charCode === 10) {
5153 charCode = 13;
5154 }
5155
5156 // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.
5157 // Must not discard the (non-)printable Enter-key.
5158 if (charCode >= 32 || charCode === 13) {
5159 return charCode;
5160 }
5161
5162 return 0;
5163}
5164
5165/**
5166 * Normalization of deprecated HTML5 `key` values
5167 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
5168 */
5169var normalizeKey = {
5170 Esc: 'Escape',
5171 Spacebar: ' ',
5172 Left: 'ArrowLeft',
5173 Up: 'ArrowUp',
5174 Right: 'ArrowRight',
5175 Down: 'ArrowDown',
5176 Del: 'Delete',
5177 Win: 'OS',
5178 Menu: 'ContextMenu',
5179 Apps: 'ContextMenu',
5180 Scroll: 'ScrollLock',
5181 MozPrintableKey: 'Unidentified'
5182};
5183
5184/**
5185 * Translation from legacy `keyCode` to HTML5 `key`
5186 * Only special keys supported, all others depend on keyboard layout or browser
5187 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names
5188 */
5189var translateToKey = {
5190 '8': 'Backspace',
5191 '9': 'Tab',
5192 '12': 'Clear',
5193 '13': 'Enter',
5194 '16': 'Shift',
5195 '17': 'Control',
5196 '18': 'Alt',
5197 '19': 'Pause',
5198 '20': 'CapsLock',
5199 '27': 'Escape',
5200 '32': ' ',
5201 '33': 'PageUp',
5202 '34': 'PageDown',
5203 '35': 'End',
5204 '36': 'Home',
5205 '37': 'ArrowLeft',
5206 '38': 'ArrowUp',
5207 '39': 'ArrowRight',
5208 '40': 'ArrowDown',
5209 '45': 'Insert',
5210 '46': 'Delete',
5211 '112': 'F1',
5212 '113': 'F2',
5213 '114': 'F3',
5214 '115': 'F4',
5215 '116': 'F5',
5216 '117': 'F6',
5217 '118': 'F7',
5218 '119': 'F8',
5219 '120': 'F9',
5220 '121': 'F10',
5221 '122': 'F11',
5222 '123': 'F12',
5223 '144': 'NumLock',
5224 '145': 'ScrollLock',
5225 '224': 'Meta'
5226};
5227
5228/**
5229 * @param {object} nativeEvent Native browser event.
5230 * @return {string} Normalized `key` property.
5231 */
5232function getEventKey(nativeEvent) {
5233 if (nativeEvent.key) {
5234 // Normalize inconsistent values reported by browsers due to
5235 // implementations of a working draft specification.
5236
5237 // FireFox implements `key` but returns `MozPrintableKey` for all
5238 // printable characters (normalized to `Unidentified`), ignore it.
5239 var key = normalizeKey[nativeEvent.key] || nativeEvent.key;
5240 if (key !== 'Unidentified') {
5241 return key;
5242 }
5243 }
5244
5245 // Browser does not implement `key`, polyfill as much of it as we can.
5246 if (nativeEvent.type === 'keypress') {
5247 var charCode = getEventCharCode(nativeEvent);
5248
5249 // The enter-key is technically both printable and non-printable and can
5250 // thus be captured by `keypress`, no other non-printable key should.
5251 return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);
5252 }
5253 if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {
5254 // While user keyboard layout determines the actual meaning of each
5255 // `keyCode` value, almost all function keys have a universal value.
5256 return translateToKey[nativeEvent.keyCode] || 'Unidentified';
5257 }
5258 return '';
5259}
5260
5261/**
5262 * @interface KeyboardEvent
5263 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5264 */
5265var SyntheticKeyboardEvent = SyntheticUIEvent.extend({
5266 key: getEventKey,
5267 location: null,
5268 ctrlKey: null,
5269 shiftKey: null,
5270 altKey: null,
5271 metaKey: null,
5272 repeat: null,
5273 locale: null,
5274 getModifierState: getEventModifierState,
5275 // Legacy Interface
5276 charCode: function (event) {
5277 // `charCode` is the result of a KeyPress event and represents the value of
5278 // the actual printable character.
5279
5280 // KeyPress is deprecated, but its replacement is not yet final and not
5281 // implemented in any major browser. Only KeyPress has charCode.
5282 if (event.type === 'keypress') {
5283 return getEventCharCode(event);
5284 }
5285 return 0;
5286 },
5287 keyCode: function (event) {
5288 // `keyCode` is the result of a KeyDown/Up event and represents the value of
5289 // physical keyboard key.
5290
5291 // The actual meaning of the value depends on the users' keyboard layout
5292 // which cannot be detected. Assuming that it is a US keyboard layout
5293 // provides a surprisingly accurate mapping for US and European users.
5294 // Due to this, it is left to the user to implement at this time.
5295 if (event.type === 'keydown' || event.type === 'keyup') {
5296 return event.keyCode;
5297 }
5298 return 0;
5299 },
5300 which: function (event) {
5301 // `which` is an alias for either `keyCode` or `charCode` depending on the
5302 // type of the event.
5303 if (event.type === 'keypress') {
5304 return getEventCharCode(event);
5305 }
5306 if (event.type === 'keydown' || event.type === 'keyup') {
5307 return event.keyCode;
5308 }
5309 return 0;
5310 }
5311});
5312
5313/**
5314 * @interface DragEvent
5315 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5316 */
5317var SyntheticDragEvent = SyntheticMouseEvent.extend({
5318 dataTransfer: null
5319});
5320
5321/**
5322 * @interface TouchEvent
5323 * @see http://www.w3.org/TR/touch-events/
5324 */
5325var SyntheticTouchEvent = SyntheticUIEvent.extend({
5326 touches: null,
5327 targetTouches: null,
5328 changedTouches: null,
5329 altKey: null,
5330 metaKey: null,
5331 ctrlKey: null,
5332 shiftKey: null,
5333 getModifierState: getEventModifierState
5334});
5335
5336/**
5337 * @interface Event
5338 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-
5339 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent
5340 */
5341var SyntheticTransitionEvent = SyntheticEvent$1.extend({
5342 propertyName: null,
5343 elapsedTime: null,
5344 pseudoElement: null
5345});
5346
5347/**
5348 * @interface WheelEvent
5349 * @see http://www.w3.org/TR/DOM-Level-3-Events/
5350 */
5351var SyntheticWheelEvent = SyntheticMouseEvent.extend({
5352 deltaX: function (event) {
5353 return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
5354 'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
5355 },
5356 deltaY: function (event) {
5357 return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
5358 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
5359 'wheelDelta' in event ? -event.wheelDelta : 0;
5360 },
5361
5362 deltaZ: null,
5363
5364 // Browsers without "deltaMode" is reporting in raw wheel delta where one
5365 // notch on the scroll is always +/- 120, roughly equivalent to pixels.
5366 // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or
5367 // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.
5368 deltaMode: null
5369});
5370
5371/**
5372 * Turns
5373 * ['abort', ...]
5374 * into
5375 * eventTypes = {
5376 * 'abort': {
5377 * phasedRegistrationNames: {
5378 * bubbled: 'onAbort',
5379 * captured: 'onAbortCapture',
5380 * },
5381 * dependencies: ['topAbort'],
5382 * },
5383 * ...
5384 * };
5385 * topLevelEventsToDispatchConfig = {
5386 * 'topAbort': { sameConfig }
5387 * };
5388 */
5389var eventTypes$4 = {};
5390var topLevelEventsToDispatchConfig = {};
5391['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) {
5392 var capitalizedEvent = event[0].toUpperCase() + event.slice(1);
5393 var onEvent = 'on' + capitalizedEvent;
5394 var topEvent = 'top' + capitalizedEvent;
5395
5396 var type = {
5397 phasedRegistrationNames: {
5398 bubbled: onEvent,
5399 captured: onEvent + 'Capture'
5400 },
5401 dependencies: [topEvent]
5402 };
5403 eventTypes$4[event] = type;
5404 topLevelEventsToDispatchConfig[topEvent] = type;
5405});
5406
5407// Only used in DEV for exhaustiveness validation.
5408var 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'];
5409
5410var SimpleEventPlugin = {
5411 eventTypes: eventTypes$4,
5412
5413 extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
5414 var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];
5415 if (!dispatchConfig) {
5416 return null;
5417 }
5418 var EventConstructor = void 0;
5419 switch (topLevelType) {
5420 case 'topKeyPress':
5421 // Firefox creates a keypress event for function keys too. This removes
5422 // the unwanted keypress events. Enter is however both printable and
5423 // non-printable. One would expect Tab to be as well (but it isn't).
5424 if (getEventCharCode(nativeEvent) === 0) {
5425 return null;
5426 }
5427 /* falls through */
5428 case 'topKeyDown':
5429 case 'topKeyUp':
5430 EventConstructor = SyntheticKeyboardEvent;
5431 break;
5432 case 'topBlur':
5433 case 'topFocus':
5434 EventConstructor = SyntheticFocusEvent;
5435 break;
5436 case 'topClick':
5437 // Firefox creates a click event on right mouse clicks. This removes the
5438 // unwanted click events.
5439 if (nativeEvent.button === 2) {
5440 return null;
5441 }
5442 /* falls through */
5443 case 'topDoubleClick':
5444 case 'topMouseDown':
5445 case 'topMouseMove':
5446 case 'topMouseUp':
5447 // TODO: Disabled elements should not respond to mouse events
5448 /* falls through */
5449 case 'topMouseOut':
5450 case 'topMouseOver':
5451 case 'topContextMenu':
5452 EventConstructor = SyntheticMouseEvent;
5453 break;
5454 case 'topDrag':
5455 case 'topDragEnd':
5456 case 'topDragEnter':
5457 case 'topDragExit':
5458 case 'topDragLeave':
5459 case 'topDragOver':
5460 case 'topDragStart':
5461 case 'topDrop':
5462 EventConstructor = SyntheticDragEvent;
5463 break;
5464 case 'topTouchCancel':
5465 case 'topTouchEnd':
5466 case 'topTouchMove':
5467 case 'topTouchStart':
5468 EventConstructor = SyntheticTouchEvent;
5469 break;
5470 case 'topAnimationEnd':
5471 case 'topAnimationIteration':
5472 case 'topAnimationStart':
5473 EventConstructor = SyntheticAnimationEvent;
5474 break;
5475 case 'topTransitionEnd':
5476 EventConstructor = SyntheticTransitionEvent;
5477 break;
5478 case 'topScroll':
5479 EventConstructor = SyntheticUIEvent;
5480 break;
5481 case 'topWheel':
5482 EventConstructor = SyntheticWheelEvent;
5483 break;
5484 case 'topCopy':
5485 case 'topCut':
5486 case 'topPaste':
5487 EventConstructor = SyntheticClipboardEvent;
5488 break;
5489 default:
5490 {
5491 if (knownHTMLTopLevelTypes.indexOf(topLevelType) === -1) {
5492 warning_1(false, 'SimpleEventPlugin: Unhandled event type, `%s`. This warning ' + 'is likely caused by a bug in React. Please file an issue.', topLevelType);
5493 }
5494 }
5495 // HTML Events
5496 // @see http://www.w3.org/TR/html5/index.html#events-0
5497 EventConstructor = SyntheticEvent$1;
5498 break;
5499 }
5500 var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);
5501 accumulateTwoPhaseDispatches(event);
5502 return event;
5503 }
5504};
5505
5506/**
5507 * Inject modules for resolving DOM hierarchy and plugin ordering.
5508 */
5509injection.injectEventPluginOrder(DOMEventPluginOrder);
5510injection$1.injectComponentTree(ReactDOMComponentTree);
5511
5512/**
5513 * Some important event plugins included by default (without having to require
5514 * them).
5515 */
5516injection.injectEventPluginsByName({
5517 SimpleEventPlugin: SimpleEventPlugin,
5518 EnterLeaveEventPlugin: EnterLeaveEventPlugin,
5519 ChangeEventPlugin: ChangeEventPlugin,
5520 SelectEventPlugin: SelectEventPlugin,
5521 BeforeInputEventPlugin: BeforeInputEventPlugin
5522});
5523
5524/**
5525 * Copyright (c) 2013-present, Facebook, Inc.
5526 *
5527 * This source code is licensed under the MIT license found in the
5528 * LICENSE file in the root directory of this source tree.
5529 *
5530 */
5531
5532
5533
5534var emptyObject = {};
5535
5536{
5537 Object.freeze(emptyObject);
5538}
5539
5540var emptyObject_1 = emptyObject;
5541
5542var valueStack = [];
5543
5544var fiberStack = void 0;
5545
5546{
5547 fiberStack = [];
5548}
5549
5550var index = -1;
5551
5552function createCursor(defaultValue) {
5553 return {
5554 current: defaultValue
5555 };
5556}
5557
5558
5559
5560function pop(cursor, fiber) {
5561 if (index < 0) {
5562 {
5563 warning_1(false, 'Unexpected pop.');
5564 }
5565 return;
5566 }
5567
5568 {
5569 if (fiber !== fiberStack[index]) {
5570 warning_1(false, 'Unexpected Fiber popped.');
5571 }
5572 }
5573
5574 cursor.current = valueStack[index];
5575
5576 valueStack[index] = null;
5577
5578 {
5579 fiberStack[index] = null;
5580 }
5581
5582 index--;
5583}
5584
5585function push(cursor, value, fiber) {
5586 index++;
5587
5588 valueStack[index] = cursor.current;
5589
5590 {
5591 fiberStack[index] = fiber;
5592 }
5593
5594 cursor.current = value;
5595}
5596
5597function reset$1() {
5598 while (index > -1) {
5599 valueStack[index] = null;
5600
5601 {
5602 fiberStack[index] = null;
5603 }
5604
5605 index--;
5606 }
5607}
5608
5609var enableAsyncSubtreeAPI = true;
5610// Exports ReactDOM.createRoot
5611var enableCreateRoot = false;
5612var enableUserTimingAPI = true;
5613
5614// Mutating mode (React DOM, React ART, React Native):
5615var enableMutatingReconciler = true;
5616// Experimental noop mode (currently unused):
5617var enableNoopReconciler = false;
5618// Experimental persistent mode (CS):
5619var enablePersistentReconciler = false;
5620
5621// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
5622var debugRenderPhaseSideEffects = false;
5623
5624// Only used in www builds.
5625
5626// Prefix measurements so that it's possible to filter them.
5627// Longer prefixes are hard to read in DevTools.
5628var reactEmoji = '\u269B';
5629var warningEmoji = '\u26D4';
5630var supportsUserTiming = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function';
5631
5632// Keep track of current fiber so that we know the path to unwind on pause.
5633// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them?
5634var currentFiber = null;
5635// If we're in the middle of user code, which fiber and method is it?
5636// Reusing `currentFiber` would be confusing for this because user code fiber
5637// can change during commit phase too, but we don't need to unwind it (since
5638// lifecycles in the commit phase don't resemble a tree).
5639var currentPhase = null;
5640var currentPhaseFiber = null;
5641// Did lifecycle hook schedule an update? This is often a performance problem,
5642// so we will keep track of it, and include it in the report.
5643// Track commits caused by cascading updates.
5644var isCommitting = false;
5645var hasScheduledUpdateInCurrentCommit = false;
5646var hasScheduledUpdateInCurrentPhase = false;
5647var commitCountInCurrentWorkLoop = 0;
5648var effectCountInCurrentCommit = 0;
5649var isWaitingForCallback = false;
5650// During commits, we only show a measurement once per method name
5651// to avoid stretch the commit phase with measurement overhead.
5652var labelsInCurrentCommit = new Set();
5653
5654var formatMarkName = function (markName) {
5655 return reactEmoji + ' ' + markName;
5656};
5657
5658var formatLabel = function (label, warning) {
5659 var prefix = warning ? warningEmoji + ' ' : reactEmoji + ' ';
5660 var suffix = warning ? ' Warning: ' + warning : '';
5661 return '' + prefix + label + suffix;
5662};
5663
5664var beginMark = function (markName) {
5665 performance.mark(formatMarkName(markName));
5666};
5667
5668var clearMark = function (markName) {
5669 performance.clearMarks(formatMarkName(markName));
5670};
5671
5672var endMark = function (label, markName, warning) {
5673 var formattedMarkName = formatMarkName(markName);
5674 var formattedLabel = formatLabel(label, warning);
5675 try {
5676 performance.measure(formattedLabel, formattedMarkName);
5677 } catch (err) {}
5678 // If previous mark was missing for some reason, this will throw.
5679 // This could only happen if React crashed in an unexpected place earlier.
5680 // Don't pile on with more errors.
5681
5682 // Clear marks immediately to avoid growing buffer.
5683 performance.clearMarks(formattedMarkName);
5684 performance.clearMeasures(formattedLabel);
5685};
5686
5687var getFiberMarkName = function (label, debugID) {
5688 return label + ' (#' + debugID + ')';
5689};
5690
5691var getFiberLabel = function (componentName, isMounted, phase) {
5692 if (phase === null) {
5693 // These are composite component total time measurements.
5694 return componentName + ' [' + (isMounted ? 'update' : 'mount') + ']';
5695 } else {
5696 // Composite component methods.
5697 return componentName + '.' + phase;
5698 }
5699};
5700
5701var beginFiberMark = function (fiber, phase) {
5702 var componentName = getComponentName(fiber) || 'Unknown';
5703 var debugID = fiber._debugID;
5704 var isMounted = fiber.alternate !== null;
5705 var label = getFiberLabel(componentName, isMounted, phase);
5706
5707 if (isCommitting && labelsInCurrentCommit.has(label)) {
5708 // During the commit phase, we don't show duplicate labels because
5709 // there is a fixed overhead for every measurement, and we don't
5710 // want to stretch the commit phase beyond necessary.
5711 return false;
5712 }
5713 labelsInCurrentCommit.add(label);
5714
5715 var markName = getFiberMarkName(label, debugID);
5716 beginMark(markName);
5717 return true;
5718};
5719
5720var clearFiberMark = function (fiber, phase) {
5721 var componentName = getComponentName(fiber) || 'Unknown';
5722 var debugID = fiber._debugID;
5723 var isMounted = fiber.alternate !== null;
5724 var label = getFiberLabel(componentName, isMounted, phase);
5725 var markName = getFiberMarkName(label, debugID);
5726 clearMark(markName);
5727};
5728
5729var endFiberMark = function (fiber, phase, warning) {
5730 var componentName = getComponentName(fiber) || 'Unknown';
5731 var debugID = fiber._debugID;
5732 var isMounted = fiber.alternate !== null;
5733 var label = getFiberLabel(componentName, isMounted, phase);
5734 var markName = getFiberMarkName(label, debugID);
5735 endMark(label, markName, warning);
5736};
5737
5738var shouldIgnoreFiber = function (fiber) {
5739 // Host components should be skipped in the timeline.
5740 // We could check typeof fiber.type, but does this work with RN?
5741 switch (fiber.tag) {
5742 case HostRoot:
5743 case HostComponent:
5744 case HostText:
5745 case HostPortal:
5746 case CallComponent:
5747 case ReturnComponent:
5748 case Fragment:
5749 return true;
5750 default:
5751 return false;
5752 }
5753};
5754
5755var clearPendingPhaseMeasurement = function () {
5756 if (currentPhase !== null && currentPhaseFiber !== null) {
5757 clearFiberMark(currentPhaseFiber, currentPhase);
5758 }
5759 currentPhaseFiber = null;
5760 currentPhase = null;
5761 hasScheduledUpdateInCurrentPhase = false;
5762};
5763
5764var pauseTimers = function () {
5765 // Stops all currently active measurements so that they can be resumed
5766 // if we continue in a later deferred loop from the same unit of work.
5767 var fiber = currentFiber;
5768 while (fiber) {
5769 if (fiber._debugIsCurrentlyTiming) {
5770 endFiberMark(fiber, null, null);
5771 }
5772 fiber = fiber['return'];
5773 }
5774};
5775
5776var resumeTimersRecursively = function (fiber) {
5777 if (fiber['return'] !== null) {
5778 resumeTimersRecursively(fiber['return']);
5779 }
5780 if (fiber._debugIsCurrentlyTiming) {
5781 beginFiberMark(fiber, null);
5782 }
5783};
5784
5785var resumeTimers = function () {
5786 // Resumes all measurements that were active during the last deferred loop.
5787 if (currentFiber !== null) {
5788 resumeTimersRecursively(currentFiber);
5789 }
5790};
5791
5792function recordEffect() {
5793 if (enableUserTimingAPI) {
5794 effectCountInCurrentCommit++;
5795 }
5796}
5797
5798function recordScheduleUpdate() {
5799 if (enableUserTimingAPI) {
5800 if (isCommitting) {
5801 hasScheduledUpdateInCurrentCommit = true;
5802 }
5803 if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') {
5804 hasScheduledUpdateInCurrentPhase = true;
5805 }
5806 }
5807}
5808
5809function startRequestCallbackTimer() {
5810 if (enableUserTimingAPI) {
5811 if (supportsUserTiming && !isWaitingForCallback) {
5812 isWaitingForCallback = true;
5813 beginMark('(Waiting for async callback...)');
5814 }
5815 }
5816}
5817
5818function stopRequestCallbackTimer(didExpire) {
5819 if (enableUserTimingAPI) {
5820 if (supportsUserTiming) {
5821 isWaitingForCallback = false;
5822 var warning = didExpire ? 'React was blocked by main thread' : null;
5823 endMark('(Waiting for async callback...)', '(Waiting for async callback...)', warning);
5824 }
5825 }
5826}
5827
5828function startWorkTimer(fiber) {
5829 if (enableUserTimingAPI) {
5830 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5831 return;
5832 }
5833 // If we pause, this is the fiber to unwind from.
5834 currentFiber = fiber;
5835 if (!beginFiberMark(fiber, null)) {
5836 return;
5837 }
5838 fiber._debugIsCurrentlyTiming = true;
5839 }
5840}
5841
5842function cancelWorkTimer(fiber) {
5843 if (enableUserTimingAPI) {
5844 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5845 return;
5846 }
5847 // Remember we shouldn't complete measurement for this fiber.
5848 // Otherwise flamechart will be deep even for small updates.
5849 fiber._debugIsCurrentlyTiming = false;
5850 clearFiberMark(fiber, null);
5851 }
5852}
5853
5854function stopWorkTimer(fiber) {
5855 if (enableUserTimingAPI) {
5856 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5857 return;
5858 }
5859 // If we pause, its parent is the fiber to unwind from.
5860 currentFiber = fiber['return'];
5861 if (!fiber._debugIsCurrentlyTiming) {
5862 return;
5863 }
5864 fiber._debugIsCurrentlyTiming = false;
5865 endFiberMark(fiber, null, null);
5866 }
5867}
5868
5869function stopFailedWorkTimer(fiber) {
5870 if (enableUserTimingAPI) {
5871 if (!supportsUserTiming || shouldIgnoreFiber(fiber)) {
5872 return;
5873 }
5874 // If we pause, its parent is the fiber to unwind from.
5875 currentFiber = fiber['return'];
5876 if (!fiber._debugIsCurrentlyTiming) {
5877 return;
5878 }
5879 fiber._debugIsCurrentlyTiming = false;
5880 var warning = 'An error was thrown inside this error boundary';
5881 endFiberMark(fiber, null, warning);
5882 }
5883}
5884
5885function startPhaseTimer(fiber, phase) {
5886 if (enableUserTimingAPI) {
5887 if (!supportsUserTiming) {
5888 return;
5889 }
5890 clearPendingPhaseMeasurement();
5891 if (!beginFiberMark(fiber, phase)) {
5892 return;
5893 }
5894 currentPhaseFiber = fiber;
5895 currentPhase = phase;
5896 }
5897}
5898
5899function stopPhaseTimer() {
5900 if (enableUserTimingAPI) {
5901 if (!supportsUserTiming) {
5902 return;
5903 }
5904 if (currentPhase !== null && currentPhaseFiber !== null) {
5905 var warning = hasScheduledUpdateInCurrentPhase ? 'Scheduled a cascading update' : null;
5906 endFiberMark(currentPhaseFiber, currentPhase, warning);
5907 }
5908 currentPhase = null;
5909 currentPhaseFiber = null;
5910 }
5911}
5912
5913function startWorkLoopTimer(nextUnitOfWork) {
5914 if (enableUserTimingAPI) {
5915 currentFiber = nextUnitOfWork;
5916 if (!supportsUserTiming) {
5917 return;
5918 }
5919 commitCountInCurrentWorkLoop = 0;
5920 // This is top level call.
5921 // Any other measurements are performed within.
5922 beginMark('(React Tree Reconciliation)');
5923 // Resume any measurements that were in progress during the last loop.
5924 resumeTimers();
5925 }
5926}
5927
5928function stopWorkLoopTimer(interruptedBy) {
5929 if (enableUserTimingAPI) {
5930 if (!supportsUserTiming) {
5931 return;
5932 }
5933 var warning = null;
5934 if (interruptedBy !== null) {
5935 if (interruptedBy.tag === HostRoot) {
5936 warning = 'A top-level update interrupted the previous render';
5937 } else {
5938 var componentName = getComponentName(interruptedBy) || 'Unknown';
5939 warning = 'An update to ' + componentName + ' interrupted the previous render';
5940 }
5941 } else if (commitCountInCurrentWorkLoop > 1) {
5942 warning = 'There were cascading updates';
5943 }
5944 commitCountInCurrentWorkLoop = 0;
5945 // Pause any measurements until the next loop.
5946 pauseTimers();
5947 endMark('(React Tree Reconciliation)', '(React Tree Reconciliation)', warning);
5948 }
5949}
5950
5951function startCommitTimer() {
5952 if (enableUserTimingAPI) {
5953 if (!supportsUserTiming) {
5954 return;
5955 }
5956 isCommitting = true;
5957 hasScheduledUpdateInCurrentCommit = false;
5958 labelsInCurrentCommit.clear();
5959 beginMark('(Committing Changes)');
5960 }
5961}
5962
5963function stopCommitTimer() {
5964 if (enableUserTimingAPI) {
5965 if (!supportsUserTiming) {
5966 return;
5967 }
5968
5969 var warning = null;
5970 if (hasScheduledUpdateInCurrentCommit) {
5971 warning = 'Lifecycle hook scheduled a cascading update';
5972 } else if (commitCountInCurrentWorkLoop > 0) {
5973 warning = 'Caused by a cascading update in earlier commit';
5974 }
5975 hasScheduledUpdateInCurrentCommit = false;
5976 commitCountInCurrentWorkLoop++;
5977 isCommitting = false;
5978 labelsInCurrentCommit.clear();
5979
5980 endMark('(Committing Changes)', '(Committing Changes)', warning);
5981 }
5982}
5983
5984function startCommitHostEffectsTimer() {
5985 if (enableUserTimingAPI) {
5986 if (!supportsUserTiming) {
5987 return;
5988 }
5989 effectCountInCurrentCommit = 0;
5990 beginMark('(Committing Host Effects)');
5991 }
5992}
5993
5994function stopCommitHostEffectsTimer() {
5995 if (enableUserTimingAPI) {
5996 if (!supportsUserTiming) {
5997 return;
5998 }
5999 var count = effectCountInCurrentCommit;
6000 effectCountInCurrentCommit = 0;
6001 endMark('(Committing Host Effects: ' + count + ' Total)', '(Committing Host Effects)', null);
6002 }
6003}
6004
6005function startCommitLifeCyclesTimer() {
6006 if (enableUserTimingAPI) {
6007 if (!supportsUserTiming) {
6008 return;
6009 }
6010 effectCountInCurrentCommit = 0;
6011 beginMark('(Calling Lifecycle Methods)');
6012 }
6013}
6014
6015function stopCommitLifeCyclesTimer() {
6016 if (enableUserTimingAPI) {
6017 if (!supportsUserTiming) {
6018 return;
6019 }
6020 var count = effectCountInCurrentCommit;
6021 effectCountInCurrentCommit = 0;
6022 endMark('(Calling Lifecycle Methods: ' + count + ' Total)', '(Calling Lifecycle Methods)', null);
6023 }
6024}
6025
6026var warnedAboutMissingGetChildContext = void 0;
6027
6028{
6029 warnedAboutMissingGetChildContext = {};
6030}
6031
6032// A cursor to the current merged context object on the stack.
6033var contextStackCursor = createCursor(emptyObject_1);
6034// A cursor to a boolean indicating whether the context has changed.
6035var didPerformWorkStackCursor = createCursor(false);
6036// Keep track of the previous context object that was on the stack.
6037// We use this to get access to the parent context after we have already
6038// pushed the next context provider, and now need to merge their contexts.
6039var previousContext = emptyObject_1;
6040
6041function getUnmaskedContext(workInProgress) {
6042 var hasOwnContext = isContextProvider(workInProgress);
6043 if (hasOwnContext) {
6044 // If the fiber is a context provider itself, when we read its context
6045 // we have already pushed its own child context on the stack. A context
6046 // provider should not "see" its own child context. Therefore we read the
6047 // previous (parent) context instead for a context provider.
6048 return previousContext;
6049 }
6050 return contextStackCursor.current;
6051}
6052
6053function cacheContext(workInProgress, unmaskedContext, maskedContext) {
6054 var instance = workInProgress.stateNode;
6055 instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext;
6056 instance.__reactInternalMemoizedMaskedChildContext = maskedContext;
6057}
6058
6059function getMaskedContext(workInProgress, unmaskedContext) {
6060 var type = workInProgress.type;
6061 var contextTypes = type.contextTypes;
6062 if (!contextTypes) {
6063 return emptyObject_1;
6064 }
6065
6066 // Avoid recreating masked context unless unmasked context has changed.
6067 // Failing to do this will result in unnecessary calls to componentWillReceiveProps.
6068 // This may trigger infinite loops if componentWillReceiveProps calls setState.
6069 var instance = workInProgress.stateNode;
6070 if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) {
6071 return instance.__reactInternalMemoizedMaskedChildContext;
6072 }
6073
6074 var context = {};
6075 for (var key in contextTypes) {
6076 context[key] = unmaskedContext[key];
6077 }
6078
6079 {
6080 var name = getComponentName(workInProgress) || 'Unknown';
6081 checkPropTypes_1(contextTypes, context, 'context', name, ReactDebugCurrentFiber.getCurrentFiberStackAddendum);
6082 }
6083
6084 // Cache unmasked context so we can avoid recreating masked context unless necessary.
6085 // Context is created before the class component is instantiated so check for instance.
6086 if (instance) {
6087 cacheContext(workInProgress, unmaskedContext, context);
6088 }
6089
6090 return context;
6091}
6092
6093function hasContextChanged() {
6094 return didPerformWorkStackCursor.current;
6095}
6096
6097function isContextConsumer(fiber) {
6098 return fiber.tag === ClassComponent && fiber.type.contextTypes != null;
6099}
6100
6101function isContextProvider(fiber) {
6102 return fiber.tag === ClassComponent && fiber.type.childContextTypes != null;
6103}
6104
6105function popContextProvider(fiber) {
6106 if (!isContextProvider(fiber)) {
6107 return;
6108 }
6109
6110 pop(didPerformWorkStackCursor, fiber);
6111 pop(contextStackCursor, fiber);
6112}
6113
6114function popTopLevelContextObject(fiber) {
6115 pop(didPerformWorkStackCursor, fiber);
6116 pop(contextStackCursor, fiber);
6117}
6118
6119function pushTopLevelContextObject(fiber, context, didChange) {
6120 !(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;
6121
6122 push(contextStackCursor, context, fiber);
6123 push(didPerformWorkStackCursor, didChange, fiber);
6124}
6125
6126function processChildContext(fiber, parentContext) {
6127 var instance = fiber.stateNode;
6128 var childContextTypes = fiber.type.childContextTypes;
6129
6130 // TODO (bvaughn) Replace this behavior with an invariant() in the future.
6131 // It has only been added in Fiber to match the (unintentional) behavior in Stack.
6132 if (typeof instance.getChildContext !== 'function') {
6133 {
6134 var componentName = getComponentName(fiber) || 'Unknown';
6135
6136 if (!warnedAboutMissingGetChildContext[componentName]) {
6137 warnedAboutMissingGetChildContext[componentName] = true;
6138 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);
6139 }
6140 }
6141 return parentContext;
6142 }
6143
6144 var childContext = void 0;
6145 {
6146 ReactDebugCurrentFiber.setCurrentPhase('getChildContext');
6147 }
6148 startPhaseTimer(fiber, 'getChildContext');
6149 childContext = instance.getChildContext();
6150 stopPhaseTimer();
6151 {
6152 ReactDebugCurrentFiber.setCurrentPhase(null);
6153 }
6154 for (var contextKey in childContext) {
6155 !(contextKey in childContextTypes) ? invariant_1(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', getComponentName(fiber) || 'Unknown', contextKey) : void 0;
6156 }
6157 {
6158 var name = getComponentName(fiber) || 'Unknown';
6159 checkPropTypes_1(childContextTypes, childContext, 'child context', name,
6160 // In practice, there is one case in which we won't get a stack. It's when
6161 // somebody calls unstable_renderSubtreeIntoContainer() and we process
6162 // context from the parent component instance. The stack will be missing
6163 // because it's outside of the reconciliation, and so the pointer has not
6164 // been set. This is rare and doesn't matter. We'll also remove that API.
6165 ReactDebugCurrentFiber.getCurrentFiberStackAddendum);
6166 }
6167
6168 return _assign({}, parentContext, childContext);
6169}
6170
6171function pushContextProvider(workInProgress) {
6172 if (!isContextProvider(workInProgress)) {
6173 return false;
6174 }
6175
6176 var instance = workInProgress.stateNode;
6177 // We push the context as early as possible to ensure stack integrity.
6178 // If the instance does not exist yet, we will push null at first,
6179 // and replace it on the stack later when invalidating the context.
6180 var memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyObject_1;
6181
6182 // Remember the parent context so we can merge with it later.
6183 // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates.
6184 previousContext = contextStackCursor.current;
6185 push(contextStackCursor, memoizedMergedChildContext, workInProgress);
6186 push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress);
6187
6188 return true;
6189}
6190
6191function invalidateContextProvider(workInProgress, didChange) {
6192 var instance = workInProgress.stateNode;
6193 !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;
6194
6195 if (didChange) {
6196 // Merge parent and own context.
6197 // Skip this if we're not updating due to sCU.
6198 // This avoids unnecessarily recomputing memoized values.
6199 var mergedContext = processChildContext(workInProgress, previousContext);
6200 instance.__reactInternalMemoizedMergedChildContext = mergedContext;
6201
6202 // Replace the old (or empty) context with the new one.
6203 // It is important to unwind the context in the reverse order.
6204 pop(didPerformWorkStackCursor, workInProgress);
6205 pop(contextStackCursor, workInProgress);
6206 // Now push the new context and mark that it has changed.
6207 push(contextStackCursor, mergedContext, workInProgress);
6208 push(didPerformWorkStackCursor, didChange, workInProgress);
6209 } else {
6210 pop(didPerformWorkStackCursor, workInProgress);
6211 push(didPerformWorkStackCursor, didChange, workInProgress);
6212 }
6213}
6214
6215function resetContext() {
6216 previousContext = emptyObject_1;
6217 contextStackCursor.current = emptyObject_1;
6218 didPerformWorkStackCursor.current = false;
6219}
6220
6221function findCurrentUnmaskedContext(fiber) {
6222 // Currently this is only used with renderSubtreeIntoContainer; not sure if it
6223 // makes sense elsewhere
6224 !(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;
6225
6226 var node = fiber;
6227 while (node.tag !== HostRoot) {
6228 if (isContextProvider(node)) {
6229 return node.stateNode.__reactInternalMemoizedMergedChildContext;
6230 }
6231 var parent = node['return'];
6232 !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;
6233 node = parent;
6234 }
6235 return node.stateNode.context;
6236}
6237
6238var NoWork = 0; // TODO: Use an opaque type once ESLint et al support the syntax
6239
6240var Sync = 1;
6241var Never = 2147483647; // Max int32: Math.pow(2, 31) - 1
6242
6243var UNIT_SIZE = 10;
6244var MAGIC_NUMBER_OFFSET = 2;
6245
6246// 1 unit of expiration time represents 10ms.
6247function msToExpirationTime(ms) {
6248 // Always add an offset so that we don't clash with the magic number for NoWork.
6249 return (ms / UNIT_SIZE | 0) + MAGIC_NUMBER_OFFSET;
6250}
6251
6252function expirationTimeToMs(expirationTime) {
6253 return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE;
6254}
6255
6256function ceiling(num, precision) {
6257 return ((num / precision | 0) + 1) * precision;
6258}
6259
6260function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) {
6261 return ceiling(currentTime + expirationInMs / UNIT_SIZE, bucketSizeMs / UNIT_SIZE);
6262}
6263
6264var NoContext = 0;
6265var AsyncUpdates = 1;
6266
6267var hasBadMapPolyfill = void 0;
6268
6269{
6270 hasBadMapPolyfill = false;
6271 try {
6272 var nonExtensibleObject = Object.preventExtensions({});
6273 var testMap = new Map([[nonExtensibleObject, null]]);
6274 var testSet = new Set([nonExtensibleObject]);
6275 // This is necessary for Rollup to not consider these unused.
6276 // https://github.com/rollup/rollup/issues/1771
6277 // TODO: we can remove these if Rollup fixes the bug.
6278 testMap.set(0, 0);
6279 testSet.add(0);
6280 } catch (e) {
6281 // TODO: Consider warning about bad polyfills
6282 hasBadMapPolyfill = true;
6283 }
6284}
6285
6286// A Fiber is work on a Component that needs to be done or was done. There can
6287// be more than one per component.
6288
6289
6290var debugCounter = void 0;
6291
6292{
6293 debugCounter = 1;
6294}
6295
6296function FiberNode(tag, pendingProps, key, internalContextTag) {
6297 // Instance
6298 this.tag = tag;
6299 this.key = key;
6300 this.type = null;
6301 this.stateNode = null;
6302
6303 // Fiber
6304 this['return'] = null;
6305 this.child = null;
6306 this.sibling = null;
6307 this.index = 0;
6308
6309 this.ref = null;
6310
6311 this.pendingProps = pendingProps;
6312 this.memoizedProps = null;
6313 this.updateQueue = null;
6314 this.memoizedState = null;
6315
6316 this.internalContextTag = internalContextTag;
6317
6318 // Effects
6319 this.effectTag = NoEffect;
6320 this.nextEffect = null;
6321
6322 this.firstEffect = null;
6323 this.lastEffect = null;
6324
6325 this.expirationTime = NoWork;
6326
6327 this.alternate = null;
6328
6329 {
6330 this._debugID = debugCounter++;
6331 this._debugSource = null;
6332 this._debugOwner = null;
6333 this._debugIsCurrentlyTiming = false;
6334 if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
6335 Object.preventExtensions(this);
6336 }
6337 }
6338}
6339
6340// This is a constructor function, rather than a POJO constructor, still
6341// please ensure we do the following:
6342// 1) Nobody should add any instance methods on this. Instance methods can be
6343// more difficult to predict when they get optimized and they are almost
6344// never inlined properly in static compilers.
6345// 2) Nobody should rely on `instanceof Fiber` for type testing. We should
6346// always know when it is a fiber.
6347// 3) We might want to experiment with using numeric keys since they are easier
6348// to optimize in a non-JIT environment.
6349// 4) We can easily go from a constructor to a createFiber object literal if that
6350// is faster.
6351// 5) It should be easy to port this to a C struct and keep a C implementation
6352// compatible.
6353var createFiber = function (tag, pendingProps, key, internalContextTag) {
6354 // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
6355 return new FiberNode(tag, pendingProps, key, internalContextTag);
6356};
6357
6358function shouldConstruct(Component) {
6359 return !!(Component.prototype && Component.prototype.isReactComponent);
6360}
6361
6362// This is used to create an alternate fiber to do work on.
6363function createWorkInProgress(current, pendingProps, expirationTime) {
6364 var workInProgress = current.alternate;
6365 if (workInProgress === null) {
6366 // We use a double buffering pooling technique because we know that we'll
6367 // only ever need at most two versions of a tree. We pool the "other" unused
6368 // node that we're free to reuse. This is lazily created to avoid allocating
6369 // extra objects for things that are never updated. It also allow us to
6370 // reclaim the extra memory if needed.
6371 workInProgress = createFiber(current.tag, pendingProps, current.key, current.internalContextTag);
6372 workInProgress.type = current.type;
6373 workInProgress.stateNode = current.stateNode;
6374
6375 {
6376 // DEV-only fields
6377 workInProgress._debugID = current._debugID;
6378 workInProgress._debugSource = current._debugSource;
6379 workInProgress._debugOwner = current._debugOwner;
6380 }
6381
6382 workInProgress.alternate = current;
6383 current.alternate = workInProgress;
6384 } else {
6385 workInProgress.pendingProps = pendingProps;
6386
6387 // We already have an alternate.
6388 // Reset the effect tag.
6389 workInProgress.effectTag = NoEffect;
6390
6391 // The effect list is no longer valid.
6392 workInProgress.nextEffect = null;
6393 workInProgress.firstEffect = null;
6394 workInProgress.lastEffect = null;
6395 }
6396
6397 workInProgress.expirationTime = expirationTime;
6398
6399 workInProgress.child = current.child;
6400 workInProgress.memoizedProps = current.memoizedProps;
6401 workInProgress.memoizedState = current.memoizedState;
6402 workInProgress.updateQueue = current.updateQueue;
6403
6404 // These will be overridden during the parent's reconciliation
6405 workInProgress.sibling = current.sibling;
6406 workInProgress.index = current.index;
6407 workInProgress.ref = current.ref;
6408
6409 return workInProgress;
6410}
6411
6412function createHostRootFiber(isAsync) {
6413 var internalContextTag = isAsync ? AsyncUpdates : NoContext;
6414 return createFiber(HostRoot, null, null, internalContextTag);
6415}
6416
6417function createFiberFromElement(element, internalContextTag, expirationTime) {
6418 var owner = null;
6419 {
6420 owner = element._owner;
6421 }
6422
6423 var fiber = void 0;
6424 var type = element.type;
6425 var key = element.key;
6426 var pendingProps = element.props;
6427 if (typeof type === 'function') {
6428 fiber = shouldConstruct(type) ? createFiber(ClassComponent, pendingProps, key, internalContextTag) : createFiber(IndeterminateComponent, pendingProps, key, internalContextTag);
6429 fiber.type = type;
6430 } else if (typeof type === 'string') {
6431 fiber = createFiber(HostComponent, pendingProps, key, internalContextTag);
6432 fiber.type = type;
6433 } else {
6434 switch (type) {
6435 case REACT_FRAGMENT_TYPE:
6436 return createFiberFromFragment(pendingProps.children, internalContextTag, expirationTime, key);
6437 case REACT_CALL_TYPE:
6438 fiber = createFiber(CallComponent, pendingProps, key, internalContextTag);
6439 fiber.type = REACT_CALL_TYPE;
6440 break;
6441 case REACT_RETURN_TYPE:
6442 fiber = createFiber(ReturnComponent, pendingProps, key, internalContextTag);
6443 fiber.type = REACT_RETURN_TYPE;
6444 break;
6445 default:
6446 {
6447 if (typeof type === 'object' && type !== null && typeof type.tag === 'number') {
6448 // Currently assumed to be a continuation and therefore is a
6449 // fiber already.
6450 // TODO: The yield system is currently broken for updates in some
6451 // cases. The reified yield stores a fiber, but we don't know which
6452 // fiber that is; the current or a workInProgress? When the
6453 // continuation gets rendered here we don't know if we can reuse that
6454 // fiber or if we need to clone it. There is probably a clever way to
6455 // restructure this.
6456 fiber = type;
6457 fiber.pendingProps = pendingProps;
6458 } else {
6459 var info = '';
6460 {
6461 if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
6462 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.';
6463 }
6464 var ownerName = owner ? getComponentName(owner) : null;
6465 if (ownerName) {
6466 info += '\n\nCheck the render method of `' + ownerName + '`.';
6467 }
6468 }
6469 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);
6470 }
6471 }
6472 }
6473 }
6474
6475 {
6476 fiber._debugSource = element._source;
6477 fiber._debugOwner = element._owner;
6478 }
6479
6480 fiber.expirationTime = expirationTime;
6481
6482 return fiber;
6483}
6484
6485function createFiberFromFragment(elements, internalContextTag, expirationTime, key) {
6486 var fiber = createFiber(Fragment, elements, key, internalContextTag);
6487 fiber.expirationTime = expirationTime;
6488 return fiber;
6489}
6490
6491function createFiberFromText(content, internalContextTag, expirationTime) {
6492 var fiber = createFiber(HostText, content, null, internalContextTag);
6493 fiber.expirationTime = expirationTime;
6494 return fiber;
6495}
6496
6497function createFiberFromHostInstanceForDeletion() {
6498 var fiber = createFiber(HostComponent, null, null, NoContext);
6499 fiber.type = 'DELETED';
6500 return fiber;
6501}
6502
6503function createFiberFromPortal(portal, internalContextTag, expirationTime) {
6504 var pendingProps = portal.children !== null ? portal.children : [];
6505 var fiber = createFiber(HostPortal, pendingProps, portal.key, internalContextTag);
6506 fiber.expirationTime = expirationTime;
6507 fiber.stateNode = {
6508 containerInfo: portal.containerInfo,
6509 pendingChildren: null, // Used by persistent updates
6510 implementation: portal.implementation
6511 };
6512 return fiber;
6513}
6514
6515// TODO: This should be lifted into the renderer.
6516
6517
6518function createFiberRoot(containerInfo, isAsync, hydrate) {
6519 // Cyclic construction. This cheats the type system right now because
6520 // stateNode is any.
6521 var uninitializedFiber = createHostRootFiber(isAsync);
6522 var root = {
6523 current: uninitializedFiber,
6524 containerInfo: containerInfo,
6525 pendingChildren: null,
6526 remainingExpirationTime: NoWork,
6527 isReadyForCommit: false,
6528 finishedWork: null,
6529 context: null,
6530 pendingContext: null,
6531 hydrate: hydrate,
6532 firstBatch: null,
6533 nextScheduledRoot: null
6534 };
6535 uninitializedFiber.stateNode = root;
6536 return root;
6537}
6538
6539var onCommitFiberRoot = null;
6540var onCommitFiberUnmount = null;
6541var hasLoggedError = false;
6542
6543function catchErrors(fn) {
6544 return function (arg) {
6545 try {
6546 return fn(arg);
6547 } catch (err) {
6548 if (true && !hasLoggedError) {
6549 hasLoggedError = true;
6550 warning_1(false, 'React DevTools encountered an error: %s', err);
6551 }
6552 }
6553 };
6554}
6555
6556function injectInternals(internals) {
6557 if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
6558 // No DevTools
6559 return false;
6560 }
6561 var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;
6562 if (hook.isDisabled) {
6563 // This isn't a real property on the hook, but it can be set to opt out
6564 // of DevTools integration and associated warnings and logs.
6565 // https://github.com/facebook/react/issues/3877
6566 return true;
6567 }
6568 if (!hook.supportsFiber) {
6569 {
6570 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');
6571 }
6572 // DevTools exists, even though it doesn't support Fiber.
6573 return true;
6574 }
6575 try {
6576 var rendererID = hook.inject(internals);
6577 // We have successfully injected, so now it is safe to set up hooks.
6578 onCommitFiberRoot = catchErrors(function (root) {
6579 return hook.onCommitFiberRoot(rendererID, root);
6580 });
6581 onCommitFiberUnmount = catchErrors(function (fiber) {
6582 return hook.onCommitFiberUnmount(rendererID, fiber);
6583 });
6584 } catch (err) {
6585 // Catch all errors because it is unsafe to throw during initialization.
6586 {
6587 warning_1(false, 'React DevTools encountered an error: %s.', err);
6588 }
6589 }
6590 // DevTools exists
6591 return true;
6592}
6593
6594function onCommitRoot(root) {
6595 if (typeof onCommitFiberRoot === 'function') {
6596 onCommitFiberRoot(root);
6597 }
6598}
6599
6600function onCommitUnmount(fiber) {
6601 if (typeof onCommitFiberUnmount === 'function') {
6602 onCommitFiberUnmount(fiber);
6603 }
6604}
6605
6606var didWarnUpdateInsideUpdate = void 0;
6607
6608{
6609 didWarnUpdateInsideUpdate = false;
6610}
6611
6612// Callbacks are not validated until invocation
6613
6614
6615// Singly linked-list of updates. When an update is scheduled, it is added to
6616// the queue of the current fiber and the work-in-progress fiber. The two queues
6617// are separate but they share a persistent structure.
6618//
6619// During reconciliation, updates are removed from the work-in-progress fiber,
6620// but they remain on the current fiber. That ensures that if a work-in-progress
6621// is aborted, the aborted updates are recovered by cloning from current.
6622//
6623// The work-in-progress queue is always a subset of the current queue.
6624//
6625// When the tree is committed, the work-in-progress becomes the current.
6626
6627
6628function createUpdateQueue(baseState) {
6629 var queue = {
6630 baseState: baseState,
6631 expirationTime: NoWork,
6632 first: null,
6633 last: null,
6634 callbackList: null,
6635 hasForceUpdate: false,
6636 isInitialized: false
6637 };
6638 {
6639 queue.isProcessing = false;
6640 }
6641 return queue;
6642}
6643
6644function insertUpdateIntoQueue(queue, update) {
6645 // Append the update to the end of the list.
6646 if (queue.last === null) {
6647 // Queue is empty
6648 queue.first = queue.last = update;
6649 } else {
6650 queue.last.next = update;
6651 queue.last = update;
6652 }
6653 if (queue.expirationTime === NoWork || queue.expirationTime > update.expirationTime) {
6654 queue.expirationTime = update.expirationTime;
6655 }
6656}
6657
6658function insertUpdateIntoFiber(fiber, update) {
6659 // We'll have at least one and at most two distinct update queues.
6660 var alternateFiber = fiber.alternate;
6661 var queue1 = fiber.updateQueue;
6662 if (queue1 === null) {
6663 // TODO: We don't know what the base state will be until we begin work.
6664 // It depends on which fiber is the next current. Initialize with an empty
6665 // base state, then set to the memoizedState when rendering. Not super
6666 // happy with this approach.
6667 queue1 = fiber.updateQueue = createUpdateQueue(null);
6668 }
6669
6670 var queue2 = void 0;
6671 if (alternateFiber !== null) {
6672 queue2 = alternateFiber.updateQueue;
6673 if (queue2 === null) {
6674 queue2 = alternateFiber.updateQueue = createUpdateQueue(null);
6675 }
6676 } else {
6677 queue2 = null;
6678 }
6679 queue2 = queue2 !== queue1 ? queue2 : null;
6680
6681 // Warn if an update is scheduled from inside an updater function.
6682 {
6683 if ((queue1.isProcessing || queue2 !== null && queue2.isProcessing) && !didWarnUpdateInsideUpdate) {
6684 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.');
6685 didWarnUpdateInsideUpdate = true;
6686 }
6687 }
6688
6689 // If there's only one queue, add the update to that queue and exit.
6690 if (queue2 === null) {
6691 insertUpdateIntoQueue(queue1, update);
6692 return;
6693 }
6694
6695 // If either queue is empty, we need to add to both queues.
6696 if (queue1.last === null || queue2.last === null) {
6697 insertUpdateIntoQueue(queue1, update);
6698 insertUpdateIntoQueue(queue2, update);
6699 return;
6700 }
6701
6702 // If both lists are not empty, the last update is the same for both lists
6703 // because of structural sharing. So, we should only append to one of
6704 // the lists.
6705 insertUpdateIntoQueue(queue1, update);
6706 // But we still need to update the `last` pointer of queue2.
6707 queue2.last = update;
6708}
6709
6710function getUpdateExpirationTime(fiber) {
6711 if (fiber.tag !== ClassComponent && fiber.tag !== HostRoot) {
6712 return NoWork;
6713 }
6714 var updateQueue = fiber.updateQueue;
6715 if (updateQueue === null) {
6716 return NoWork;
6717 }
6718 return updateQueue.expirationTime;
6719}
6720
6721function getStateFromUpdate(update, instance, prevState, props) {
6722 var partialState = update.partialState;
6723 if (typeof partialState === 'function') {
6724 var updateFn = partialState;
6725
6726 // Invoke setState callback an extra time to help detect side-effects.
6727 if (debugRenderPhaseSideEffects) {
6728 updateFn.call(instance, prevState, props);
6729 }
6730
6731 return updateFn.call(instance, prevState, props);
6732 } else {
6733 return partialState;
6734 }
6735}
6736
6737function processUpdateQueue(current, workInProgress, queue, instance, props, renderExpirationTime) {
6738 if (current !== null && current.updateQueue === queue) {
6739 // We need to create a work-in-progress queue, by cloning the current queue.
6740 var currentQueue = queue;
6741 queue = workInProgress.updateQueue = {
6742 baseState: currentQueue.baseState,
6743 expirationTime: currentQueue.expirationTime,
6744 first: currentQueue.first,
6745 last: currentQueue.last,
6746 isInitialized: currentQueue.isInitialized,
6747 // These fields are no longer valid because they were already committed.
6748 // Reset them.
6749 callbackList: null,
6750 hasForceUpdate: false
6751 };
6752 }
6753
6754 {
6755 // Set this flag so we can warn if setState is called inside the update
6756 // function of another setState.
6757 queue.isProcessing = true;
6758 }
6759
6760 // Reset the remaining expiration time. If we skip over any updates, we'll
6761 // increase this accordingly.
6762 queue.expirationTime = NoWork;
6763
6764 // TODO: We don't know what the base state will be until we begin work.
6765 // It depends on which fiber is the next current. Initialize with an empty
6766 // base state, then set to the memoizedState when rendering. Not super
6767 // happy with this approach.
6768 var state = void 0;
6769 if (queue.isInitialized) {
6770 state = queue.baseState;
6771 } else {
6772 state = queue.baseState = workInProgress.memoizedState;
6773 queue.isInitialized = true;
6774 }
6775 var dontMutatePrevState = true;
6776 var update = queue.first;
6777 var didSkip = false;
6778 while (update !== null) {
6779 var updateExpirationTime = update.expirationTime;
6780 if (updateExpirationTime > renderExpirationTime) {
6781 // This update does not have sufficient priority. Skip it.
6782 var remainingExpirationTime = queue.expirationTime;
6783 if (remainingExpirationTime === NoWork || remainingExpirationTime > updateExpirationTime) {
6784 // Update the remaining expiration time.
6785 queue.expirationTime = updateExpirationTime;
6786 }
6787 if (!didSkip) {
6788 didSkip = true;
6789 queue.baseState = state;
6790 }
6791 // Continue to the next update.
6792 update = update.next;
6793 continue;
6794 }
6795
6796 // This update does have sufficient priority.
6797
6798 // If no previous updates were skipped, drop this update from the queue by
6799 // advancing the head of the list.
6800 if (!didSkip) {
6801 queue.first = update.next;
6802 if (queue.first === null) {
6803 queue.last = null;
6804 }
6805 }
6806
6807 // Process the update
6808 var _partialState = void 0;
6809 if (update.isReplace) {
6810 state = getStateFromUpdate(update, instance, state, props);
6811 dontMutatePrevState = true;
6812 } else {
6813 _partialState = getStateFromUpdate(update, instance, state, props);
6814 if (_partialState) {
6815 if (dontMutatePrevState) {
6816 // $FlowFixMe: Idk how to type this properly.
6817 state = _assign({}, state, _partialState);
6818 } else {
6819 state = _assign(state, _partialState);
6820 }
6821 dontMutatePrevState = false;
6822 }
6823 }
6824 if (update.isForced) {
6825 queue.hasForceUpdate = true;
6826 }
6827 if (update.callback !== null) {
6828 // Append to list of callbacks.
6829 var _callbackList = queue.callbackList;
6830 if (_callbackList === null) {
6831 _callbackList = queue.callbackList = [];
6832 }
6833 _callbackList.push(update);
6834 }
6835 update = update.next;
6836 }
6837
6838 if (queue.callbackList !== null) {
6839 workInProgress.effectTag |= Callback;
6840 } else if (queue.first === null && !queue.hasForceUpdate) {
6841 // The queue is empty. We can reset it.
6842 workInProgress.updateQueue = null;
6843 }
6844
6845 if (!didSkip) {
6846 didSkip = true;
6847 queue.baseState = state;
6848 }
6849
6850 {
6851 // No longer processing.
6852 queue.isProcessing = false;
6853 }
6854
6855 return state;
6856}
6857
6858function commitCallbacks(queue, context) {
6859 var callbackList = queue.callbackList;
6860 if (callbackList === null) {
6861 return;
6862 }
6863 // Set the list to null to make sure they don't get called more than once.
6864 queue.callbackList = null;
6865 for (var i = 0; i < callbackList.length; i++) {
6866 var update = callbackList[i];
6867 var _callback = update.callback;
6868 // This update might be processed again. Clear the callback so it's only
6869 // called once.
6870 update.callback = null;
6871 !(typeof _callback === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback) : void 0;
6872 _callback.call(context);
6873 }
6874}
6875
6876var fakeInternalInstance = {};
6877var isArray = Array.isArray;
6878
6879var didWarnAboutStateAssignmentForComponent = void 0;
6880var warnOnInvalidCallback$1 = void 0;
6881
6882{
6883 var didWarnOnInvalidCallback = {};
6884 didWarnAboutStateAssignmentForComponent = {};
6885
6886 warnOnInvalidCallback$1 = function (callback, callerName) {
6887 if (callback === null || typeof callback === 'function') {
6888 return;
6889 }
6890 var key = callerName + '_' + callback;
6891 if (!didWarnOnInvalidCallback[key]) {
6892 warning_1(false, '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
6893 didWarnOnInvalidCallback[key] = true;
6894 }
6895 };
6896
6897 // This is so gross but it's at least non-critical and can be removed if
6898 // it causes problems. This is meant to give a nicer error message for
6899 // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component,
6900 // ...)) which otherwise throws a "_processChildContext is not a function"
6901 // exception.
6902 Object.defineProperty(fakeInternalInstance, '_processChildContext', {
6903 enumerable: false,
6904 value: function () {
6905 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).');
6906 }
6907 });
6908 Object.freeze(fakeInternalInstance);
6909}
6910
6911var ReactFiberClassComponent = function (scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState) {
6912 // Class component state updater
6913 var updater = {
6914 isMounted: isMounted,
6915 enqueueSetState: function (instance, partialState, callback) {
6916 var fiber = get(instance);
6917 callback = callback === undefined ? null : callback;
6918 {
6919 warnOnInvalidCallback$1(callback, 'setState');
6920 }
6921 var expirationTime = computeExpirationForFiber(fiber);
6922 var update = {
6923 expirationTime: expirationTime,
6924 partialState: partialState,
6925 callback: callback,
6926 isReplace: false,
6927 isForced: false,
6928 nextCallback: null,
6929 next: null
6930 };
6931 insertUpdateIntoFiber(fiber, update);
6932 scheduleWork(fiber, expirationTime);
6933 },
6934 enqueueReplaceState: function (instance, state, callback) {
6935 var fiber = get(instance);
6936 callback = callback === undefined ? null : callback;
6937 {
6938 warnOnInvalidCallback$1(callback, 'replaceState');
6939 }
6940 var expirationTime = computeExpirationForFiber(fiber);
6941 var update = {
6942 expirationTime: expirationTime,
6943 partialState: state,
6944 callback: callback,
6945 isReplace: true,
6946 isForced: false,
6947 nextCallback: null,
6948 next: null
6949 };
6950 insertUpdateIntoFiber(fiber, update);
6951 scheduleWork(fiber, expirationTime);
6952 },
6953 enqueueForceUpdate: function (instance, callback) {
6954 var fiber = get(instance);
6955 callback = callback === undefined ? null : callback;
6956 {
6957 warnOnInvalidCallback$1(callback, 'forceUpdate');
6958 }
6959 var expirationTime = computeExpirationForFiber(fiber);
6960 var update = {
6961 expirationTime: expirationTime,
6962 partialState: null,
6963 callback: callback,
6964 isReplace: false,
6965 isForced: true,
6966 nextCallback: null,
6967 next: null
6968 };
6969 insertUpdateIntoFiber(fiber, update);
6970 scheduleWork(fiber, expirationTime);
6971 }
6972 };
6973
6974 function checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext) {
6975 if (oldProps === null || workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate) {
6976 // If the workInProgress already has an Update effect, return true
6977 return true;
6978 }
6979
6980 var instance = workInProgress.stateNode;
6981 var type = workInProgress.type;
6982 if (typeof instance.shouldComponentUpdate === 'function') {
6983 startPhaseTimer(workInProgress, 'shouldComponentUpdate');
6984 var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, newContext);
6985 stopPhaseTimer();
6986
6987 // Simulate an async bailout/interruption by invoking lifecycle twice.
6988 if (debugRenderPhaseSideEffects) {
6989 instance.shouldComponentUpdate(newProps, newState, newContext);
6990 }
6991
6992 {
6993 warning_1(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentName(workInProgress) || 'Unknown');
6994 }
6995
6996 return shouldUpdate;
6997 }
6998
6999 if (type.prototype && type.prototype.isPureReactComponent) {
7000 return !shallowEqual_1(oldProps, newProps) || !shallowEqual_1(oldState, newState);
7001 }
7002
7003 return true;
7004 }
7005
7006 function checkClassInstance(workInProgress) {
7007 var instance = workInProgress.stateNode;
7008 var type = workInProgress.type;
7009 {
7010 var name = getComponentName(workInProgress);
7011 var renderPresent = instance.render;
7012
7013 if (!renderPresent) {
7014 if (type.prototype && typeof type.prototype.render === 'function') {
7015 warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name);
7016 } else {
7017 warning_1(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name);
7018 }
7019 }
7020
7021 var noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state;
7022 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);
7023 var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved;
7024 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);
7025 var noInstancePropTypes = !instance.propTypes;
7026 warning_1(noInstancePropTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name);
7027 var noInstanceContextTypes = !instance.contextTypes;
7028 warning_1(noInstanceContextTypes, 'contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name);
7029 var noComponentShouldUpdate = typeof instance.componentShouldUpdate !== 'function';
7030 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);
7031 if (type.prototype && type.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') {
7032 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');
7033 }
7034 var noComponentDidUnmount = typeof instance.componentDidUnmount !== 'function';
7035 warning_1(noComponentDidUnmount, '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name);
7036 var noComponentDidReceiveProps = typeof instance.componentDidReceiveProps !== 'function';
7037 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);
7038 var noComponentWillRecieveProps = typeof instance.componentWillRecieveProps !== 'function';
7039 warning_1(noComponentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name);
7040 var hasMutatedProps = instance.props !== workInProgress.pendingProps;
7041 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);
7042 var noInstanceDefaultProps = !instance.defaultProps;
7043 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);
7044 }
7045
7046 var state = instance.state;
7047 if (state && (typeof state !== 'object' || isArray(state))) {
7048 warning_1(false, '%s.state: must be set to an object or null', getComponentName(workInProgress));
7049 }
7050 if (typeof instance.getChildContext === 'function') {
7051 warning_1(typeof workInProgress.type.childContextTypes === 'object', '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', getComponentName(workInProgress));
7052 }
7053 }
7054
7055 function resetInputPointers(workInProgress, instance) {
7056 instance.props = workInProgress.memoizedProps;
7057 instance.state = workInProgress.memoizedState;
7058 }
7059
7060 function adoptClassInstance(workInProgress, instance) {
7061 instance.updater = updater;
7062 workInProgress.stateNode = instance;
7063 // The instance needs access to the fiber so that it can schedule updates
7064 set(instance, workInProgress);
7065 {
7066 instance._reactInternalInstance = fakeInternalInstance;
7067 }
7068 }
7069
7070 function constructClassInstance(workInProgress, props) {
7071 var ctor = workInProgress.type;
7072 var unmaskedContext = getUnmaskedContext(workInProgress);
7073 var needsContext = isContextConsumer(workInProgress);
7074 var context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject_1;
7075 var instance = new ctor(props, context);
7076 adoptClassInstance(workInProgress, instance);
7077
7078 // Cache unmasked context so we can avoid recreating masked context unless necessary.
7079 // ReactFiberContext usually updates this cache but can't for newly-created instances.
7080 if (needsContext) {
7081 cacheContext(workInProgress, unmaskedContext, context);
7082 }
7083
7084 return instance;
7085 }
7086
7087 function callComponentWillMount(workInProgress, instance) {
7088 startPhaseTimer(workInProgress, 'componentWillMount');
7089 var oldState = instance.state;
7090 instance.componentWillMount();
7091 stopPhaseTimer();
7092
7093 if (oldState !== instance.state) {
7094 {
7095 warning_1(false, '%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentName(workInProgress));
7096 }
7097 updater.enqueueReplaceState(instance, instance.state, null);
7098 }
7099 }
7100
7101 function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) {
7102 startPhaseTimer(workInProgress, 'componentWillReceiveProps');
7103 var oldState = instance.state;
7104 instance.componentWillReceiveProps(newProps, newContext);
7105 stopPhaseTimer();
7106
7107 // Simulate an async bailout/interruption by invoking lifecycle twice.
7108 if (debugRenderPhaseSideEffects) {
7109 instance.componentWillReceiveProps(newProps, newContext);
7110 }
7111
7112 if (instance.state !== oldState) {
7113 {
7114 var componentName = getComponentName(workInProgress) || 'Component';
7115 if (!didWarnAboutStateAssignmentForComponent[componentName]) {
7116 warning_1(false, '%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', componentName);
7117 didWarnAboutStateAssignmentForComponent[componentName] = true;
7118 }
7119 }
7120 updater.enqueueReplaceState(instance, instance.state, null);
7121 }
7122 }
7123
7124 // Invokes the mount life-cycles on a previously never rendered instance.
7125 function mountClassInstance(workInProgress, renderExpirationTime) {
7126 var current = workInProgress.alternate;
7127
7128 {
7129 checkClassInstance(workInProgress);
7130 }
7131
7132 var instance = workInProgress.stateNode;
7133 var state = instance.state || null;
7134 var props = workInProgress.pendingProps;
7135 var unmaskedContext = getUnmaskedContext(workInProgress);
7136
7137 instance.props = props;
7138 instance.state = workInProgress.memoizedState = state;
7139 instance.refs = emptyObject_1;
7140 instance.context = getMaskedContext(workInProgress, unmaskedContext);
7141
7142 if (enableAsyncSubtreeAPI && workInProgress.type != null && workInProgress.type.prototype != null && workInProgress.type.prototype.unstable_isAsyncReactComponent === true) {
7143 workInProgress.internalContextTag |= AsyncUpdates;
7144 }
7145
7146 if (typeof instance.componentWillMount === 'function') {
7147 callComponentWillMount(workInProgress, instance);
7148 // If we had additional state updates during this life-cycle, let's
7149 // process them now.
7150 var updateQueue = workInProgress.updateQueue;
7151 if (updateQueue !== null) {
7152 instance.state = processUpdateQueue(current, workInProgress, updateQueue, instance, props, renderExpirationTime);
7153 }
7154 }
7155 if (typeof instance.componentDidMount === 'function') {
7156 workInProgress.effectTag |= Update;
7157 }
7158 }
7159
7160 // Called on a preexisting class instance. Returns false if a resumed render
7161 // could be reused.
7162 // function resumeMountClassInstance(
7163 // workInProgress: Fiber,
7164 // priorityLevel: PriorityLevel,
7165 // ): boolean {
7166 // const instance = workInProgress.stateNode;
7167 // resetInputPointers(workInProgress, instance);
7168
7169 // let newState = workInProgress.memoizedState;
7170 // let newProps = workInProgress.pendingProps;
7171 // if (!newProps) {
7172 // // If there isn't any new props, then we'll reuse the memoized props.
7173 // // This could be from already completed work.
7174 // newProps = workInProgress.memoizedProps;
7175 // invariant(
7176 // newProps != null,
7177 // 'There should always be pending or memoized props. This error is ' +
7178 // 'likely caused by a bug in React. Please file an issue.',
7179 // );
7180 // }
7181 // const newUnmaskedContext = getUnmaskedContext(workInProgress);
7182 // const newContext = getMaskedContext(workInProgress, newUnmaskedContext);
7183
7184 // const oldContext = instance.context;
7185 // const oldProps = workInProgress.memoizedProps;
7186
7187 // if (
7188 // typeof instance.componentWillReceiveProps === 'function' &&
7189 // (oldProps !== newProps || oldContext !== newContext)
7190 // ) {
7191 // callComponentWillReceiveProps(
7192 // workInProgress,
7193 // instance,
7194 // newProps,
7195 // newContext,
7196 // );
7197 // }
7198
7199 // // Process the update queue before calling shouldComponentUpdate
7200 // const updateQueue = workInProgress.updateQueue;
7201 // if (updateQueue !== null) {
7202 // newState = processUpdateQueue(
7203 // workInProgress,
7204 // updateQueue,
7205 // instance,
7206 // newState,
7207 // newProps,
7208 // priorityLevel,
7209 // );
7210 // }
7211
7212 // // TODO: Should we deal with a setState that happened after the last
7213 // // componentWillMount and before this componentWillMount? Probably
7214 // // unsupported anyway.
7215
7216 // if (
7217 // !checkShouldComponentUpdate(
7218 // workInProgress,
7219 // workInProgress.memoizedProps,
7220 // newProps,
7221 // workInProgress.memoizedState,
7222 // newState,
7223 // newContext,
7224 // )
7225 // ) {
7226 // // Update the existing instance's state, props, and context pointers even
7227 // // though we're bailing out.
7228 // instance.props = newProps;
7229 // instance.state = newState;
7230 // instance.context = newContext;
7231 // return false;
7232 // }
7233
7234 // // Update the input pointers now so that they are correct when we call
7235 // // componentWillMount
7236 // instance.props = newProps;
7237 // instance.state = newState;
7238 // instance.context = newContext;
7239
7240 // if (typeof instance.componentWillMount === 'function') {
7241 // callComponentWillMount(workInProgress, instance);
7242 // // componentWillMount may have called setState. Process the update queue.
7243 // const newUpdateQueue = workInProgress.updateQueue;
7244 // if (newUpdateQueue !== null) {
7245 // newState = processUpdateQueue(
7246 // workInProgress,
7247 // newUpdateQueue,
7248 // instance,
7249 // newState,
7250 // newProps,
7251 // priorityLevel,
7252 // );
7253 // }
7254 // }
7255
7256 // if (typeof instance.componentDidMount === 'function') {
7257 // workInProgress.effectTag |= Update;
7258 // }
7259
7260 // instance.state = newState;
7261
7262 // return true;
7263 // }
7264
7265 // Invokes the update life-cycles and returns false if it shouldn't rerender.
7266 function updateClassInstance(current, workInProgress, renderExpirationTime) {
7267 var instance = workInProgress.stateNode;
7268 resetInputPointers(workInProgress, instance);
7269
7270 var oldProps = workInProgress.memoizedProps;
7271 var newProps = workInProgress.pendingProps;
7272 var oldContext = instance.context;
7273 var newUnmaskedContext = getUnmaskedContext(workInProgress);
7274 var newContext = getMaskedContext(workInProgress, newUnmaskedContext);
7275
7276 // Note: During these life-cycles, instance.props/instance.state are what
7277 // ever the previously attempted to render - not the "current". However,
7278 // during componentDidUpdate we pass the "current" props.
7279
7280 if (typeof instance.componentWillReceiveProps === 'function' && (oldProps !== newProps || oldContext !== newContext)) {
7281 callComponentWillReceiveProps(workInProgress, instance, newProps, newContext);
7282 }
7283
7284 // Compute the next state using the memoized state and the update queue.
7285 var oldState = workInProgress.memoizedState;
7286 // TODO: Previous state can be null.
7287 var newState = void 0;
7288 if (workInProgress.updateQueue !== null) {
7289 newState = processUpdateQueue(current, workInProgress, workInProgress.updateQueue, instance, newProps, renderExpirationTime);
7290 } else {
7291 newState = oldState;
7292 }
7293
7294 if (oldProps === newProps && oldState === newState && !hasContextChanged() && !(workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate)) {
7295 // If an update was already in progress, we should schedule an Update
7296 // effect even though we're bailing out, so that cWU/cDU are called.
7297 if (typeof instance.componentDidUpdate === 'function') {
7298 if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
7299 workInProgress.effectTag |= Update;
7300 }
7301 }
7302 return false;
7303 }
7304
7305 var shouldUpdate = checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext);
7306
7307 if (shouldUpdate) {
7308 if (typeof instance.componentWillUpdate === 'function') {
7309 startPhaseTimer(workInProgress, 'componentWillUpdate');
7310 instance.componentWillUpdate(newProps, newState, newContext);
7311 stopPhaseTimer();
7312
7313 // Simulate an async bailout/interruption by invoking lifecycle twice.
7314 if (debugRenderPhaseSideEffects) {
7315 instance.componentWillUpdate(newProps, newState, newContext);
7316 }
7317 }
7318 if (typeof instance.componentDidUpdate === 'function') {
7319 workInProgress.effectTag |= Update;
7320 }
7321 } else {
7322 // If an update was already in progress, we should schedule an Update
7323 // effect even though we're bailing out, so that cWU/cDU are called.
7324 if (typeof instance.componentDidUpdate === 'function') {
7325 if (oldProps !== current.memoizedProps || oldState !== current.memoizedState) {
7326 workInProgress.effectTag |= Update;
7327 }
7328 }
7329
7330 // If shouldComponentUpdate returned false, we should still update the
7331 // memoized props/state to indicate that this work can be reused.
7332 memoizeProps(workInProgress, newProps);
7333 memoizeState(workInProgress, newState);
7334 }
7335
7336 // Update the existing instance's state, props, and context pointers even
7337 // if shouldComponentUpdate returns false.
7338 instance.props = newProps;
7339 instance.state = newState;
7340 instance.context = newContext;
7341
7342 return shouldUpdate;
7343 }
7344
7345 return {
7346 adoptClassInstance: adoptClassInstance,
7347 constructClassInstance: constructClassInstance,
7348 mountClassInstance: mountClassInstance,
7349 // resumeMountClassInstance,
7350 updateClassInstance: updateClassInstance
7351 };
7352};
7353
7354var getCurrentFiberStackAddendum$2 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
7355
7356
7357var didWarnAboutMaps = void 0;
7358var ownerHasKeyUseWarning = void 0;
7359var ownerHasFunctionTypeWarning = void 0;
7360var warnForMissingKey = function (child) {};
7361
7362{
7363 didWarnAboutMaps = false;
7364 /**
7365 * Warn if there's no key explicitly set on dynamic arrays of children or
7366 * object keys are not valid. This allows us to keep track of children between
7367 * updates.
7368 */
7369 ownerHasKeyUseWarning = {};
7370 ownerHasFunctionTypeWarning = {};
7371
7372 warnForMissingKey = function (child) {
7373 if (child === null || typeof child !== 'object') {
7374 return;
7375 }
7376 if (!child._store || child._store.validated || child.key != null) {
7377 return;
7378 }
7379 !(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;
7380 child._store.validated = true;
7381
7382 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() || '');
7383 if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
7384 return;
7385 }
7386 ownerHasKeyUseWarning[currentComponentErrorInfo] = true;
7387
7388 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());
7389 };
7390}
7391
7392var isArray$1 = Array.isArray;
7393
7394function coerceRef(current, element) {
7395 var mixedRef = element.ref;
7396 if (mixedRef !== null && typeof mixedRef !== 'function') {
7397 if (element._owner) {
7398 var owner = element._owner;
7399 var inst = void 0;
7400 if (owner) {
7401 var ownerFiber = owner;
7402 !(ownerFiber.tag === ClassComponent) ? invariant_1(false, 'Stateless function components cannot have refs.') : void 0;
7403 inst = ownerFiber.stateNode;
7404 }
7405 !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;
7406 var stringRef = '' + mixedRef;
7407 // Check if previous string ref matches new string ref
7408 if (current !== null && current.ref !== null && current.ref._stringRef === stringRef) {
7409 return current.ref;
7410 }
7411 var ref = function (value) {
7412 var refs = inst.refs === emptyObject_1 ? inst.refs = {} : inst.refs;
7413 if (value === null) {
7414 delete refs[stringRef];
7415 } else {
7416 refs[stringRef] = value;
7417 }
7418 };
7419 ref._stringRef = stringRef;
7420 return ref;
7421 } else {
7422 !(typeof mixedRef === 'string') ? invariant_1(false, 'Expected ref to be a function or a string.') : void 0;
7423 !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;
7424 }
7425 }
7426 return mixedRef;
7427}
7428
7429function throwOnInvalidObjectType(returnFiber, newChild) {
7430 if (returnFiber.type !== 'textarea') {
7431 var addendum = '';
7432 {
7433 addendum = ' If you meant to render a collection of children, use an array ' + 'instead.' + (getCurrentFiberStackAddendum$2() || '');
7434 }
7435 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);
7436 }
7437}
7438
7439function warnOnFunctionType() {
7440 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() || '');
7441
7442 if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) {
7443 return;
7444 }
7445 ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true;
7446
7447 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() || '');
7448}
7449
7450// This wrapper function exists because I expect to clone the code in each path
7451// to be able to optimize each path individually by branching early. This needs
7452// a compiler or we can do it manually. Helpers that don't need this branching
7453// live outside of this function.
7454function ChildReconciler(shouldTrackSideEffects) {
7455 function deleteChild(returnFiber, childToDelete) {
7456 if (!shouldTrackSideEffects) {
7457 // Noop.
7458 return;
7459 }
7460 // Deletions are added in reversed order so we add it to the front.
7461 // At this point, the return fiber's effect list is empty except for
7462 // deletions, so we can just append the deletion to the list. The remaining
7463 // effects aren't added until the complete phase. Once we implement
7464 // resuming, this may not be true.
7465 var last = returnFiber.lastEffect;
7466 if (last !== null) {
7467 last.nextEffect = childToDelete;
7468 returnFiber.lastEffect = childToDelete;
7469 } else {
7470 returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
7471 }
7472 childToDelete.nextEffect = null;
7473 childToDelete.effectTag = Deletion;
7474 }
7475
7476 function deleteRemainingChildren(returnFiber, currentFirstChild) {
7477 if (!shouldTrackSideEffects) {
7478 // Noop.
7479 return null;
7480 }
7481
7482 // TODO: For the shouldClone case, this could be micro-optimized a bit by
7483 // assuming that after the first child we've already added everything.
7484 var childToDelete = currentFirstChild;
7485 while (childToDelete !== null) {
7486 deleteChild(returnFiber, childToDelete);
7487 childToDelete = childToDelete.sibling;
7488 }
7489 return null;
7490 }
7491
7492 function mapRemainingChildren(returnFiber, currentFirstChild) {
7493 // Add the remaining children to a temporary map so that we can find them by
7494 // keys quickly. Implicit (null) keys get added to this set with their index
7495 var existingChildren = new Map();
7496
7497 var existingChild = currentFirstChild;
7498 while (existingChild !== null) {
7499 if (existingChild.key !== null) {
7500 existingChildren.set(existingChild.key, existingChild);
7501 } else {
7502 existingChildren.set(existingChild.index, existingChild);
7503 }
7504 existingChild = existingChild.sibling;
7505 }
7506 return existingChildren;
7507 }
7508
7509 function useFiber(fiber, pendingProps, expirationTime) {
7510 // We currently set sibling to null and index to 0 here because it is easy
7511 // to forget to do before returning it. E.g. for the single child case.
7512 var clone = createWorkInProgress(fiber, pendingProps, expirationTime);
7513 clone.index = 0;
7514 clone.sibling = null;
7515 return clone;
7516 }
7517
7518 function placeChild(newFiber, lastPlacedIndex, newIndex) {
7519 newFiber.index = newIndex;
7520 if (!shouldTrackSideEffects) {
7521 // Noop.
7522 return lastPlacedIndex;
7523 }
7524 var current = newFiber.alternate;
7525 if (current !== null) {
7526 var oldIndex = current.index;
7527 if (oldIndex < lastPlacedIndex) {
7528 // This is a move.
7529 newFiber.effectTag = Placement;
7530 return lastPlacedIndex;
7531 } else {
7532 // This item can stay in place.
7533 return oldIndex;
7534 }
7535 } else {
7536 // This is an insertion.
7537 newFiber.effectTag = Placement;
7538 return lastPlacedIndex;
7539 }
7540 }
7541
7542 function placeSingleChild(newFiber) {
7543 // This is simpler for the single child case. We only need to do a
7544 // placement for inserting new children.
7545 if (shouldTrackSideEffects && newFiber.alternate === null) {
7546 newFiber.effectTag = Placement;
7547 }
7548 return newFiber;
7549 }
7550
7551 function updateTextNode(returnFiber, current, textContent, expirationTime) {
7552 if (current === null || current.tag !== HostText) {
7553 // Insert
7554 var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime);
7555 created['return'] = returnFiber;
7556 return created;
7557 } else {
7558 // Update
7559 var existing = useFiber(current, textContent, expirationTime);
7560 existing['return'] = returnFiber;
7561 return existing;
7562 }
7563 }
7564
7565 function updateElement(returnFiber, current, element, expirationTime) {
7566 if (current !== null && current.type === element.type) {
7567 // Move based on index
7568 var existing = useFiber(current, element.props, expirationTime);
7569 existing.ref = coerceRef(current, element);
7570 existing['return'] = returnFiber;
7571 {
7572 existing._debugSource = element._source;
7573 existing._debugOwner = element._owner;
7574 }
7575 return existing;
7576 } else {
7577 // Insert
7578 var created = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime);
7579 created.ref = coerceRef(current, element);
7580 created['return'] = returnFiber;
7581 return created;
7582 }
7583 }
7584
7585 function updatePortal(returnFiber, current, portal, expirationTime) {
7586 if (current === null || current.tag !== HostPortal || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) {
7587 // Insert
7588 var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime);
7589 created['return'] = returnFiber;
7590 return created;
7591 } else {
7592 // Update
7593 var existing = useFiber(current, portal.children || [], expirationTime);
7594 existing['return'] = returnFiber;
7595 return existing;
7596 }
7597 }
7598
7599 function updateFragment(returnFiber, current, fragment, expirationTime, key) {
7600 if (current === null || current.tag !== Fragment) {
7601 // Insert
7602 var created = createFiberFromFragment(fragment, returnFiber.internalContextTag, expirationTime, key);
7603 created['return'] = returnFiber;
7604 return created;
7605 } else {
7606 // Update
7607 var existing = useFiber(current, fragment, expirationTime);
7608 existing['return'] = returnFiber;
7609 return existing;
7610 }
7611 }
7612
7613 function createChild(returnFiber, newChild, expirationTime) {
7614 if (typeof newChild === 'string' || typeof newChild === 'number') {
7615 // Text nodes don't have keys. If the previous node is implicitly keyed
7616 // we can continue to replace it without aborting even if it is not a text
7617 // node.
7618 var created = createFiberFromText('' + newChild, returnFiber.internalContextTag, expirationTime);
7619 created['return'] = returnFiber;
7620 return created;
7621 }
7622
7623 if (typeof newChild === 'object' && newChild !== null) {
7624 switch (newChild.$$typeof) {
7625 case REACT_ELEMENT_TYPE:
7626 {
7627 var _created = createFiberFromElement(newChild, returnFiber.internalContextTag, expirationTime);
7628 _created.ref = coerceRef(null, newChild);
7629 _created['return'] = returnFiber;
7630 return _created;
7631 }
7632 case REACT_PORTAL_TYPE:
7633 {
7634 var _created2 = createFiberFromPortal(newChild, returnFiber.internalContextTag, expirationTime);
7635 _created2['return'] = returnFiber;
7636 return _created2;
7637 }
7638 }
7639
7640 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7641 var _created3 = createFiberFromFragment(newChild, returnFiber.internalContextTag, expirationTime, null);
7642 _created3['return'] = returnFiber;
7643 return _created3;
7644 }
7645
7646 throwOnInvalidObjectType(returnFiber, newChild);
7647 }
7648
7649 {
7650 if (typeof newChild === 'function') {
7651 warnOnFunctionType();
7652 }
7653 }
7654
7655 return null;
7656 }
7657
7658 function updateSlot(returnFiber, oldFiber, newChild, expirationTime) {
7659 // Update the fiber if the keys match, otherwise return null.
7660
7661 var key = oldFiber !== null ? oldFiber.key : null;
7662
7663 if (typeof newChild === 'string' || typeof newChild === 'number') {
7664 // Text nodes don't have keys. If the previous node is implicitly keyed
7665 // we can continue to replace it without aborting even if it is not a text
7666 // node.
7667 if (key !== null) {
7668 return null;
7669 }
7670 return updateTextNode(returnFiber, oldFiber, '' + newChild, expirationTime);
7671 }
7672
7673 if (typeof newChild === 'object' && newChild !== null) {
7674 switch (newChild.$$typeof) {
7675 case REACT_ELEMENT_TYPE:
7676 {
7677 if (newChild.key === key) {
7678 if (newChild.type === REACT_FRAGMENT_TYPE) {
7679 return updateFragment(returnFiber, oldFiber, newChild.props.children, expirationTime, key);
7680 }
7681 return updateElement(returnFiber, oldFiber, newChild, expirationTime);
7682 } else {
7683 return null;
7684 }
7685 }
7686 case REACT_PORTAL_TYPE:
7687 {
7688 if (newChild.key === key) {
7689 return updatePortal(returnFiber, oldFiber, newChild, expirationTime);
7690 } else {
7691 return null;
7692 }
7693 }
7694 }
7695
7696 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7697 if (key !== null) {
7698 return null;
7699 }
7700
7701 return updateFragment(returnFiber, oldFiber, newChild, expirationTime, null);
7702 }
7703
7704 throwOnInvalidObjectType(returnFiber, newChild);
7705 }
7706
7707 {
7708 if (typeof newChild === 'function') {
7709 warnOnFunctionType();
7710 }
7711 }
7712
7713 return null;
7714 }
7715
7716 function updateFromMap(existingChildren, returnFiber, newIdx, newChild, expirationTime) {
7717 if (typeof newChild === 'string' || typeof newChild === 'number') {
7718 // Text nodes don't have keys, so we neither have to check the old nor
7719 // new node for the key. If both are text nodes, they match.
7720 var matchedFiber = existingChildren.get(newIdx) || null;
7721 return updateTextNode(returnFiber, matchedFiber, '' + newChild, expirationTime);
7722 }
7723
7724 if (typeof newChild === 'object' && newChild !== null) {
7725 switch (newChild.$$typeof) {
7726 case REACT_ELEMENT_TYPE:
7727 {
7728 var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
7729 if (newChild.type === REACT_FRAGMENT_TYPE) {
7730 return updateFragment(returnFiber, _matchedFiber, newChild.props.children, expirationTime, newChild.key);
7731 }
7732 return updateElement(returnFiber, _matchedFiber, newChild, expirationTime);
7733 }
7734 case REACT_PORTAL_TYPE:
7735 {
7736 var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null;
7737 return updatePortal(returnFiber, _matchedFiber2, newChild, expirationTime);
7738 }
7739 }
7740
7741 if (isArray$1(newChild) || getIteratorFn(newChild)) {
7742 var _matchedFiber3 = existingChildren.get(newIdx) || null;
7743 return updateFragment(returnFiber, _matchedFiber3, newChild, expirationTime, null);
7744 }
7745
7746 throwOnInvalidObjectType(returnFiber, newChild);
7747 }
7748
7749 {
7750 if (typeof newChild === 'function') {
7751 warnOnFunctionType();
7752 }
7753 }
7754
7755 return null;
7756 }
7757
7758 /**
7759 * Warns if there is a duplicate or missing key
7760 */
7761 function warnOnInvalidKey(child, knownKeys) {
7762 {
7763 if (typeof child !== 'object' || child === null) {
7764 return knownKeys;
7765 }
7766 switch (child.$$typeof) {
7767 case REACT_ELEMENT_TYPE:
7768 case REACT_PORTAL_TYPE:
7769 warnForMissingKey(child);
7770 var key = child.key;
7771 if (typeof key !== 'string') {
7772 break;
7773 }
7774 if (knownKeys === null) {
7775 knownKeys = new Set();
7776 knownKeys.add(key);
7777 break;
7778 }
7779 if (!knownKeys.has(key)) {
7780 knownKeys.add(key);
7781 break;
7782 }
7783 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());
7784 break;
7785 default:
7786 break;
7787 }
7788 }
7789 return knownKeys;
7790 }
7791
7792 function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, expirationTime) {
7793 // This algorithm can't optimize by searching from boths ends since we
7794 // don't have backpointers on fibers. I'm trying to see how far we can get
7795 // with that model. If it ends up not being worth the tradeoffs, we can
7796 // add it later.
7797
7798 // Even with a two ended optimization, we'd want to optimize for the case
7799 // where there are few changes and brute force the comparison instead of
7800 // going for the Map. It'd like to explore hitting that path first in
7801 // forward-only mode and only go for the Map once we notice that we need
7802 // lots of look ahead. This doesn't handle reversal as well as two ended
7803 // search but that's unusual. Besides, for the two ended optimization to
7804 // work on Iterables, we'd need to copy the whole set.
7805
7806 // In this first iteration, we'll just live with hitting the bad case
7807 // (adding everything to a Map) in for every insert/move.
7808
7809 // If you change this code, also update reconcileChildrenIterator() which
7810 // uses the same algorithm.
7811
7812 {
7813 // First, validate keys.
7814 var knownKeys = null;
7815 for (var i = 0; i < newChildren.length; i++) {
7816 var child = newChildren[i];
7817 knownKeys = warnOnInvalidKey(child, knownKeys);
7818 }
7819 }
7820
7821 var resultingFirstChild = null;
7822 var previousNewFiber = null;
7823
7824 var oldFiber = currentFirstChild;
7825 var lastPlacedIndex = 0;
7826 var newIdx = 0;
7827 var nextOldFiber = null;
7828 for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) {
7829 if (oldFiber.index > newIdx) {
7830 nextOldFiber = oldFiber;
7831 oldFiber = null;
7832 } else {
7833 nextOldFiber = oldFiber.sibling;
7834 }
7835 var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], expirationTime);
7836 if (newFiber === null) {
7837 // TODO: This breaks on empty slots like null children. That's
7838 // unfortunate because it triggers the slow path all the time. We need
7839 // a better way to communicate whether this was a miss or null,
7840 // boolean, undefined, etc.
7841 if (oldFiber === null) {
7842 oldFiber = nextOldFiber;
7843 }
7844 break;
7845 }
7846 if (shouldTrackSideEffects) {
7847 if (oldFiber && newFiber.alternate === null) {
7848 // We matched the slot, but we didn't reuse the existing fiber, so we
7849 // need to delete the existing child.
7850 deleteChild(returnFiber, oldFiber);
7851 }
7852 }
7853 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
7854 if (previousNewFiber === null) {
7855 // TODO: Move out of the loop. This only happens for the first run.
7856 resultingFirstChild = newFiber;
7857 } else {
7858 // TODO: Defer siblings if we're not at the right index for this slot.
7859 // I.e. if we had null values before, then we want to defer this
7860 // for each null value. However, we also don't want to call updateSlot
7861 // with the previous one.
7862 previousNewFiber.sibling = newFiber;
7863 }
7864 previousNewFiber = newFiber;
7865 oldFiber = nextOldFiber;
7866 }
7867
7868 if (newIdx === newChildren.length) {
7869 // We've reached the end of the new children. We can delete the rest.
7870 deleteRemainingChildren(returnFiber, oldFiber);
7871 return resultingFirstChild;
7872 }
7873
7874 if (oldFiber === null) {
7875 // If we don't have any more existing children we can choose a fast path
7876 // since the rest will all be insertions.
7877 for (; newIdx < newChildren.length; newIdx++) {
7878 var _newFiber = createChild(returnFiber, newChildren[newIdx], expirationTime);
7879 if (!_newFiber) {
7880 continue;
7881 }
7882 lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx);
7883 if (previousNewFiber === null) {
7884 // TODO: Move out of the loop. This only happens for the first run.
7885 resultingFirstChild = _newFiber;
7886 } else {
7887 previousNewFiber.sibling = _newFiber;
7888 }
7889 previousNewFiber = _newFiber;
7890 }
7891 return resultingFirstChild;
7892 }
7893
7894 // Add all children to a key map for quick lookups.
7895 var existingChildren = mapRemainingChildren(returnFiber, oldFiber);
7896
7897 // Keep scanning and use the map to restore deleted items as moves.
7898 for (; newIdx < newChildren.length; newIdx++) {
7899 var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], expirationTime);
7900 if (_newFiber2) {
7901 if (shouldTrackSideEffects) {
7902 if (_newFiber2.alternate !== null) {
7903 // The new fiber is a work in progress, but if there exists a
7904 // current, that means that we reused the fiber. We need to delete
7905 // it from the child list so that we don't add it to the deletion
7906 // list.
7907 existingChildren['delete'](_newFiber2.key === null ? newIdx : _newFiber2.key);
7908 }
7909 }
7910 lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx);
7911 if (previousNewFiber === null) {
7912 resultingFirstChild = _newFiber2;
7913 } else {
7914 previousNewFiber.sibling = _newFiber2;
7915 }
7916 previousNewFiber = _newFiber2;
7917 }
7918 }
7919
7920 if (shouldTrackSideEffects) {
7921 // Any existing children that weren't consumed above were deleted. We need
7922 // to add them to the deletion list.
7923 existingChildren.forEach(function (child) {
7924 return deleteChild(returnFiber, child);
7925 });
7926 }
7927
7928 return resultingFirstChild;
7929 }
7930
7931 function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, expirationTime) {
7932 // This is the same implementation as reconcileChildrenArray(),
7933 // but using the iterator instead.
7934
7935 var iteratorFn = getIteratorFn(newChildrenIterable);
7936 !(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;
7937
7938 {
7939 // Warn about using Maps as children
7940 if (typeof newChildrenIterable.entries === 'function') {
7941 var possibleMap = newChildrenIterable;
7942 if (possibleMap.entries === iteratorFn) {
7943 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());
7944 didWarnAboutMaps = true;
7945 }
7946 }
7947
7948 // First, validate keys.
7949 // We'll get a different iterator later for the main pass.
7950 var _newChildren = iteratorFn.call(newChildrenIterable);
7951 if (_newChildren) {
7952 var knownKeys = null;
7953 var _step = _newChildren.next();
7954 for (; !_step.done; _step = _newChildren.next()) {
7955 var child = _step.value;
7956 knownKeys = warnOnInvalidKey(child, knownKeys);
7957 }
7958 }
7959 }
7960
7961 var newChildren = iteratorFn.call(newChildrenIterable);
7962 !(newChildren != null) ? invariant_1(false, 'An iterable object provided no iterator.') : void 0;
7963
7964 var resultingFirstChild = null;
7965 var previousNewFiber = null;
7966
7967 var oldFiber = currentFirstChild;
7968 var lastPlacedIndex = 0;
7969 var newIdx = 0;
7970 var nextOldFiber = null;
7971
7972 var step = newChildren.next();
7973 for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) {
7974 if (oldFiber.index > newIdx) {
7975 nextOldFiber = oldFiber;
7976 oldFiber = null;
7977 } else {
7978 nextOldFiber = oldFiber.sibling;
7979 }
7980 var newFiber = updateSlot(returnFiber, oldFiber, step.value, expirationTime);
7981 if (newFiber === null) {
7982 // TODO: This breaks on empty slots like null children. That's
7983 // unfortunate because it triggers the slow path all the time. We need
7984 // a better way to communicate whether this was a miss or null,
7985 // boolean, undefined, etc.
7986 if (!oldFiber) {
7987 oldFiber = nextOldFiber;
7988 }
7989 break;
7990 }
7991 if (shouldTrackSideEffects) {
7992 if (oldFiber && newFiber.alternate === null) {
7993 // We matched the slot, but we didn't reuse the existing fiber, so we
7994 // need to delete the existing child.
7995 deleteChild(returnFiber, oldFiber);
7996 }
7997 }
7998 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx);
7999 if (previousNewFiber === null) {
8000 // TODO: Move out of the loop. This only happens for the first run.
8001 resultingFirstChild = newFiber;
8002 } else {
8003 // TODO: Defer siblings if we're not at the right index for this slot.
8004 // I.e. if we had null values before, then we want to defer this
8005 // for each null value. However, we also don't want to call updateSlot
8006 // with the previous one.
8007 previousNewFiber.sibling = newFiber;
8008 }
8009 previousNewFiber = newFiber;
8010 oldFiber = nextOldFiber;
8011 }
8012
8013 if (step.done) {
8014 // We've reached the end of the new children. We can delete the rest.
8015 deleteRemainingChildren(returnFiber, oldFiber);
8016 return resultingFirstChild;
8017 }
8018
8019 if (oldFiber === null) {
8020 // If we don't have any more existing children we can choose a fast path
8021 // since the rest will all be insertions.
8022 for (; !step.done; newIdx++, step = newChildren.next()) {
8023 var _newFiber3 = createChild(returnFiber, step.value, expirationTime);
8024 if (_newFiber3 === null) {
8025 continue;
8026 }
8027 lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx);
8028 if (previousNewFiber === null) {
8029 // TODO: Move out of the loop. This only happens for the first run.
8030 resultingFirstChild = _newFiber3;
8031 } else {
8032 previousNewFiber.sibling = _newFiber3;
8033 }
8034 previousNewFiber = _newFiber3;
8035 }
8036 return resultingFirstChild;
8037 }
8038
8039 // Add all children to a key map for quick lookups.
8040 var existingChildren = mapRemainingChildren(returnFiber, oldFiber);
8041
8042 // Keep scanning and use the map to restore deleted items as moves.
8043 for (; !step.done; newIdx++, step = newChildren.next()) {
8044 var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, expirationTime);
8045 if (_newFiber4 !== null) {
8046 if (shouldTrackSideEffects) {
8047 if (_newFiber4.alternate !== null) {
8048 // The new fiber is a work in progress, but if there exists a
8049 // current, that means that we reused the fiber. We need to delete
8050 // it from the child list so that we don't add it to the deletion
8051 // list.
8052 existingChildren['delete'](_newFiber4.key === null ? newIdx : _newFiber4.key);
8053 }
8054 }
8055 lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx);
8056 if (previousNewFiber === null) {
8057 resultingFirstChild = _newFiber4;
8058 } else {
8059 previousNewFiber.sibling = _newFiber4;
8060 }
8061 previousNewFiber = _newFiber4;
8062 }
8063 }
8064
8065 if (shouldTrackSideEffects) {
8066 // Any existing children that weren't consumed above were deleted. We need
8067 // to add them to the deletion list.
8068 existingChildren.forEach(function (child) {
8069 return deleteChild(returnFiber, child);
8070 });
8071 }
8072
8073 return resultingFirstChild;
8074 }
8075
8076 function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, expirationTime) {
8077 // There's no need to check for keys on text nodes since we don't have a
8078 // way to define them.
8079 if (currentFirstChild !== null && currentFirstChild.tag === HostText) {
8080 // We already have an existing node so let's just update it and delete
8081 // the rest.
8082 deleteRemainingChildren(returnFiber, currentFirstChild.sibling);
8083 var existing = useFiber(currentFirstChild, textContent, expirationTime);
8084 existing['return'] = returnFiber;
8085 return existing;
8086 }
8087 // The existing first child is not a text node so we need to create one
8088 // and delete the existing ones.
8089 deleteRemainingChildren(returnFiber, currentFirstChild);
8090 var created = createFiberFromText(textContent, returnFiber.internalContextTag, expirationTime);
8091 created['return'] = returnFiber;
8092 return created;
8093 }
8094
8095 function reconcileSingleElement(returnFiber, currentFirstChild, element, expirationTime) {
8096 var key = element.key;
8097 var child = currentFirstChild;
8098 while (child !== null) {
8099 // TODO: If key === null and child.key === null, then this only applies to
8100 // the first item in the list.
8101 if (child.key === key) {
8102 if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.type === element.type) {
8103 deleteRemainingChildren(returnFiber, child.sibling);
8104 var existing = useFiber(child, element.type === REACT_FRAGMENT_TYPE ? element.props.children : element.props, expirationTime);
8105 existing.ref = coerceRef(child, element);
8106 existing['return'] = returnFiber;
8107 {
8108 existing._debugSource = element._source;
8109 existing._debugOwner = element._owner;
8110 }
8111 return existing;
8112 } else {
8113 deleteRemainingChildren(returnFiber, child);
8114 break;
8115 }
8116 } else {
8117 deleteChild(returnFiber, child);
8118 }
8119 child = child.sibling;
8120 }
8121
8122 if (element.type === REACT_FRAGMENT_TYPE) {
8123 var created = createFiberFromFragment(element.props.children, returnFiber.internalContextTag, expirationTime, element.key);
8124 created['return'] = returnFiber;
8125 return created;
8126 } else {
8127 var _created4 = createFiberFromElement(element, returnFiber.internalContextTag, expirationTime);
8128 _created4.ref = coerceRef(currentFirstChild, element);
8129 _created4['return'] = returnFiber;
8130 return _created4;
8131 }
8132 }
8133
8134 function reconcileSinglePortal(returnFiber, currentFirstChild, portal, expirationTime) {
8135 var key = portal.key;
8136 var child = currentFirstChild;
8137 while (child !== null) {
8138 // TODO: If key === null and child.key === null, then this only applies to
8139 // the first item in the list.
8140 if (child.key === key) {
8141 if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) {
8142 deleteRemainingChildren(returnFiber, child.sibling);
8143 var existing = useFiber(child, portal.children || [], expirationTime);
8144 existing['return'] = returnFiber;
8145 return existing;
8146 } else {
8147 deleteRemainingChildren(returnFiber, child);
8148 break;
8149 }
8150 } else {
8151 deleteChild(returnFiber, child);
8152 }
8153 child = child.sibling;
8154 }
8155
8156 var created = createFiberFromPortal(portal, returnFiber.internalContextTag, expirationTime);
8157 created['return'] = returnFiber;
8158 return created;
8159 }
8160
8161 // This API will tag the children with the side-effect of the reconciliation
8162 // itself. They will be added to the side-effect list as we pass through the
8163 // children and the parent.
8164 function reconcileChildFibers(returnFiber, currentFirstChild, newChild, expirationTime) {
8165 // This function is not recursive.
8166 // If the top level item is an array, we treat it as a set of children,
8167 // not as a fragment. Nested arrays on the other hand will be treated as
8168 // fragment nodes. Recursion happens at the normal flow.
8169
8170 // Handle top level unkeyed fragments as if they were arrays.
8171 // This leads to an ambiguity between <>{[...]}</> and <>...</>.
8172 // We treat the ambiguous cases above the same.
8173 if (typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null) {
8174 newChild = newChild.props.children;
8175 }
8176
8177 // Handle object types
8178 var isObject = typeof newChild === 'object' && newChild !== null;
8179
8180 if (isObject) {
8181 switch (newChild.$$typeof) {
8182 case REACT_ELEMENT_TYPE:
8183 return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, expirationTime));
8184 case REACT_PORTAL_TYPE:
8185 return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, expirationTime));
8186 }
8187 }
8188
8189 if (typeof newChild === 'string' || typeof newChild === 'number') {
8190 return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, expirationTime));
8191 }
8192
8193 if (isArray$1(newChild)) {
8194 return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, expirationTime);
8195 }
8196
8197 if (getIteratorFn(newChild)) {
8198 return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, expirationTime);
8199 }
8200
8201 if (isObject) {
8202 throwOnInvalidObjectType(returnFiber, newChild);
8203 }
8204
8205 {
8206 if (typeof newChild === 'function') {
8207 warnOnFunctionType();
8208 }
8209 }
8210 if (typeof newChild === 'undefined') {
8211 // If the new child is undefined, and the return fiber is a composite
8212 // component, throw an error. If Fiber return types are disabled,
8213 // we already threw above.
8214 switch (returnFiber.tag) {
8215 case ClassComponent:
8216 {
8217 {
8218 var instance = returnFiber.stateNode;
8219 if (instance.render._isMockFunction) {
8220 // We allow auto-mocks to proceed as if they're returning null.
8221 break;
8222 }
8223 }
8224 }
8225 // Intentionally fall through to the next case, which handles both
8226 // functions and classes
8227 // eslint-disable-next-lined no-fallthrough
8228 case FunctionalComponent:
8229 {
8230 var Component = returnFiber.type;
8231 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');
8232 }
8233 }
8234 }
8235
8236 // Remaining cases are all treated as empty.
8237 return deleteRemainingChildren(returnFiber, currentFirstChild);
8238 }
8239
8240 return reconcileChildFibers;
8241}
8242
8243var reconcileChildFibers = ChildReconciler(true);
8244var mountChildFibers = ChildReconciler(false);
8245
8246function cloneChildFibers(current, workInProgress) {
8247 !(current === null || workInProgress.child === current.child) ? invariant_1(false, 'Resuming work not yet implemented.') : void 0;
8248
8249 if (workInProgress.child === null) {
8250 return;
8251 }
8252
8253 var currentChild = workInProgress.child;
8254 var newChild = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
8255 workInProgress.child = newChild;
8256
8257 newChild['return'] = workInProgress;
8258 while (currentChild.sibling !== null) {
8259 currentChild = currentChild.sibling;
8260 newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps, currentChild.expirationTime);
8261 newChild['return'] = workInProgress;
8262 }
8263 newChild.sibling = null;
8264}
8265
8266var warnedAboutStatelessRefs = void 0;
8267var didWarnAboutBadClass = void 0;
8268
8269{
8270 warnedAboutStatelessRefs = {};
8271 didWarnAboutBadClass = {};
8272}
8273
8274var ReactFiberBeginWork = function (config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber) {
8275 var shouldSetTextContent = config.shouldSetTextContent,
8276 shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree;
8277 var pushHostContext = hostContext.pushHostContext,
8278 pushHostContainer = hostContext.pushHostContainer;
8279 var enterHydrationState = hydrationContext.enterHydrationState,
8280 resetHydrationState = hydrationContext.resetHydrationState,
8281 tryToClaimNextHydratableInstance = hydrationContext.tryToClaimNextHydratableInstance;
8282
8283 var _ReactFiberClassCompo = ReactFiberClassComponent(scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState),
8284 adoptClassInstance = _ReactFiberClassCompo.adoptClassInstance,
8285 constructClassInstance = _ReactFiberClassCompo.constructClassInstance,
8286 mountClassInstance = _ReactFiberClassCompo.mountClassInstance,
8287 updateClassInstance = _ReactFiberClassCompo.updateClassInstance;
8288
8289 // TODO: Remove this and use reconcileChildrenAtExpirationTime directly.
8290
8291
8292 function reconcileChildren(current, workInProgress, nextChildren) {
8293 reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, workInProgress.expirationTime);
8294 }
8295
8296 function reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, renderExpirationTime) {
8297 if (current === null) {
8298 // If this is a fresh new component that hasn't been rendered yet, we
8299 // won't update its child set by applying minimal side-effects. Instead,
8300 // we will add them all to the child before it gets rendered. That means
8301 // we can optimize this reconciliation pass by not tracking side-effects.
8302 workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
8303 } else {
8304 // If the current child is the same as the work in progress, it means that
8305 // we haven't yet started any work on these children. Therefore, we use
8306 // the clone algorithm to create a copy of all the current children.
8307
8308 // If we had any progressed work already, that is invalid at this point so
8309 // let's throw it out.
8310 workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderExpirationTime);
8311 }
8312 }
8313
8314 function updateFragment(current, workInProgress) {
8315 var nextChildren = workInProgress.pendingProps;
8316 if (hasContextChanged()) {
8317 // Normally we can bail out on props equality but if context has changed
8318 // we don't do the bailout and we have to reuse existing props instead.
8319 } else if (nextChildren === null || workInProgress.memoizedProps === nextChildren) {
8320 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8321 }
8322 reconcileChildren(current, workInProgress, nextChildren);
8323 memoizeProps(workInProgress, nextChildren);
8324 return workInProgress.child;
8325 }
8326
8327 function markRef(current, workInProgress) {
8328 var ref = workInProgress.ref;
8329 if (ref !== null && (!current || current.ref !== ref)) {
8330 // Schedule a Ref effect
8331 workInProgress.effectTag |= Ref;
8332 }
8333 }
8334
8335 function updateFunctionalComponent(current, workInProgress) {
8336 var fn = workInProgress.type;
8337 var nextProps = workInProgress.pendingProps;
8338
8339 if (hasContextChanged()) {
8340 // Normally we can bail out on props equality but if context has changed
8341 // we don't do the bailout and we have to reuse existing props instead.
8342 } else {
8343 if (workInProgress.memoizedProps === nextProps) {
8344 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8345 }
8346 // TODO: consider bringing fn.shouldComponentUpdate() back.
8347 // It used to be here.
8348 }
8349
8350 var unmaskedContext = getUnmaskedContext(workInProgress);
8351 var context = getMaskedContext(workInProgress, unmaskedContext);
8352
8353 var nextChildren = void 0;
8354
8355 {
8356 ReactCurrentOwner.current = workInProgress;
8357 ReactDebugCurrentFiber.setCurrentPhase('render');
8358 nextChildren = fn(nextProps, context);
8359 ReactDebugCurrentFiber.setCurrentPhase(null);
8360 }
8361 // React DevTools reads this flag.
8362 workInProgress.effectTag |= PerformedWork;
8363 reconcileChildren(current, workInProgress, nextChildren);
8364 memoizeProps(workInProgress, nextProps);
8365 return workInProgress.child;
8366 }
8367
8368 function updateClassComponent(current, workInProgress, renderExpirationTime) {
8369 // Push context providers early to prevent context stack mismatches.
8370 // During mounting we don't know the child context yet as the instance doesn't exist.
8371 // We will invalidate the child context in finishClassComponent() right after rendering.
8372 var hasContext = pushContextProvider(workInProgress);
8373
8374 var shouldUpdate = void 0;
8375 if (current === null) {
8376 if (!workInProgress.stateNode) {
8377 // In the initial pass we might need to construct the instance.
8378 constructClassInstance(workInProgress, workInProgress.pendingProps);
8379 mountClassInstance(workInProgress, renderExpirationTime);
8380
8381 // Simulate an async bailout/interruption by invoking lifecycle twice.
8382 // We do this here rather than inside of ReactFiberClassComponent,
8383 // To more realistically simulate the interruption behavior of async,
8384 // Which would never call componentWillMount() twice on the same instance.
8385 if (debugRenderPhaseSideEffects) {
8386 constructClassInstance(workInProgress, workInProgress.pendingProps);
8387 mountClassInstance(workInProgress, renderExpirationTime);
8388 }
8389
8390 shouldUpdate = true;
8391 } else {
8392 invariant_1(false, 'Resuming work not yet implemented.');
8393 // In a resume, we'll already have an instance we can reuse.
8394 // shouldUpdate = resumeMountClassInstance(workInProgress, renderExpirationTime);
8395 }
8396 } else {
8397 shouldUpdate = updateClassInstance(current, workInProgress, renderExpirationTime);
8398 }
8399 return finishClassComponent(current, workInProgress, shouldUpdate, hasContext);
8400 }
8401
8402 function finishClassComponent(current, workInProgress, shouldUpdate, hasContext) {
8403 // Refs should update even if shouldComponentUpdate returns false
8404 markRef(current, workInProgress);
8405
8406 if (!shouldUpdate) {
8407 // Context providers should defer to sCU for rendering
8408 if (hasContext) {
8409 invalidateContextProvider(workInProgress, false);
8410 }
8411
8412 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8413 }
8414
8415 var instance = workInProgress.stateNode;
8416
8417 // Rerender
8418 ReactCurrentOwner.current = workInProgress;
8419 var nextChildren = void 0;
8420 {
8421 ReactDebugCurrentFiber.setCurrentPhase('render');
8422 nextChildren = instance.render();
8423 if (debugRenderPhaseSideEffects) {
8424 instance.render();
8425 }
8426 ReactDebugCurrentFiber.setCurrentPhase(null);
8427 }
8428 // React DevTools reads this flag.
8429 workInProgress.effectTag |= PerformedWork;
8430 reconcileChildren(current, workInProgress, nextChildren);
8431 // Memoize props and state using the values we just used to render.
8432 // TODO: Restructure so we never read values from the instance.
8433 memoizeState(workInProgress, instance.state);
8434 memoizeProps(workInProgress, instance.props);
8435
8436 // The context might have changed so we need to recalculate it.
8437 if (hasContext) {
8438 invalidateContextProvider(workInProgress, true);
8439 }
8440
8441 return workInProgress.child;
8442 }
8443
8444 function pushHostRootContext(workInProgress) {
8445 var root = workInProgress.stateNode;
8446 if (root.pendingContext) {
8447 pushTopLevelContextObject(workInProgress, root.pendingContext, root.pendingContext !== root.context);
8448 } else if (root.context) {
8449 // Should always be set
8450 pushTopLevelContextObject(workInProgress, root.context, false);
8451 }
8452 pushHostContainer(workInProgress, root.containerInfo);
8453 }
8454
8455 function updateHostRoot(current, workInProgress, renderExpirationTime) {
8456 pushHostRootContext(workInProgress);
8457 var updateQueue = workInProgress.updateQueue;
8458 if (updateQueue !== null) {
8459 var prevState = workInProgress.memoizedState;
8460 var state = processUpdateQueue(current, workInProgress, updateQueue, null, null, renderExpirationTime);
8461 if (prevState === state) {
8462 // If the state is the same as before, that's a bailout because we had
8463 // no work that expires at this time.
8464 resetHydrationState();
8465 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8466 }
8467 var element = state.element;
8468 var root = workInProgress.stateNode;
8469 if ((current === null || current.child === null) && root.hydrate && enterHydrationState(workInProgress)) {
8470 // If we don't have any current children this might be the first pass.
8471 // We always try to hydrate. If this isn't a hydration pass there won't
8472 // be any children to hydrate which is effectively the same thing as
8473 // not hydrating.
8474
8475 // This is a bit of a hack. We track the host root as a placement to
8476 // know that we're currently in a mounting state. That way isMounted
8477 // works as expected. We must reset this before committing.
8478 // TODO: Delete this when we delete isMounted and findDOMNode.
8479 workInProgress.effectTag |= Placement;
8480
8481 // Ensure that children mount into this root without tracking
8482 // side-effects. This ensures that we don't store Placement effects on
8483 // nodes that will be hydrated.
8484 workInProgress.child = mountChildFibers(workInProgress, null, element, renderExpirationTime);
8485 } else {
8486 // Otherwise reset hydration state in case we aborted and resumed another
8487 // root.
8488 resetHydrationState();
8489 reconcileChildren(current, workInProgress, element);
8490 }
8491 memoizeState(workInProgress, state);
8492 return workInProgress.child;
8493 }
8494 resetHydrationState();
8495 // If there is no update queue, that's a bailout because the root has no props.
8496 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8497 }
8498
8499 function updateHostComponent(current, workInProgress, renderExpirationTime) {
8500 pushHostContext(workInProgress);
8501
8502 if (current === null) {
8503 tryToClaimNextHydratableInstance(workInProgress);
8504 }
8505
8506 var type = workInProgress.type;
8507 var memoizedProps = workInProgress.memoizedProps;
8508 var nextProps = workInProgress.pendingProps;
8509 var prevProps = current !== null ? current.memoizedProps : null;
8510
8511 if (hasContextChanged()) {
8512 // Normally we can bail out on props equality but if context has changed
8513 // we don't do the bailout and we have to reuse existing props instead.
8514 } else if (memoizedProps === nextProps) {
8515 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8516 }
8517
8518 var nextChildren = nextProps.children;
8519 var isDirectTextChild = shouldSetTextContent(type, nextProps);
8520
8521 if (isDirectTextChild) {
8522 // We special case a direct text child of a host node. This is a common
8523 // case. We won't handle it as a reified child. We will instead handle
8524 // this in the host environment that also have access to this prop. That
8525 // avoids allocating another HostText fiber and traversing it.
8526 nextChildren = null;
8527 } else if (prevProps && shouldSetTextContent(type, prevProps)) {
8528 // If we're switching from a direct text child to a normal child, or to
8529 // empty, we need to schedule the text content to be reset.
8530 workInProgress.effectTag |= ContentReset;
8531 }
8532
8533 markRef(current, workInProgress);
8534
8535 // Check the host config to see if the children are offscreen/hidden.
8536 if (renderExpirationTime !== Never && workInProgress.internalContextTag & AsyncUpdates && shouldDeprioritizeSubtree(type, nextProps)) {
8537 // Down-prioritize the children.
8538 workInProgress.expirationTime = Never;
8539 // Bailout and come back to this fiber later.
8540 return null;
8541 }
8542
8543 reconcileChildren(current, workInProgress, nextChildren);
8544 memoizeProps(workInProgress, nextProps);
8545 return workInProgress.child;
8546 }
8547
8548 function updateHostText(current, workInProgress) {
8549 if (current === null) {
8550 tryToClaimNextHydratableInstance(workInProgress);
8551 }
8552 var nextProps = workInProgress.pendingProps;
8553 memoizeProps(workInProgress, nextProps);
8554 // Nothing to do here. This is terminal. We'll do the completion step
8555 // immediately after.
8556 return null;
8557 }
8558
8559 function mountIndeterminateComponent(current, workInProgress, renderExpirationTime) {
8560 !(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;
8561 var fn = workInProgress.type;
8562 var props = workInProgress.pendingProps;
8563 var unmaskedContext = getUnmaskedContext(workInProgress);
8564 var context = getMaskedContext(workInProgress, unmaskedContext);
8565
8566 var value = void 0;
8567
8568 {
8569 if (fn.prototype && typeof fn.prototype.render === 'function') {
8570 var componentName = getComponentName(workInProgress) || 'Unknown';
8571
8572 if (!didWarnAboutBadClass[componentName]) {
8573 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);
8574 didWarnAboutBadClass[componentName] = true;
8575 }
8576 }
8577 ReactCurrentOwner.current = workInProgress;
8578 value = fn(props, context);
8579 }
8580 // React DevTools reads this flag.
8581 workInProgress.effectTag |= PerformedWork;
8582
8583 if (typeof value === 'object' && value !== null && typeof value.render === 'function') {
8584 // Proceed under the assumption that this is a class instance
8585 workInProgress.tag = ClassComponent;
8586
8587 // Push context providers early to prevent context stack mismatches.
8588 // During mounting we don't know the child context yet as the instance doesn't exist.
8589 // We will invalidate the child context in finishClassComponent() right after rendering.
8590 var hasContext = pushContextProvider(workInProgress);
8591 adoptClassInstance(workInProgress, value);
8592 mountClassInstance(workInProgress, renderExpirationTime);
8593 return finishClassComponent(current, workInProgress, true, hasContext);
8594 } else {
8595 // Proceed under the assumption that this is a functional component
8596 workInProgress.tag = FunctionalComponent;
8597 {
8598 var Component = workInProgress.type;
8599
8600 if (Component) {
8601 warning_1(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component');
8602 }
8603 if (workInProgress.ref !== null) {
8604 var info = '';
8605 var ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName();
8606 if (ownerName) {
8607 info += '\n\nCheck the render method of `' + ownerName + '`.';
8608 }
8609
8610 var warningKey = ownerName || workInProgress._debugID || '';
8611 var debugSource = workInProgress._debugSource;
8612 if (debugSource) {
8613 warningKey = debugSource.fileName + ':' + debugSource.lineNumber;
8614 }
8615 if (!warnedAboutStatelessRefs[warningKey]) {
8616 warnedAboutStatelessRefs[warningKey] = true;
8617 warning_1(false, 'Stateless function components cannot be given refs. ' + 'Attempts to access this ref will fail.%s%s', info, ReactDebugCurrentFiber.getCurrentFiberStackAddendum());
8618 }
8619 }
8620 }
8621 reconcileChildren(current, workInProgress, value);
8622 memoizeProps(workInProgress, props);
8623 return workInProgress.child;
8624 }
8625 }
8626
8627 function updateCallComponent(current, workInProgress, renderExpirationTime) {
8628 var nextProps = workInProgress.pendingProps;
8629 if (hasContextChanged()) {
8630 // Normally we can bail out on props equality but if context has changed
8631 // we don't do the bailout and we have to reuse existing props instead.
8632 } else if (workInProgress.memoizedProps === nextProps) {
8633 nextProps = workInProgress.memoizedProps;
8634 // TODO: When bailing out, we might need to return the stateNode instead
8635 // of the child. To check it for work.
8636 // return bailoutOnAlreadyFinishedWork(current, workInProgress);
8637 }
8638
8639 var nextChildren = nextProps.children;
8640
8641 // The following is a fork of reconcileChildrenAtExpirationTime but using
8642 // stateNode to store the child.
8643 if (current === null) {
8644 workInProgress.stateNode = mountChildFibers(workInProgress, workInProgress.stateNode, nextChildren, renderExpirationTime);
8645 } else {
8646 workInProgress.stateNode = reconcileChildFibers(workInProgress, current.stateNode, nextChildren, renderExpirationTime);
8647 }
8648
8649 memoizeProps(workInProgress, nextProps);
8650 // This doesn't take arbitrary time so we could synchronously just begin
8651 // eagerly do the work of workInProgress.child as an optimization.
8652 return workInProgress.stateNode;
8653 }
8654
8655 function updatePortalComponent(current, workInProgress, renderExpirationTime) {
8656 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
8657 var nextChildren = workInProgress.pendingProps;
8658 if (hasContextChanged()) {
8659 // Normally we can bail out on props equality but if context has changed
8660 // we don't do the bailout and we have to reuse existing props instead.
8661 } else if (workInProgress.memoizedProps === nextChildren) {
8662 return bailoutOnAlreadyFinishedWork(current, workInProgress);
8663 }
8664
8665 if (current === null) {
8666 // Portals are special because we don't append the children during mount
8667 // but at commit. Therefore we need to track insertions which the normal
8668 // flow doesn't do during mount. This doesn't happen at the root because
8669 // the root always starts with a "current" with a null child.
8670 // TODO: Consider unifying this with how the root works.
8671 workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderExpirationTime);
8672 memoizeProps(workInProgress, nextChildren);
8673 } else {
8674 reconcileChildren(current, workInProgress, nextChildren);
8675 memoizeProps(workInProgress, nextChildren);
8676 }
8677 return workInProgress.child;
8678 }
8679
8680 /*
8681 function reuseChildrenEffects(returnFiber : Fiber, firstChild : Fiber) {
8682 let child = firstChild;
8683 do {
8684 // Ensure that the first and last effect of the parent corresponds
8685 // to the children's first and last effect.
8686 if (!returnFiber.firstEffect) {
8687 returnFiber.firstEffect = child.firstEffect;
8688 }
8689 if (child.lastEffect) {
8690 if (returnFiber.lastEffect) {
8691 returnFiber.lastEffect.nextEffect = child.firstEffect;
8692 }
8693 returnFiber.lastEffect = child.lastEffect;
8694 }
8695 } while (child = child.sibling);
8696 }
8697 */
8698
8699 function bailoutOnAlreadyFinishedWork(current, workInProgress) {
8700 cancelWorkTimer(workInProgress);
8701
8702 // TODO: We should ideally be able to bail out early if the children have no
8703 // more work to do. However, since we don't have a separation of this
8704 // Fiber's priority and its children yet - we don't know without doing lots
8705 // of the same work we do anyway. Once we have that separation we can just
8706 // bail out here if the children has no more work at this priority level.
8707 // if (workInProgress.priorityOfChildren <= priorityLevel) {
8708 // // If there are side-effects in these children that have not yet been
8709 // // committed we need to ensure that they get properly transferred up.
8710 // if (current && current.child !== workInProgress.child) {
8711 // reuseChildrenEffects(workInProgress, child);
8712 // }
8713 // return null;
8714 // }
8715
8716 cloneChildFibers(current, workInProgress);
8717 return workInProgress.child;
8718 }
8719
8720 function bailoutOnLowPriority(current, workInProgress) {
8721 cancelWorkTimer(workInProgress);
8722
8723 // TODO: Handle HostComponent tags here as well and call pushHostContext()?
8724 // See PR 8590 discussion for context
8725 switch (workInProgress.tag) {
8726 case HostRoot:
8727 pushHostRootContext(workInProgress);
8728 break;
8729 case ClassComponent:
8730 pushContextProvider(workInProgress);
8731 break;
8732 case HostPortal:
8733 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);
8734 break;
8735 }
8736 // TODO: What if this is currently in progress?
8737 // How can that happen? How is this not being cloned?
8738 return null;
8739 }
8740
8741 // TODO: Delete memoizeProps/State and move to reconcile/bailout instead
8742 function memoizeProps(workInProgress, nextProps) {
8743 workInProgress.memoizedProps = nextProps;
8744 }
8745
8746 function memoizeState(workInProgress, nextState) {
8747 workInProgress.memoizedState = nextState;
8748 // Don't reset the updateQueue, in case there are pending updates. Resetting
8749 // is handled by processUpdateQueue.
8750 }
8751
8752 function beginWork(current, workInProgress, renderExpirationTime) {
8753 if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
8754 return bailoutOnLowPriority(current, workInProgress);
8755 }
8756
8757 switch (workInProgress.tag) {
8758 case IndeterminateComponent:
8759 return mountIndeterminateComponent(current, workInProgress, renderExpirationTime);
8760 case FunctionalComponent:
8761 return updateFunctionalComponent(current, workInProgress);
8762 case ClassComponent:
8763 return updateClassComponent(current, workInProgress, renderExpirationTime);
8764 case HostRoot:
8765 return updateHostRoot(current, workInProgress, renderExpirationTime);
8766 case HostComponent:
8767 return updateHostComponent(current, workInProgress, renderExpirationTime);
8768 case HostText:
8769 return updateHostText(current, workInProgress);
8770 case CallHandlerPhase:
8771 // This is a restart. Reset the tag to the initial phase.
8772 workInProgress.tag = CallComponent;
8773 // Intentionally fall through since this is now the same.
8774 case CallComponent:
8775 return updateCallComponent(current, workInProgress, renderExpirationTime);
8776 case ReturnComponent:
8777 // A return component is just a placeholder, we can just run through the
8778 // next one immediately.
8779 return null;
8780 case HostPortal:
8781 return updatePortalComponent(current, workInProgress, renderExpirationTime);
8782 case Fragment:
8783 return updateFragment(current, workInProgress);
8784 default:
8785 invariant_1(false, 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.');
8786 }
8787 }
8788
8789 function beginFailedWork(current, workInProgress, renderExpirationTime) {
8790 // Push context providers here to avoid a push/pop context mismatch.
8791 switch (workInProgress.tag) {
8792 case ClassComponent:
8793 pushContextProvider(workInProgress);
8794 break;
8795 case HostRoot:
8796 pushHostRootContext(workInProgress);
8797 break;
8798 default:
8799 invariant_1(false, 'Invalid type of work. This error is likely caused by a bug in React. Please file an issue.');
8800 }
8801
8802 // Add an error effect so we can handle the error during the commit phase
8803 workInProgress.effectTag |= Err;
8804
8805 // This is a weird case where we do "resume" work ? work that failed on
8806 // our first attempt. Because we no longer have a notion of "progressed
8807 // deletions," reset the child to the current child to make sure we delete
8808 // it again. TODO: Find a better way to handle this, perhaps during a more
8809 // general overhaul of error handling.
8810 if (current === null) {
8811 workInProgress.child = null;
8812 } else if (workInProgress.child !== current.child) {
8813 workInProgress.child = current.child;
8814 }
8815
8816 if (workInProgress.expirationTime === NoWork || workInProgress.expirationTime > renderExpirationTime) {
8817 return bailoutOnLowPriority(current, workInProgress);
8818 }
8819
8820 // If we don't bail out, we're going be recomputing our children so we need
8821 // to drop our effect list.
8822 workInProgress.firstEffect = null;
8823 workInProgress.lastEffect = null;
8824
8825 // Unmount the current children as if the component rendered null
8826 var nextChildren = null;
8827 reconcileChildrenAtExpirationTime(current, workInProgress, nextChildren, renderExpirationTime);
8828
8829 if (workInProgress.tag === ClassComponent) {
8830 var instance = workInProgress.stateNode;
8831 workInProgress.memoizedProps = instance.props;
8832 workInProgress.memoizedState = instance.state;
8833 }
8834
8835 return workInProgress.child;
8836 }
8837
8838 return {
8839 beginWork: beginWork,
8840 beginFailedWork: beginFailedWork
8841 };
8842};
8843
8844var ReactFiberCompleteWork = function (config, hostContext, hydrationContext) {
8845 var createInstance = config.createInstance,
8846 createTextInstance = config.createTextInstance,
8847 appendInitialChild = config.appendInitialChild,
8848 finalizeInitialChildren = config.finalizeInitialChildren,
8849 prepareUpdate = config.prepareUpdate,
8850 mutation = config.mutation,
8851 persistence = config.persistence;
8852 var getRootHostContainer = hostContext.getRootHostContainer,
8853 popHostContext = hostContext.popHostContext,
8854 getHostContext = hostContext.getHostContext,
8855 popHostContainer = hostContext.popHostContainer;
8856 var prepareToHydrateHostInstance = hydrationContext.prepareToHydrateHostInstance,
8857 prepareToHydrateHostTextInstance = hydrationContext.prepareToHydrateHostTextInstance,
8858 popHydrationState = hydrationContext.popHydrationState;
8859
8860
8861 function markUpdate(workInProgress) {
8862 // Tag the fiber with an update effect. This turns a Placement into
8863 // an UpdateAndPlacement.
8864 workInProgress.effectTag |= Update;
8865 }
8866
8867 function markRef(workInProgress) {
8868 workInProgress.effectTag |= Ref;
8869 }
8870
8871 function appendAllReturns(returns, workInProgress) {
8872 var node = workInProgress.stateNode;
8873 if (node) {
8874 node['return'] = workInProgress;
8875 }
8876 while (node !== null) {
8877 if (node.tag === HostComponent || node.tag === HostText || node.tag === HostPortal) {
8878 invariant_1(false, 'A call cannot have host component children.');
8879 } else if (node.tag === ReturnComponent) {
8880 returns.push(node.pendingProps.value);
8881 } else if (node.child !== null) {
8882 node.child['return'] = node;
8883 node = node.child;
8884 continue;
8885 }
8886 while (node.sibling === null) {
8887 if (node['return'] === null || node['return'] === workInProgress) {
8888 return;
8889 }
8890 node = node['return'];
8891 }
8892 node.sibling['return'] = node['return'];
8893 node = node.sibling;
8894 }
8895 }
8896
8897 function moveCallToHandlerPhase(current, workInProgress, renderExpirationTime) {
8898 var props = workInProgress.memoizedProps;
8899 !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;
8900
8901 // First step of the call has completed. Now we need to do the second.
8902 // TODO: It would be nice to have a multi stage call represented by a
8903 // single component, or at least tail call optimize nested ones. Currently
8904 // that requires additional fields that we don't want to add to the fiber.
8905 // So this requires nested handlers.
8906 // Note: This doesn't mutate the alternate node. I don't think it needs to
8907 // since this stage is reset for every pass.
8908 workInProgress.tag = CallHandlerPhase;
8909
8910 // Build up the returns.
8911 // TODO: Compare this to a generator or opaque helpers like Children.
8912 var returns = [];
8913 appendAllReturns(returns, workInProgress);
8914 var fn = props.handler;
8915 var childProps = props.props;
8916 var nextChildren = fn(childProps, returns);
8917
8918 var currentFirstChild = current !== null ? current.child : null;
8919 workInProgress.child = reconcileChildFibers(workInProgress, currentFirstChild, nextChildren, renderExpirationTime);
8920 return workInProgress.child;
8921 }
8922
8923 function appendAllChildren(parent, workInProgress) {
8924 // We only have the top Fiber that was created but we need recurse down its
8925 // children to find all the terminal nodes.
8926 var node = workInProgress.child;
8927 while (node !== null) {
8928 if (node.tag === HostComponent || node.tag === HostText) {
8929 appendInitialChild(parent, node.stateNode);
8930 } else if (node.tag === HostPortal) {
8931 // If we have a portal child, then we don't want to traverse
8932 // down its children. Instead, we'll get insertions from each child in
8933 // the portal directly.
8934 } else if (node.child !== null) {
8935 node.child['return'] = node;
8936 node = node.child;
8937 continue;
8938 }
8939 if (node === workInProgress) {
8940 return;
8941 }
8942 while (node.sibling === null) {
8943 if (node['return'] === null || node['return'] === workInProgress) {
8944 return;
8945 }
8946 node = node['return'];
8947 }
8948 node.sibling['return'] = node['return'];
8949 node = node.sibling;
8950 }
8951 }
8952
8953 var updateHostContainer = void 0;
8954 var updateHostComponent = void 0;
8955 var updateHostText = void 0;
8956 if (mutation) {
8957 if (enableMutatingReconciler) {
8958 // Mutation mode
8959 updateHostContainer = function (workInProgress) {
8960 // Noop
8961 };
8962 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance, currentHostContext) {
8963 // TODO: Type this specific to this type of component.
8964 workInProgress.updateQueue = updatePayload;
8965 // If the update payload indicates that there is a change or if there
8966 // is a new ref we mark this as an update. All the work is done in commitWork.
8967 if (updatePayload) {
8968 markUpdate(workInProgress);
8969 }
8970 };
8971 updateHostText = function (current, workInProgress, oldText, newText) {
8972 // If the text differs, mark it as an update. All the work in done in commitWork.
8973 if (oldText !== newText) {
8974 markUpdate(workInProgress);
8975 }
8976 };
8977 } else {
8978 invariant_1(false, 'Mutating reconciler is disabled.');
8979 }
8980 } else if (persistence) {
8981 if (enablePersistentReconciler) {
8982 // Persistent host tree mode
8983 var cloneInstance = persistence.cloneInstance,
8984 createContainerChildSet = persistence.createContainerChildSet,
8985 appendChildToContainerChildSet = persistence.appendChildToContainerChildSet,
8986 finalizeContainerChildren = persistence.finalizeContainerChildren;
8987
8988 // An unfortunate fork of appendAllChildren because we have two different parent types.
8989
8990 var appendAllChildrenToContainer = function (containerChildSet, workInProgress) {
8991 // We only have the top Fiber that was created but we need recurse down its
8992 // children to find all the terminal nodes.
8993 var node = workInProgress.child;
8994 while (node !== null) {
8995 if (node.tag === HostComponent || node.tag === HostText) {
8996 appendChildToContainerChildSet(containerChildSet, node.stateNode);
8997 } else if (node.tag === HostPortal) {
8998 // If we have a portal child, then we don't want to traverse
8999 // down its children. Instead, we'll get insertions from each child in
9000 // the portal directly.
9001 } else if (node.child !== null) {
9002 node.child['return'] = node;
9003 node = node.child;
9004 continue;
9005 }
9006 if (node === workInProgress) {
9007 return;
9008 }
9009 while (node.sibling === null) {
9010 if (node['return'] === null || node['return'] === workInProgress) {
9011 return;
9012 }
9013 node = node['return'];
9014 }
9015 node.sibling['return'] = node['return'];
9016 node = node.sibling;
9017 }
9018 };
9019 updateHostContainer = function (workInProgress) {
9020 var portalOrRoot = workInProgress.stateNode;
9021 var childrenUnchanged = workInProgress.firstEffect === null;
9022 if (childrenUnchanged) {
9023 // No changes, just reuse the existing instance.
9024 } else {
9025 var container = portalOrRoot.containerInfo;
9026 var newChildSet = createContainerChildSet(container);
9027 if (finalizeContainerChildren(container, newChildSet)) {
9028 markUpdate(workInProgress);
9029 }
9030 portalOrRoot.pendingChildren = newChildSet;
9031 // If children might have changed, we have to add them all to the set.
9032 appendAllChildrenToContainer(newChildSet, workInProgress);
9033 // Schedule an update on the container to swap out the container.
9034 markUpdate(workInProgress);
9035 }
9036 };
9037 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance, currentHostContext) {
9038 // If there are no effects associated with this node, then none of our children had any updates.
9039 // This guarantees that we can reuse all of them.
9040 var childrenUnchanged = workInProgress.firstEffect === null;
9041 var currentInstance = current.stateNode;
9042 if (childrenUnchanged && updatePayload === null) {
9043 // No changes, just reuse the existing instance.
9044 // Note that this might release a previous clone.
9045 workInProgress.stateNode = currentInstance;
9046 } else {
9047 var recyclableInstance = workInProgress.stateNode;
9048 var newInstance = cloneInstance(currentInstance, updatePayload, type, oldProps, newProps, workInProgress, childrenUnchanged, recyclableInstance);
9049 if (finalizeInitialChildren(newInstance, type, newProps, rootContainerInstance, currentHostContext)) {
9050 markUpdate(workInProgress);
9051 }
9052 workInProgress.stateNode = newInstance;
9053 if (childrenUnchanged) {
9054 // If there are no other effects in this tree, we need to flag this node as having one.
9055 // Even though we're not going to use it for anything.
9056 // Otherwise parents won't know that there are new children to propagate upwards.
9057 markUpdate(workInProgress);
9058 } else {
9059 // If children might have changed, we have to add them all to the set.
9060 appendAllChildren(newInstance, workInProgress);
9061 }
9062 }
9063 };
9064 updateHostText = function (current, workInProgress, oldText, newText) {
9065 if (oldText !== newText) {
9066 // If the text content differs, we'll create a new text instance for it.
9067 var rootContainerInstance = getRootHostContainer();
9068 var currentHostContext = getHostContext();
9069 workInProgress.stateNode = createTextInstance(newText, rootContainerInstance, currentHostContext, workInProgress);
9070 // We'll have to mark it as having an effect, even though we won't use the effect for anything.
9071 // This lets the parents know that at least one of their children has changed.
9072 markUpdate(workInProgress);
9073 }
9074 };
9075 } else {
9076 invariant_1(false, 'Persistent reconciler is disabled.');
9077 }
9078 } else {
9079 if (enableNoopReconciler) {
9080 // No host operations
9081 updateHostContainer = function (workInProgress) {
9082 // Noop
9083 };
9084 updateHostComponent = function (current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance, currentHostContext) {
9085 // Noop
9086 };
9087 updateHostText = function (current, workInProgress, oldText, newText) {
9088 // Noop
9089 };
9090 } else {
9091 invariant_1(false, 'Noop reconciler is disabled.');
9092 }
9093 }
9094
9095 function completeWork(current, workInProgress, renderExpirationTime) {
9096 var newProps = workInProgress.pendingProps;
9097 switch (workInProgress.tag) {
9098 case FunctionalComponent:
9099 return null;
9100 case ClassComponent:
9101 {
9102 // We are leaving this subtree, so pop context if any.
9103 popContextProvider(workInProgress);
9104 return null;
9105 }
9106 case HostRoot:
9107 {
9108 popHostContainer(workInProgress);
9109 popTopLevelContextObject(workInProgress);
9110 var fiberRoot = workInProgress.stateNode;
9111 if (fiberRoot.pendingContext) {
9112 fiberRoot.context = fiberRoot.pendingContext;
9113 fiberRoot.pendingContext = null;
9114 }
9115
9116 if (current === null || current.child === null) {
9117 // If we hydrated, pop so that we can delete any remaining children
9118 // that weren't hydrated.
9119 popHydrationState(workInProgress);
9120 // This resets the hacky state to fix isMounted before committing.
9121 // TODO: Delete this when we delete isMounted and findDOMNode.
9122 workInProgress.effectTag &= ~Placement;
9123 }
9124 updateHostContainer(workInProgress);
9125 return null;
9126 }
9127 case HostComponent:
9128 {
9129 popHostContext(workInProgress);
9130 var rootContainerInstance = getRootHostContainer();
9131 var type = workInProgress.type;
9132 if (current !== null && workInProgress.stateNode != null) {
9133 // If we have an alternate, that means this is an update and we need to
9134 // schedule a side-effect to do the updates.
9135 var oldProps = current.memoizedProps;
9136 // If we get updated because one of our children updated, we don't
9137 // have newProps so we'll have to reuse them.
9138 // TODO: Split the update API as separate for the props vs. children.
9139 // Even better would be if children weren't special cased at all tho.
9140 var instance = workInProgress.stateNode;
9141 var currentHostContext = getHostContext();
9142 var updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext);
9143
9144 updateHostComponent(current, workInProgress, updatePayload, type, oldProps, newProps, rootContainerInstance, currentHostContext);
9145
9146 if (current.ref !== workInProgress.ref) {
9147 markRef(workInProgress);
9148 }
9149 } else {
9150 if (!newProps) {
9151 !(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;
9152 // This can happen when we abort work.
9153 return null;
9154 }
9155
9156 var _currentHostContext = getHostContext();
9157 // TODO: Move createInstance to beginWork and keep it on a context
9158 // "stack" as the parent. Then append children as we go in beginWork
9159 // or completeWork depending on we want to add then top->down or
9160 // bottom->up. Top->down is faster in IE11.
9161 var wasHydrated = popHydrationState(workInProgress);
9162 if (wasHydrated) {
9163 // TODO: Move this and createInstance step into the beginPhase
9164 // to consolidate.
9165 if (prepareToHydrateHostInstance(workInProgress, rootContainerInstance, _currentHostContext)) {
9166 // If changes to the hydrated node needs to be applied at the
9167 // commit-phase we mark this as such.
9168 markUpdate(workInProgress);
9169 }
9170 } else {
9171 var _instance = createInstance(type, newProps, rootContainerInstance, _currentHostContext, workInProgress);
9172
9173 appendAllChildren(_instance, workInProgress);
9174
9175 // Certain renderers require commit-time effects for initial mount.
9176 // (eg DOM renderer supports auto-focus for certain elements).
9177 // Make sure such renderers get scheduled for later work.
9178 if (finalizeInitialChildren(_instance, type, newProps, rootContainerInstance, _currentHostContext)) {
9179 markUpdate(workInProgress);
9180 }
9181 workInProgress.stateNode = _instance;
9182 }
9183
9184 if (workInProgress.ref !== null) {
9185 // If there is a ref on a host node we need to schedule a callback
9186 markRef(workInProgress);
9187 }
9188 }
9189 return null;
9190 }
9191 case HostText:
9192 {
9193 var newText = newProps;
9194 if (current && workInProgress.stateNode != null) {
9195 var oldText = current.memoizedProps;
9196 // If we have an alternate, that means this is an update and we need
9197 // to schedule a side-effect to do the updates.
9198 updateHostText(current, workInProgress, oldText, newText);
9199 } else {
9200 if (typeof newText !== 'string') {
9201 !(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;
9202 // This can happen when we abort work.
9203 return null;
9204 }
9205 var _rootContainerInstance = getRootHostContainer();
9206 var _currentHostContext2 = getHostContext();
9207 var _wasHydrated = popHydrationState(workInProgress);
9208 if (_wasHydrated) {
9209 if (prepareToHydrateHostTextInstance(workInProgress)) {
9210 markUpdate(workInProgress);
9211 }
9212 } else {
9213 workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext2, workInProgress);
9214 }
9215 }
9216 return null;
9217 }
9218 case CallComponent:
9219 return moveCallToHandlerPhase(current, workInProgress, renderExpirationTime);
9220 case CallHandlerPhase:
9221 // Reset the tag to now be a first phase call.
9222 workInProgress.tag = CallComponent;
9223 return null;
9224 case ReturnComponent:
9225 // Does nothing.
9226 return null;
9227 case Fragment:
9228 return null;
9229 case HostPortal:
9230 popHostContainer(workInProgress);
9231 updateHostContainer(workInProgress);
9232 return null;
9233 // Error cases
9234 case IndeterminateComponent:
9235 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.');
9236 // eslint-disable-next-line no-fallthrough
9237 default:
9238 invariant_1(false, 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.');
9239 }
9240 }
9241
9242 return {
9243 completeWork: completeWork
9244 };
9245};
9246
9247var invokeGuardedCallback$3 = ReactErrorUtils.invokeGuardedCallback;
9248var hasCaughtError$1 = ReactErrorUtils.hasCaughtError;
9249var clearCaughtError$1 = ReactErrorUtils.clearCaughtError;
9250
9251
9252var ReactFiberCommitWork = function (config, captureError) {
9253 var getPublicInstance = config.getPublicInstance,
9254 mutation = config.mutation,
9255 persistence = config.persistence;
9256
9257
9258 var callComponentWillUnmountWithTimer = function (current, instance) {
9259 startPhaseTimer(current, 'componentWillUnmount');
9260 instance.props = current.memoizedProps;
9261 instance.state = current.memoizedState;
9262 instance.componentWillUnmount();
9263 stopPhaseTimer();
9264 };
9265
9266 // Capture errors so they don't interrupt unmounting.
9267 function safelyCallComponentWillUnmount(current, instance) {
9268 {
9269 invokeGuardedCallback$3(null, callComponentWillUnmountWithTimer, null, current, instance);
9270 if (hasCaughtError$1()) {
9271 var unmountError = clearCaughtError$1();
9272 captureError(current, unmountError);
9273 }
9274 }
9275 }
9276
9277 function safelyDetachRef(current) {
9278 var ref = current.ref;
9279 if (ref !== null) {
9280 {
9281 invokeGuardedCallback$3(null, ref, null, null);
9282 if (hasCaughtError$1()) {
9283 var refError = clearCaughtError$1();
9284 captureError(current, refError);
9285 }
9286 }
9287 }
9288 }
9289
9290 function commitLifeCycles(current, finishedWork) {
9291 switch (finishedWork.tag) {
9292 case ClassComponent:
9293 {
9294 var instance = finishedWork.stateNode;
9295 if (finishedWork.effectTag & Update) {
9296 if (current === null) {
9297 startPhaseTimer(finishedWork, 'componentDidMount');
9298 instance.props = finishedWork.memoizedProps;
9299 instance.state = finishedWork.memoizedState;
9300 instance.componentDidMount();
9301 stopPhaseTimer();
9302 } else {
9303 var prevProps = current.memoizedProps;
9304 var prevState = current.memoizedState;
9305 startPhaseTimer(finishedWork, 'componentDidUpdate');
9306 instance.props = finishedWork.memoizedProps;
9307 instance.state = finishedWork.memoizedState;
9308 instance.componentDidUpdate(prevProps, prevState);
9309 stopPhaseTimer();
9310 }
9311 }
9312 var updateQueue = finishedWork.updateQueue;
9313 if (updateQueue !== null) {
9314 commitCallbacks(updateQueue, instance);
9315 }
9316 return;
9317 }
9318 case HostRoot:
9319 {
9320 var _updateQueue = finishedWork.updateQueue;
9321 if (_updateQueue !== null) {
9322 var _instance = finishedWork.child !== null ? finishedWork.child.stateNode : null;
9323 commitCallbacks(_updateQueue, _instance);
9324 }
9325 return;
9326 }
9327 case HostComponent:
9328 {
9329 var _instance2 = finishedWork.stateNode;
9330
9331 // Renderers may schedule work to be done after host components are mounted
9332 // (eg DOM renderer may schedule auto-focus for inputs and form controls).
9333 // These effects should only be committed when components are first mounted,
9334 // aka when there is no current/alternate.
9335 if (current === null && finishedWork.effectTag & Update) {
9336 var type = finishedWork.type;
9337 var props = finishedWork.memoizedProps;
9338 commitMount(_instance2, type, props, finishedWork);
9339 }
9340
9341 return;
9342 }
9343 case HostText:
9344 {
9345 // We have no life-cycles associated with text.
9346 return;
9347 }
9348 case HostPortal:
9349 {
9350 // We have no life-cycles associated with portals.
9351 return;
9352 }
9353 default:
9354 {
9355 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.');
9356 }
9357 }
9358 }
9359
9360 function commitAttachRef(finishedWork) {
9361 var ref = finishedWork.ref;
9362 if (ref !== null) {
9363 var instance = finishedWork.stateNode;
9364 switch (finishedWork.tag) {
9365 case HostComponent:
9366 ref(getPublicInstance(instance));
9367 break;
9368 default:
9369 ref(instance);
9370 }
9371 }
9372 }
9373
9374 function commitDetachRef(current) {
9375 var currentRef = current.ref;
9376 if (currentRef !== null) {
9377 currentRef(null);
9378 }
9379 }
9380
9381 // User-originating errors (lifecycles and refs) should not interrupt
9382 // deletion, so don't let them throw. Host-originating errors should
9383 // interrupt deletion, so it's okay
9384 function commitUnmount(current) {
9385 if (typeof onCommitUnmount === 'function') {
9386 onCommitUnmount(current);
9387 }
9388
9389 switch (current.tag) {
9390 case ClassComponent:
9391 {
9392 safelyDetachRef(current);
9393 var instance = current.stateNode;
9394 if (typeof instance.componentWillUnmount === 'function') {
9395 safelyCallComponentWillUnmount(current, instance);
9396 }
9397 return;
9398 }
9399 case HostComponent:
9400 {
9401 safelyDetachRef(current);
9402 return;
9403 }
9404 case CallComponent:
9405 {
9406 commitNestedUnmounts(current.stateNode);
9407 return;
9408 }
9409 case HostPortal:
9410 {
9411 // TODO: this is recursive.
9412 // We are also not using this parent because
9413 // the portal will get pushed immediately.
9414 if (enableMutatingReconciler && mutation) {
9415 unmountHostComponents(current);
9416 } else if (enablePersistentReconciler && persistence) {
9417 emptyPortalContainer(current);
9418 }
9419 return;
9420 }
9421 }
9422 }
9423
9424 function commitNestedUnmounts(root) {
9425 // While we're inside a removed host node we don't want to call
9426 // removeChild on the inner nodes because they're removed by the top
9427 // call anyway. We also want to call componentWillUnmount on all
9428 // composites before this host node is removed from the tree. Therefore
9429 var node = root;
9430 while (true) {
9431 commitUnmount(node);
9432 // Visit children because they may contain more composite or host nodes.
9433 // Skip portals because commitUnmount() currently visits them recursively.
9434 if (node.child !== null && (
9435 // If we use mutation we drill down into portals using commitUnmount above.
9436 // If we don't use mutation we drill down into portals here instead.
9437 !mutation || node.tag !== HostPortal)) {
9438 node.child['return'] = node;
9439 node = node.child;
9440 continue;
9441 }
9442 if (node === root) {
9443 return;
9444 }
9445 while (node.sibling === null) {
9446 if (node['return'] === null || node['return'] === root) {
9447 return;
9448 }
9449 node = node['return'];
9450 }
9451 node.sibling['return'] = node['return'];
9452 node = node.sibling;
9453 }
9454 }
9455
9456 function detachFiber(current) {
9457 // Cut off the return pointers to disconnect it from the tree. Ideally, we
9458 // should clear the child pointer of the parent alternate to let this
9459 // get GC:ed but we don't know which for sure which parent is the current
9460 // one so we'll settle for GC:ing the subtree of this child. This child
9461 // itself will be GC:ed when the parent updates the next time.
9462 current['return'] = null;
9463 current.child = null;
9464 if (current.alternate) {
9465 current.alternate.child = null;
9466 current.alternate['return'] = null;
9467 }
9468 }
9469
9470 var emptyPortalContainer = void 0;
9471
9472 if (!mutation) {
9473 var commitContainer = void 0;
9474 if (persistence) {
9475 var replaceContainerChildren = persistence.replaceContainerChildren,
9476 createContainerChildSet = persistence.createContainerChildSet;
9477
9478 emptyPortalContainer = function (current) {
9479 var portal = current.stateNode;
9480 var containerInfo = portal.containerInfo;
9481
9482 var emptyChildSet = createContainerChildSet(containerInfo);
9483 replaceContainerChildren(containerInfo, emptyChildSet);
9484 };
9485 commitContainer = function (finishedWork) {
9486 switch (finishedWork.tag) {
9487 case ClassComponent:
9488 {
9489 return;
9490 }
9491 case HostComponent:
9492 {
9493 return;
9494 }
9495 case HostText:
9496 {
9497 return;
9498 }
9499 case HostRoot:
9500 case HostPortal:
9501 {
9502 var portalOrRoot = finishedWork.stateNode;
9503 var containerInfo = portalOrRoot.containerInfo,
9504 _pendingChildren = portalOrRoot.pendingChildren;
9505
9506 replaceContainerChildren(containerInfo, _pendingChildren);
9507 return;
9508 }
9509 default:
9510 {
9511 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.');
9512 }
9513 }
9514 };
9515 } else {
9516 commitContainer = function (finishedWork) {
9517 // Noop
9518 };
9519 }
9520 if (enablePersistentReconciler || enableNoopReconciler) {
9521 return {
9522 commitResetTextContent: function (finishedWork) {},
9523 commitPlacement: function (finishedWork) {},
9524 commitDeletion: function (current) {
9525 // Detach refs and call componentWillUnmount() on the whole subtree.
9526 commitNestedUnmounts(current);
9527 detachFiber(current);
9528 },
9529 commitWork: function (current, finishedWork) {
9530 commitContainer(finishedWork);
9531 },
9532
9533 commitLifeCycles: commitLifeCycles,
9534 commitAttachRef: commitAttachRef,
9535 commitDetachRef: commitDetachRef
9536 };
9537 } else if (persistence) {
9538 invariant_1(false, 'Persistent reconciler is disabled.');
9539 } else {
9540 invariant_1(false, 'Noop reconciler is disabled.');
9541 }
9542 }
9543 var commitMount = mutation.commitMount,
9544 commitUpdate = mutation.commitUpdate,
9545 resetTextContent = mutation.resetTextContent,
9546 commitTextUpdate = mutation.commitTextUpdate,
9547 appendChild = mutation.appendChild,
9548 appendChildToContainer = mutation.appendChildToContainer,
9549 insertBefore = mutation.insertBefore,
9550 insertInContainerBefore = mutation.insertInContainerBefore,
9551 removeChild = mutation.removeChild,
9552 removeChildFromContainer = mutation.removeChildFromContainer;
9553
9554
9555 function getHostParentFiber(fiber) {
9556 var parent = fiber['return'];
9557 while (parent !== null) {
9558 if (isHostParent(parent)) {
9559 return parent;
9560 }
9561 parent = parent['return'];
9562 }
9563 invariant_1(false, 'Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue.');
9564 }
9565
9566 function isHostParent(fiber) {
9567 return fiber.tag === HostComponent || fiber.tag === HostRoot || fiber.tag === HostPortal;
9568 }
9569
9570 function getHostSibling(fiber) {
9571 // We're going to search forward into the tree until we find a sibling host
9572 // node. Unfortunately, if multiple insertions are done in a row we have to
9573 // search past them. This leads to exponential search for the next sibling.
9574 var node = fiber;
9575 siblings: while (true) {
9576 // If we didn't find anything, let's try the next sibling.
9577 while (node.sibling === null) {
9578 if (node['return'] === null || isHostParent(node['return'])) {
9579 // If we pop out of the root or hit the parent the fiber we are the
9580 // last sibling.
9581 return null;
9582 }
9583 node = node['return'];
9584 }
9585 node.sibling['return'] = node['return'];
9586 node = node.sibling;
9587 while (node.tag !== HostComponent && node.tag !== HostText) {
9588 // If it is not host node and, we might have a host node inside it.
9589 // Try to search down until we find one.
9590 if (node.effectTag & Placement) {
9591 // If we don't have a child, try the siblings instead.
9592 continue siblings;
9593 }
9594 // If we don't have a child, try the siblings instead.
9595 // We also skip portals because they are not part of this host tree.
9596 if (node.child === null || node.tag === HostPortal) {
9597 continue siblings;
9598 } else {
9599 node.child['return'] = node;
9600 node = node.child;
9601 }
9602 }
9603 // Check if this host node is stable or about to be placed.
9604 if (!(node.effectTag & Placement)) {
9605 // Found it!
9606 return node.stateNode;
9607 }
9608 }
9609 }
9610
9611 function commitPlacement(finishedWork) {
9612 // Recursively insert all host nodes into the parent.
9613 var parentFiber = getHostParentFiber(finishedWork);
9614 var parent = void 0;
9615 var isContainer = void 0;
9616 switch (parentFiber.tag) {
9617 case HostComponent:
9618 parent = parentFiber.stateNode;
9619 isContainer = false;
9620 break;
9621 case HostRoot:
9622 parent = parentFiber.stateNode.containerInfo;
9623 isContainer = true;
9624 break;
9625 case HostPortal:
9626 parent = parentFiber.stateNode.containerInfo;
9627 isContainer = true;
9628 break;
9629 default:
9630 invariant_1(false, 'Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue.');
9631 }
9632 if (parentFiber.effectTag & ContentReset) {
9633 // Reset the text content of the parent before doing any insertions
9634 resetTextContent(parent);
9635 // Clear ContentReset from the effect tag
9636 parentFiber.effectTag &= ~ContentReset;
9637 }
9638
9639 var before = getHostSibling(finishedWork);
9640 // We only have the top Fiber that was inserted but we need recurse down its
9641 // children to find all the terminal nodes.
9642 var node = finishedWork;
9643 while (true) {
9644 if (node.tag === HostComponent || node.tag === HostText) {
9645 if (before) {
9646 if (isContainer) {
9647 insertInContainerBefore(parent, node.stateNode, before);
9648 } else {
9649 insertBefore(parent, node.stateNode, before);
9650 }
9651 } else {
9652 if (isContainer) {
9653 appendChildToContainer(parent, node.stateNode);
9654 } else {
9655 appendChild(parent, node.stateNode);
9656 }
9657 }
9658 } else if (node.tag === HostPortal) {
9659 // If the insertion itself is a portal, then we don't want to traverse
9660 // down its children. Instead, we'll get insertions from each child in
9661 // the portal directly.
9662 } else if (node.child !== null) {
9663 node.child['return'] = node;
9664 node = node.child;
9665 continue;
9666 }
9667 if (node === finishedWork) {
9668 return;
9669 }
9670 while (node.sibling === null) {
9671 if (node['return'] === null || node['return'] === finishedWork) {
9672 return;
9673 }
9674 node = node['return'];
9675 }
9676 node.sibling['return'] = node['return'];
9677 node = node.sibling;
9678 }
9679 }
9680
9681 function unmountHostComponents(current) {
9682 // We only have the top Fiber that was inserted but we need recurse down its
9683 var node = current;
9684
9685 // Each iteration, currentParent is populated with node's host parent if not
9686 // currentParentIsValid.
9687 var currentParentIsValid = false;
9688 var currentParent = void 0;
9689 var currentParentIsContainer = void 0;
9690
9691 while (true) {
9692 if (!currentParentIsValid) {
9693 var parent = node['return'];
9694 findParent: while (true) {
9695 !(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;
9696 switch (parent.tag) {
9697 case HostComponent:
9698 currentParent = parent.stateNode;
9699 currentParentIsContainer = false;
9700 break findParent;
9701 case HostRoot:
9702 currentParent = parent.stateNode.containerInfo;
9703 currentParentIsContainer = true;
9704 break findParent;
9705 case HostPortal:
9706 currentParent = parent.stateNode.containerInfo;
9707 currentParentIsContainer = true;
9708 break findParent;
9709 }
9710 parent = parent['return'];
9711 }
9712 currentParentIsValid = true;
9713 }
9714
9715 if (node.tag === HostComponent || node.tag === HostText) {
9716 commitNestedUnmounts(node);
9717 // After all the children have unmounted, it is now safe to remove the
9718 // node from the tree.
9719 if (currentParentIsContainer) {
9720 removeChildFromContainer(currentParent, node.stateNode);
9721 } else {
9722 removeChild(currentParent, node.stateNode);
9723 }
9724 // Don't visit children because we already visited them.
9725 } else if (node.tag === HostPortal) {
9726 // When we go into a portal, it becomes the parent to remove from.
9727 // We will reassign it back when we pop the portal on the way up.
9728 currentParent = node.stateNode.containerInfo;
9729 // Visit children because portals might contain host components.
9730 if (node.child !== null) {
9731 node.child['return'] = node;
9732 node = node.child;
9733 continue;
9734 }
9735 } else {
9736 commitUnmount(node);
9737 // Visit children because we may find more host components below.
9738 if (node.child !== null) {
9739 node.child['return'] = node;
9740 node = node.child;
9741 continue;
9742 }
9743 }
9744 if (node === current) {
9745 return;
9746 }
9747 while (node.sibling === null) {
9748 if (node['return'] === null || node['return'] === current) {
9749 return;
9750 }
9751 node = node['return'];
9752 if (node.tag === HostPortal) {
9753 // When we go out of the portal, we need to restore the parent.
9754 // Since we don't keep a stack of them, we will search for it.
9755 currentParentIsValid = false;
9756 }
9757 }
9758 node.sibling['return'] = node['return'];
9759 node = node.sibling;
9760 }
9761 }
9762
9763 function commitDeletion(current) {
9764 // Recursively delete all host nodes from the parent.
9765 // Detach refs and call componentWillUnmount() on the whole subtree.
9766 unmountHostComponents(current);
9767 detachFiber(current);
9768 }
9769
9770 function commitWork(current, finishedWork) {
9771 switch (finishedWork.tag) {
9772 case ClassComponent:
9773 {
9774 return;
9775 }
9776 case HostComponent:
9777 {
9778 var instance = finishedWork.stateNode;
9779 if (instance != null) {
9780 // Commit the work prepared earlier.
9781 var newProps = finishedWork.memoizedProps;
9782 // For hydration we reuse the update path but we treat the oldProps
9783 // as the newProps. The updatePayload will contain the real change in
9784 // this case.
9785 var oldProps = current !== null ? current.memoizedProps : newProps;
9786 var type = finishedWork.type;
9787 // TODO: Type the updateQueue to be specific to host components.
9788 var updatePayload = finishedWork.updateQueue;
9789 finishedWork.updateQueue = null;
9790 if (updatePayload !== null) {
9791 commitUpdate(instance, updatePayload, type, oldProps, newProps, finishedWork);
9792 }
9793 }
9794 return;
9795 }
9796 case HostText:
9797 {
9798 !(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;
9799 var textInstance = finishedWork.stateNode;
9800 var newText = finishedWork.memoizedProps;
9801 // For hydration we reuse the update path but we treat the oldProps
9802 // as the newProps. The updatePayload will contain the real change in
9803 // this case.
9804 var oldText = current !== null ? current.memoizedProps : newText;
9805 commitTextUpdate(textInstance, oldText, newText);
9806 return;
9807 }
9808 case HostRoot:
9809 {
9810 return;
9811 }
9812 default:
9813 {
9814 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.');
9815 }
9816 }
9817 }
9818
9819 function commitResetTextContent(current) {
9820 resetTextContent(current.stateNode);
9821 }
9822
9823 if (enableMutatingReconciler) {
9824 return {
9825 commitResetTextContent: commitResetTextContent,
9826 commitPlacement: commitPlacement,
9827 commitDeletion: commitDeletion,
9828 commitWork: commitWork,
9829 commitLifeCycles: commitLifeCycles,
9830 commitAttachRef: commitAttachRef,
9831 commitDetachRef: commitDetachRef
9832 };
9833 } else {
9834 invariant_1(false, 'Mutating reconciler is disabled.');
9835 }
9836};
9837
9838var NO_CONTEXT = {};
9839
9840var ReactFiberHostContext = function (config) {
9841 var getChildHostContext = config.getChildHostContext,
9842 getRootHostContext = config.getRootHostContext;
9843
9844
9845 var contextStackCursor = createCursor(NO_CONTEXT);
9846 var contextFiberStackCursor = createCursor(NO_CONTEXT);
9847 var rootInstanceStackCursor = createCursor(NO_CONTEXT);
9848
9849 function requiredContext(c) {
9850 !(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;
9851 return c;
9852 }
9853
9854 function getRootHostContainer() {
9855 var rootInstance = requiredContext(rootInstanceStackCursor.current);
9856 return rootInstance;
9857 }
9858
9859 function pushHostContainer(fiber, nextRootInstance) {
9860 // Push current root instance onto the stack;
9861 // This allows us to reset root when portals are popped.
9862 push(rootInstanceStackCursor, nextRootInstance, fiber);
9863
9864 var nextRootContext = getRootHostContext(nextRootInstance);
9865
9866 // Track the context and the Fiber that provided it.
9867 // This enables us to pop only Fibers that provide unique contexts.
9868 push(contextFiberStackCursor, fiber, fiber);
9869 push(contextStackCursor, nextRootContext, fiber);
9870 }
9871
9872 function popHostContainer(fiber) {
9873 pop(contextStackCursor, fiber);
9874 pop(contextFiberStackCursor, fiber);
9875 pop(rootInstanceStackCursor, fiber);
9876 }
9877
9878 function getHostContext() {
9879 var context = requiredContext(contextStackCursor.current);
9880 return context;
9881 }
9882
9883 function pushHostContext(fiber) {
9884 var rootInstance = requiredContext(rootInstanceStackCursor.current);
9885 var context = requiredContext(contextStackCursor.current);
9886 var nextContext = getChildHostContext(context, fiber.type, rootInstance);
9887
9888 // Don't push this Fiber's context unless it's unique.
9889 if (context === nextContext) {
9890 return;
9891 }
9892
9893 // Track the context and the Fiber that provided it.
9894 // This enables us to pop only Fibers that provide unique contexts.
9895 push(contextFiberStackCursor, fiber, fiber);
9896 push(contextStackCursor, nextContext, fiber);
9897 }
9898
9899 function popHostContext(fiber) {
9900 // Do not pop unless this Fiber provided the current context.
9901 // pushHostContext() only pushes Fibers that provide unique contexts.
9902 if (contextFiberStackCursor.current !== fiber) {
9903 return;
9904 }
9905
9906 pop(contextStackCursor, fiber);
9907 pop(contextFiberStackCursor, fiber);
9908 }
9909
9910 function resetHostContainer() {
9911 contextStackCursor.current = NO_CONTEXT;
9912 rootInstanceStackCursor.current = NO_CONTEXT;
9913 }
9914
9915 return {
9916 getHostContext: getHostContext,
9917 getRootHostContainer: getRootHostContainer,
9918 popHostContainer: popHostContainer,
9919 popHostContext: popHostContext,
9920 pushHostContainer: pushHostContainer,
9921 pushHostContext: pushHostContext,
9922 resetHostContainer: resetHostContainer
9923 };
9924};
9925
9926var ReactFiberHydrationContext = function (config) {
9927 var shouldSetTextContent = config.shouldSetTextContent,
9928 hydration = config.hydration;
9929
9930 // If this doesn't have hydration mode.
9931
9932 if (!hydration) {
9933 return {
9934 enterHydrationState: function () {
9935 return false;
9936 },
9937 resetHydrationState: function () {},
9938 tryToClaimNextHydratableInstance: function () {},
9939 prepareToHydrateHostInstance: function () {
9940 invariant_1(false, 'Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.');
9941 },
9942 prepareToHydrateHostTextInstance: function () {
9943 invariant_1(false, 'Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.');
9944 },
9945 popHydrationState: function (fiber) {
9946 return false;
9947 }
9948 };
9949 }
9950
9951 var canHydrateInstance = hydration.canHydrateInstance,
9952 canHydrateTextInstance = hydration.canHydrateTextInstance,
9953 getNextHydratableSibling = hydration.getNextHydratableSibling,
9954 getFirstHydratableChild = hydration.getFirstHydratableChild,
9955 hydrateInstance = hydration.hydrateInstance,
9956 hydrateTextInstance = hydration.hydrateTextInstance,
9957 didNotMatchHydratedContainerTextInstance = hydration.didNotMatchHydratedContainerTextInstance,
9958 didNotMatchHydratedTextInstance = hydration.didNotMatchHydratedTextInstance,
9959 didNotHydrateContainerInstance = hydration.didNotHydrateContainerInstance,
9960 didNotHydrateInstance = hydration.didNotHydrateInstance,
9961 didNotFindHydratableContainerInstance = hydration.didNotFindHydratableContainerInstance,
9962 didNotFindHydratableContainerTextInstance = hydration.didNotFindHydratableContainerTextInstance,
9963 didNotFindHydratableInstance = hydration.didNotFindHydratableInstance,
9964 didNotFindHydratableTextInstance = hydration.didNotFindHydratableTextInstance;
9965
9966 // The deepest Fiber on the stack involved in a hydration context.
9967 // This may have been an insertion or a hydration.
9968
9969 var hydrationParentFiber = null;
9970 var nextHydratableInstance = null;
9971 var isHydrating = false;
9972
9973 function enterHydrationState(fiber) {
9974 var parentInstance = fiber.stateNode.containerInfo;
9975 nextHydratableInstance = getFirstHydratableChild(parentInstance);
9976 hydrationParentFiber = fiber;
9977 isHydrating = true;
9978 return true;
9979 }
9980
9981 function deleteHydratableInstance(returnFiber, instance) {
9982 {
9983 switch (returnFiber.tag) {
9984 case HostRoot:
9985 didNotHydrateContainerInstance(returnFiber.stateNode.containerInfo, instance);
9986 break;
9987 case HostComponent:
9988 didNotHydrateInstance(returnFiber.type, returnFiber.memoizedProps, returnFiber.stateNode, instance);
9989 break;
9990 }
9991 }
9992
9993 var childToDelete = createFiberFromHostInstanceForDeletion();
9994 childToDelete.stateNode = instance;
9995 childToDelete['return'] = returnFiber;
9996 childToDelete.effectTag = Deletion;
9997
9998 // This might seem like it belongs on progressedFirstDeletion. However,
9999 // these children are not part of the reconciliation list of children.
10000 // Even if we abort and rereconcile the children, that will try to hydrate
10001 // again and the nodes are still in the host tree so these will be
10002 // recreated.
10003 if (returnFiber.lastEffect !== null) {
10004 returnFiber.lastEffect.nextEffect = childToDelete;
10005 returnFiber.lastEffect = childToDelete;
10006 } else {
10007 returnFiber.firstEffect = returnFiber.lastEffect = childToDelete;
10008 }
10009 }
10010
10011 function insertNonHydratedInstance(returnFiber, fiber) {
10012 fiber.effectTag |= Placement;
10013 {
10014 switch (returnFiber.tag) {
10015 case HostRoot:
10016 {
10017 var parentContainer = returnFiber.stateNode.containerInfo;
10018 switch (fiber.tag) {
10019 case HostComponent:
10020 var type = fiber.type;
10021 var props = fiber.pendingProps;
10022 didNotFindHydratableContainerInstance(parentContainer, type, props);
10023 break;
10024 case HostText:
10025 var text = fiber.pendingProps;
10026 didNotFindHydratableContainerTextInstance(parentContainer, text);
10027 break;
10028 }
10029 break;
10030 }
10031 case HostComponent:
10032 {
10033 var parentType = returnFiber.type;
10034 var parentProps = returnFiber.memoizedProps;
10035 var parentInstance = returnFiber.stateNode;
10036 switch (fiber.tag) {
10037 case HostComponent:
10038 var _type = fiber.type;
10039 var _props = fiber.pendingProps;
10040 didNotFindHydratableInstance(parentType, parentProps, parentInstance, _type, _props);
10041 break;
10042 case HostText:
10043 var _text = fiber.pendingProps;
10044 didNotFindHydratableTextInstance(parentType, parentProps, parentInstance, _text);
10045 break;
10046 }
10047 break;
10048 }
10049 default:
10050 return;
10051 }
10052 }
10053 }
10054
10055 function tryHydrate(fiber, nextInstance) {
10056 switch (fiber.tag) {
10057 case HostComponent:
10058 {
10059 var type = fiber.type;
10060 var props = fiber.pendingProps;
10061 var instance = canHydrateInstance(nextInstance, type, props);
10062 if (instance !== null) {
10063 fiber.stateNode = instance;
10064 return true;
10065 }
10066 return false;
10067 }
10068 case HostText:
10069 {
10070 var text = fiber.pendingProps;
10071 var textInstance = canHydrateTextInstance(nextInstance, text);
10072 if (textInstance !== null) {
10073 fiber.stateNode = textInstance;
10074 return true;
10075 }
10076 return false;
10077 }
10078 default:
10079 return false;
10080 }
10081 }
10082
10083 function tryToClaimNextHydratableInstance(fiber) {
10084 if (!isHydrating) {
10085 return;
10086 }
10087 var nextInstance = nextHydratableInstance;
10088 if (!nextInstance) {
10089 // Nothing to hydrate. Make it an insertion.
10090 insertNonHydratedInstance(hydrationParentFiber, fiber);
10091 isHydrating = false;
10092 hydrationParentFiber = fiber;
10093 return;
10094 }
10095 if (!tryHydrate(fiber, nextInstance)) {
10096 // If we can't hydrate this instance let's try the next one.
10097 // We use this as a heuristic. It's based on intuition and not data so it
10098 // might be flawed or unnecessary.
10099 nextInstance = getNextHydratableSibling(nextInstance);
10100 if (!nextInstance || !tryHydrate(fiber, nextInstance)) {
10101 // Nothing to hydrate. Make it an insertion.
10102 insertNonHydratedInstance(hydrationParentFiber, fiber);
10103 isHydrating = false;
10104 hydrationParentFiber = fiber;
10105 return;
10106 }
10107 // We matched the next one, we'll now assume that the first one was
10108 // superfluous and we'll delete it. Since we can't eagerly delete it
10109 // we'll have to schedule a deletion. To do that, this node needs a dummy
10110 // fiber associated with it.
10111 deleteHydratableInstance(hydrationParentFiber, nextHydratableInstance);
10112 }
10113 hydrationParentFiber = fiber;
10114 nextHydratableInstance = getFirstHydratableChild(nextInstance);
10115 }
10116
10117 function prepareToHydrateHostInstance(fiber, rootContainerInstance, hostContext) {
10118 var instance = fiber.stateNode;
10119 var updatePayload = hydrateInstance(instance, fiber.type, fiber.memoizedProps, rootContainerInstance, hostContext, fiber);
10120 // TODO: Type this specific to this type of component.
10121 fiber.updateQueue = updatePayload;
10122 // If the update payload indicates that there is a change or if there
10123 // is a new ref we mark this as an update.
10124 if (updatePayload !== null) {
10125 return true;
10126 }
10127 return false;
10128 }
10129
10130 function prepareToHydrateHostTextInstance(fiber) {
10131 var textInstance = fiber.stateNode;
10132 var textContent = fiber.memoizedProps;
10133 var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber);
10134 {
10135 if (shouldUpdate) {
10136 // We assume that prepareToHydrateHostTextInstance is called in a context where the
10137 // hydration parent is the parent host component of this host text.
10138 var returnFiber = hydrationParentFiber;
10139 if (returnFiber !== null) {
10140 switch (returnFiber.tag) {
10141 case HostRoot:
10142 {
10143 var parentContainer = returnFiber.stateNode.containerInfo;
10144 didNotMatchHydratedContainerTextInstance(parentContainer, textInstance, textContent);
10145 break;
10146 }
10147 case HostComponent:
10148 {
10149 var parentType = returnFiber.type;
10150 var parentProps = returnFiber.memoizedProps;
10151 var parentInstance = returnFiber.stateNode;
10152 didNotMatchHydratedTextInstance(parentType, parentProps, parentInstance, textInstance, textContent);
10153 break;
10154 }
10155 }
10156 }
10157 }
10158 }
10159 return shouldUpdate;
10160 }
10161
10162 function popToNextHostParent(fiber) {
10163 var parent = fiber['return'];
10164 while (parent !== null && parent.tag !== HostComponent && parent.tag !== HostRoot) {
10165 parent = parent['return'];
10166 }
10167 hydrationParentFiber = parent;
10168 }
10169
10170 function popHydrationState(fiber) {
10171 if (fiber !== hydrationParentFiber) {
10172 // We're deeper than the current hydration context, inside an inserted
10173 // tree.
10174 return false;
10175 }
10176 if (!isHydrating) {
10177 // If we're not currently hydrating but we're in a hydration context, then
10178 // we were an insertion and now need to pop up reenter hydration of our
10179 // siblings.
10180 popToNextHostParent(fiber);
10181 isHydrating = true;
10182 return false;
10183 }
10184
10185 var type = fiber.type;
10186
10187 // If we have any remaining hydratable nodes, we need to delete them now.
10188 // We only do this deeper than head and body since they tend to have random
10189 // other nodes in them. We also ignore components with pure text content in
10190 // side of them.
10191 // TODO: Better heuristic.
10192 if (fiber.tag !== HostComponent || type !== 'head' && type !== 'body' && !shouldSetTextContent(type, fiber.memoizedProps)) {
10193 var nextInstance = nextHydratableInstance;
10194 while (nextInstance) {
10195 deleteHydratableInstance(fiber, nextInstance);
10196 nextInstance = getNextHydratableSibling(nextInstance);
10197 }
10198 }
10199
10200 popToNextHostParent(fiber);
10201 nextHydratableInstance = hydrationParentFiber ? getNextHydratableSibling(fiber.stateNode) : null;
10202 return true;
10203 }
10204
10205 function resetHydrationState() {
10206 hydrationParentFiber = null;
10207 nextHydratableInstance = null;
10208 isHydrating = false;
10209 }
10210
10211 return {
10212 enterHydrationState: enterHydrationState,
10213 resetHydrationState: resetHydrationState,
10214 tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance,
10215 prepareToHydrateHostInstance: prepareToHydrateHostInstance,
10216 prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance,
10217 popHydrationState: popHydrationState
10218 };
10219};
10220
10221// This lets us hook into Fiber to debug what it's doing.
10222// See https://github.com/facebook/react/pull/8033.
10223// This is not part of the public API, not even for React DevTools.
10224// You may only inject a debugTool if you work on React Fiber itself.
10225var ReactFiberInstrumentation = {
10226 debugTool: null
10227};
10228
10229var ReactFiberInstrumentation_1 = ReactFiberInstrumentation;
10230
10231// This module is forked in different environments.
10232// By default, return `true` to log errors to the console.
10233// Forks can return `false` if this isn't desirable.
10234function showErrorDialog(capturedError) {
10235 return true;
10236}
10237
10238function logCapturedError(capturedError) {
10239 var logError = showErrorDialog(capturedError);
10240
10241 // Allow injected showErrorDialog() to prevent default console.error logging.
10242 // This enables renderers like ReactNative to better manage redbox behavior.
10243 if (logError === false) {
10244 return;
10245 }
10246
10247 var error = capturedError.error;
10248 var suppressLogging = error && error.suppressReactErrorLogging;
10249 if (suppressLogging) {
10250 return;
10251 }
10252
10253 {
10254 var componentName = capturedError.componentName,
10255 componentStack = capturedError.componentStack,
10256 errorBoundaryName = capturedError.errorBoundaryName,
10257 errorBoundaryFound = capturedError.errorBoundaryFound,
10258 willRetry = capturedError.willRetry;
10259
10260
10261 var componentNameMessage = componentName ? 'The above error occurred in the <' + componentName + '> component:' : 'The above error occurred in one of your React components:';
10262
10263 var errorBoundaryMessage = void 0;
10264 // errorBoundaryFound check is sufficient; errorBoundaryName check is to satisfy Flow.
10265 if (errorBoundaryFound && errorBoundaryName) {
10266 if (willRetry) {
10267 errorBoundaryMessage = 'React will try to recreate this component tree from scratch ' + ('using the error boundary you provided, ' + errorBoundaryName + '.');
10268 } else {
10269 errorBoundaryMessage = 'This error was initially handled by the error boundary ' + errorBoundaryName + '.\n' + 'Recreating the tree from scratch failed so React will unmount the tree.';
10270 }
10271 } else {
10272 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.';
10273 }
10274 var combinedMessage = '' + componentNameMessage + componentStack + '\n\n' + ('' + errorBoundaryMessage);
10275
10276 // In development, we provide our own message with just the component stack.
10277 // We don't include the original error message and JS stack because the browser
10278 // has already printed it. Even if the application swallows the error, it is still
10279 // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils.
10280 console.error(combinedMessage);
10281 }
10282}
10283
10284var invokeGuardedCallback$2 = ReactErrorUtils.invokeGuardedCallback;
10285var hasCaughtError = ReactErrorUtils.hasCaughtError;
10286var clearCaughtError = ReactErrorUtils.clearCaughtError;
10287
10288
10289var didWarnAboutStateTransition = void 0;
10290var didWarnSetStateChildContext = void 0;
10291var warnAboutUpdateOnUnmounted = void 0;
10292var warnAboutInvalidUpdates = void 0;
10293
10294{
10295 didWarnAboutStateTransition = false;
10296 didWarnSetStateChildContext = false;
10297 var didWarnStateUpdateForUnmountedComponent = {};
10298
10299 warnAboutUpdateOnUnmounted = function (fiber) {
10300 var componentName = getComponentName(fiber) || 'ReactClass';
10301 if (didWarnStateUpdateForUnmountedComponent[componentName]) {
10302 return;
10303 }
10304 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);
10305 didWarnStateUpdateForUnmountedComponent[componentName] = true;
10306 };
10307
10308 warnAboutInvalidUpdates = function (instance) {
10309 switch (ReactDebugCurrentFiber.phase) {
10310 case 'getChildContext':
10311 if (didWarnSetStateChildContext) {
10312 return;
10313 }
10314 warning_1(false, 'setState(...): Cannot call setState() inside getChildContext()');
10315 didWarnSetStateChildContext = true;
10316 break;
10317 case 'render':
10318 if (didWarnAboutStateTransition) {
10319 return;
10320 }
10321 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`.');
10322 didWarnAboutStateTransition = true;
10323 break;
10324 }
10325 };
10326}
10327
10328var ReactFiberScheduler = function (config) {
10329 var hostContext = ReactFiberHostContext(config);
10330 var hydrationContext = ReactFiberHydrationContext(config);
10331 var popHostContainer = hostContext.popHostContainer,
10332 popHostContext = hostContext.popHostContext,
10333 resetHostContainer = hostContext.resetHostContainer;
10334
10335 var _ReactFiberBeginWork = ReactFiberBeginWork(config, hostContext, hydrationContext, scheduleWork, computeExpirationForFiber),
10336 beginWork = _ReactFiberBeginWork.beginWork,
10337 beginFailedWork = _ReactFiberBeginWork.beginFailedWork;
10338
10339 var _ReactFiberCompleteWo = ReactFiberCompleteWork(config, hostContext, hydrationContext),
10340 completeWork = _ReactFiberCompleteWo.completeWork;
10341
10342 var _ReactFiberCommitWork = ReactFiberCommitWork(config, captureError),
10343 commitResetTextContent = _ReactFiberCommitWork.commitResetTextContent,
10344 commitPlacement = _ReactFiberCommitWork.commitPlacement,
10345 commitDeletion = _ReactFiberCommitWork.commitDeletion,
10346 commitWork = _ReactFiberCommitWork.commitWork,
10347 commitLifeCycles = _ReactFiberCommitWork.commitLifeCycles,
10348 commitAttachRef = _ReactFiberCommitWork.commitAttachRef,
10349 commitDetachRef = _ReactFiberCommitWork.commitDetachRef;
10350
10351 var now = config.now,
10352 scheduleDeferredCallback = config.scheduleDeferredCallback,
10353 cancelDeferredCallback = config.cancelDeferredCallback,
10354 prepareForCommit = config.prepareForCommit,
10355 resetAfterCommit = config.resetAfterCommit;
10356
10357 // Represents the current time in ms.
10358
10359 var startTime = now();
10360 var mostRecentCurrentTime = msToExpirationTime(0);
10361
10362 // Used to ensure computeUniqueAsyncExpiration is monotonically increases.
10363 var lastUniqueAsyncExpiration = 0;
10364
10365 // Represents the expiration time that incoming updates should use. (If this
10366 // is NoWork, use the default strategy: async updates in async mode, sync
10367 // updates in sync mode.)
10368 var expirationContext = NoWork;
10369
10370 var isWorking = false;
10371
10372 // The next work in progress fiber that we're currently working on.
10373 var nextUnitOfWork = null;
10374 var nextRoot = null;
10375 // The time at which we're currently rendering work.
10376 var nextRenderExpirationTime = NoWork;
10377
10378 // The next fiber with an effect that we're currently committing.
10379 var nextEffect = null;
10380
10381 // Keep track of which fibers have captured an error that need to be handled.
10382 // Work is removed from this collection after componentDidCatch is called.
10383 var capturedErrors = null;
10384 // Keep track of which fibers have failed during the current batch of work.
10385 // This is a different set than capturedErrors, because it is not reset until
10386 // the end of the batch. This is needed to propagate errors correctly if a
10387 // subtree fails more than once.
10388 var failedBoundaries = null;
10389 // Error boundaries that captured an error during the current commit.
10390 var commitPhaseBoundaries = null;
10391 var firstUncaughtError = null;
10392 var didFatal = false;
10393
10394 var isCommitting = false;
10395 var isUnmounting = false;
10396
10397 // Used for performance tracking.
10398 var interruptedBy = null;
10399
10400 function resetContextStack() {
10401 // Reset the stack
10402 reset$1();
10403 // Reset the cursors
10404 resetContext();
10405 resetHostContainer();
10406 }
10407
10408 function commitAllHostEffects() {
10409 while (nextEffect !== null) {
10410 {
10411 ReactDebugCurrentFiber.setCurrentFiber(nextEffect);
10412 }
10413 recordEffect();
10414
10415 var effectTag = nextEffect.effectTag;
10416 if (effectTag & ContentReset) {
10417 commitResetTextContent(nextEffect);
10418 }
10419
10420 if (effectTag & Ref) {
10421 var current = nextEffect.alternate;
10422 if (current !== null) {
10423 commitDetachRef(current);
10424 }
10425 }
10426
10427 // The following switch statement is only concerned about placement,
10428 // updates, and deletions. To avoid needing to add a case for every
10429 // possible bitmap value, we remove the secondary effects from the
10430 // effect tag and switch on that value.
10431 var primaryEffectTag = effectTag & ~(Callback | Err | ContentReset | Ref | PerformedWork);
10432 switch (primaryEffectTag) {
10433 case Placement:
10434 {
10435 commitPlacement(nextEffect);
10436 // Clear the "placement" from effect tag so that we know that this is inserted, before
10437 // any life-cycles like componentDidMount gets called.
10438 // TODO: findDOMNode doesn't rely on this any more but isMounted
10439 // does and isMounted is deprecated anyway so we should be able
10440 // to kill this.
10441 nextEffect.effectTag &= ~Placement;
10442 break;
10443 }
10444 case PlacementAndUpdate:
10445 {
10446 // Placement
10447 commitPlacement(nextEffect);
10448 // Clear the "placement" from effect tag so that we know that this is inserted, before
10449 // any life-cycles like componentDidMount gets called.
10450 nextEffect.effectTag &= ~Placement;
10451
10452 // Update
10453 var _current = nextEffect.alternate;
10454 commitWork(_current, nextEffect);
10455 break;
10456 }
10457 case Update:
10458 {
10459 var _current2 = nextEffect.alternate;
10460 commitWork(_current2, nextEffect);
10461 break;
10462 }
10463 case Deletion:
10464 {
10465 isUnmounting = true;
10466 commitDeletion(nextEffect);
10467 isUnmounting = false;
10468 break;
10469 }
10470 }
10471 nextEffect = nextEffect.nextEffect;
10472 }
10473
10474 {
10475 ReactDebugCurrentFiber.resetCurrentFiber();
10476 }
10477 }
10478
10479 function commitAllLifeCycles() {
10480 while (nextEffect !== null) {
10481 var effectTag = nextEffect.effectTag;
10482
10483 if (effectTag & (Update | Callback)) {
10484 recordEffect();
10485 var current = nextEffect.alternate;
10486 commitLifeCycles(current, nextEffect);
10487 }
10488
10489 if (effectTag & Ref) {
10490 recordEffect();
10491 commitAttachRef(nextEffect);
10492 }
10493
10494 if (effectTag & Err) {
10495 recordEffect();
10496 commitErrorHandling(nextEffect);
10497 }
10498
10499 var next = nextEffect.nextEffect;
10500 // Ensure that we clean these up so that we don't accidentally keep them.
10501 // I'm not actually sure this matters because we can't reset firstEffect
10502 // and lastEffect since they're on every node, not just the effectful
10503 // ones. So we have to clean everything as we reuse nodes anyway.
10504 nextEffect.nextEffect = null;
10505 // Ensure that we reset the effectTag here so that we can rely on effect
10506 // tags to reason about the current life-cycle.
10507 nextEffect = next;
10508 }
10509 }
10510
10511 function commitRoot(finishedWork) {
10512 // We keep track of this so that captureError can collect any boundaries
10513 // that capture an error during the commit phase. The reason these aren't
10514 // local to this function is because errors that occur during cWU are
10515 // captured elsewhere, to prevent the unmount from being interrupted.
10516 isWorking = true;
10517 isCommitting = true;
10518 startCommitTimer();
10519
10520 var root = finishedWork.stateNode;
10521 !(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;
10522 root.isReadyForCommit = false;
10523
10524 // Reset this to null before calling lifecycles
10525 ReactCurrentOwner.current = null;
10526
10527 var firstEffect = void 0;
10528 if (finishedWork.effectTag > PerformedWork) {
10529 // A fiber's effect list consists only of its children, not itself. So if
10530 // the root has an effect, we need to add it to the end of the list. The
10531 // resulting list is the set that would belong to the root's parent, if
10532 // it had one; that is, all the effects in the tree including the root.
10533 if (finishedWork.lastEffect !== null) {
10534 finishedWork.lastEffect.nextEffect = finishedWork;
10535 firstEffect = finishedWork.firstEffect;
10536 } else {
10537 firstEffect = finishedWork;
10538 }
10539 } else {
10540 // There is no effect on the root.
10541 firstEffect = finishedWork.firstEffect;
10542 }
10543
10544 prepareForCommit();
10545
10546 // Commit all the side-effects within a tree. We'll do this in two passes.
10547 // The first pass performs all the host insertions, updates, deletions and
10548 // ref unmounts.
10549 nextEffect = firstEffect;
10550 startCommitHostEffectsTimer();
10551 while (nextEffect !== null) {
10552 var didError = false;
10553 var _error = void 0;
10554 {
10555 invokeGuardedCallback$2(null, commitAllHostEffects, null);
10556 if (hasCaughtError()) {
10557 didError = true;
10558 _error = clearCaughtError();
10559 }
10560 }
10561 if (didError) {
10562 !(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;
10563 captureError(nextEffect, _error);
10564 // Clean-up
10565 if (nextEffect !== null) {
10566 nextEffect = nextEffect.nextEffect;
10567 }
10568 }
10569 }
10570 stopCommitHostEffectsTimer();
10571
10572 resetAfterCommit();
10573
10574 // The work-in-progress tree is now the current tree. This must come after
10575 // the first pass of the commit phase, so that the previous tree is still
10576 // current during componentWillUnmount, but before the second pass, so that
10577 // the finished work is current during componentDidMount/Update.
10578 root.current = finishedWork;
10579
10580 // In the second pass we'll perform all life-cycles and ref callbacks.
10581 // Life-cycles happen as a separate pass so that all placements, updates,
10582 // and deletions in the entire tree have already been invoked.
10583 // This pass also triggers any renderer-specific initial effects.
10584 nextEffect = firstEffect;
10585 startCommitLifeCyclesTimer();
10586 while (nextEffect !== null) {
10587 var _didError = false;
10588 var _error2 = void 0;
10589 {
10590 invokeGuardedCallback$2(null, commitAllLifeCycles, null);
10591 if (hasCaughtError()) {
10592 _didError = true;
10593 _error2 = clearCaughtError();
10594 }
10595 }
10596 if (_didError) {
10597 !(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;
10598 captureError(nextEffect, _error2);
10599 if (nextEffect !== null) {
10600 nextEffect = nextEffect.nextEffect;
10601 }
10602 }
10603 }
10604
10605 isCommitting = false;
10606 isWorking = false;
10607 stopCommitLifeCyclesTimer();
10608 stopCommitTimer();
10609 if (typeof onCommitRoot === 'function') {
10610 onCommitRoot(finishedWork.stateNode);
10611 }
10612 if (true && ReactFiberInstrumentation_1.debugTool) {
10613 ReactFiberInstrumentation_1.debugTool.onCommitWork(finishedWork);
10614 }
10615
10616 // If we caught any errors during this commit, schedule their boundaries
10617 // to update.
10618 if (commitPhaseBoundaries) {
10619 commitPhaseBoundaries.forEach(scheduleErrorRecovery);
10620 commitPhaseBoundaries = null;
10621 }
10622
10623 if (firstUncaughtError !== null) {
10624 var _error3 = firstUncaughtError;
10625 firstUncaughtError = null;
10626 onUncaughtError(_error3);
10627 }
10628
10629 var remainingTime = root.current.expirationTime;
10630
10631 if (remainingTime === NoWork) {
10632 capturedErrors = null;
10633 failedBoundaries = null;
10634 }
10635
10636 return remainingTime;
10637 }
10638
10639 function resetExpirationTime(workInProgress, renderTime) {
10640 if (renderTime !== Never && workInProgress.expirationTime === Never) {
10641 // The children of this component are hidden. Don't bubble their
10642 // expiration times.
10643 return;
10644 }
10645
10646 // Check for pending updates.
10647 var newExpirationTime = getUpdateExpirationTime(workInProgress);
10648
10649 // TODO: Calls need to visit stateNode
10650
10651 // Bubble up the earliest expiration time.
10652 var child = workInProgress.child;
10653 while (child !== null) {
10654 if (child.expirationTime !== NoWork && (newExpirationTime === NoWork || newExpirationTime > child.expirationTime)) {
10655 newExpirationTime = child.expirationTime;
10656 }
10657 child = child.sibling;
10658 }
10659 workInProgress.expirationTime = newExpirationTime;
10660 }
10661
10662 function completeUnitOfWork(workInProgress) {
10663 while (true) {
10664 // The current, flushed, state of this fiber is the alternate.
10665 // Ideally nothing should rely on this, but relying on it here
10666 // means that we don't need an additional field on the work in
10667 // progress.
10668 var current = workInProgress.alternate;
10669 {
10670 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10671 }
10672 var next = completeWork(current, workInProgress, nextRenderExpirationTime);
10673 {
10674 ReactDebugCurrentFiber.resetCurrentFiber();
10675 }
10676
10677 var returnFiber = workInProgress['return'];
10678 var siblingFiber = workInProgress.sibling;
10679
10680 resetExpirationTime(workInProgress, nextRenderExpirationTime);
10681
10682 if (next !== null) {
10683 stopWorkTimer(workInProgress);
10684 if (true && ReactFiberInstrumentation_1.debugTool) {
10685 ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress);
10686 }
10687 // If completing this work spawned new work, do that next. We'll come
10688 // back here again.
10689 return next;
10690 }
10691
10692 if (returnFiber !== null) {
10693 // Append all the effects of the subtree and this fiber onto the effect
10694 // list of the parent. The completion order of the children affects the
10695 // side-effect order.
10696 if (returnFiber.firstEffect === null) {
10697 returnFiber.firstEffect = workInProgress.firstEffect;
10698 }
10699 if (workInProgress.lastEffect !== null) {
10700 if (returnFiber.lastEffect !== null) {
10701 returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;
10702 }
10703 returnFiber.lastEffect = workInProgress.lastEffect;
10704 }
10705
10706 // If this fiber had side-effects, we append it AFTER the children's
10707 // side-effects. We can perform certain side-effects earlier if
10708 // needed, by doing multiple passes over the effect list. We don't want
10709 // to schedule our own side-effect on our own list because if end up
10710 // reusing children we'll schedule this effect onto itself since we're
10711 // at the end.
10712 var effectTag = workInProgress.effectTag;
10713 // Skip both NoWork and PerformedWork tags when creating the effect list.
10714 // PerformedWork effect is read by React DevTools but shouldn't be committed.
10715 if (effectTag > PerformedWork) {
10716 if (returnFiber.lastEffect !== null) {
10717 returnFiber.lastEffect.nextEffect = workInProgress;
10718 } else {
10719 returnFiber.firstEffect = workInProgress;
10720 }
10721 returnFiber.lastEffect = workInProgress;
10722 }
10723 }
10724
10725 stopWorkTimer(workInProgress);
10726 if (true && ReactFiberInstrumentation_1.debugTool) {
10727 ReactFiberInstrumentation_1.debugTool.onCompleteWork(workInProgress);
10728 }
10729
10730 if (siblingFiber !== null) {
10731 // If there is more work to do in this returnFiber, do that next.
10732 return siblingFiber;
10733 } else if (returnFiber !== null) {
10734 // If there's no more work in this returnFiber. Complete the returnFiber.
10735 workInProgress = returnFiber;
10736 continue;
10737 } else {
10738 // We've reached the root.
10739 var root = workInProgress.stateNode;
10740 root.isReadyForCommit = true;
10741 return null;
10742 }
10743 }
10744
10745 // Without this explicit null return Flow complains of invalid return type
10746 // TODO Remove the above while(true) loop
10747 // eslint-disable-next-line no-unreachable
10748 return null;
10749 }
10750
10751 function performUnitOfWork(workInProgress) {
10752 // The current, flushed, state of this fiber is the alternate.
10753 // Ideally nothing should rely on this, but relying on it here
10754 // means that we don't need an additional field on the work in
10755 // progress.
10756 var current = workInProgress.alternate;
10757
10758 // See if beginning this work spawns more work.
10759 startWorkTimer(workInProgress);
10760 {
10761 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10762 }
10763
10764 var next = beginWork(current, workInProgress, nextRenderExpirationTime);
10765 {
10766 ReactDebugCurrentFiber.resetCurrentFiber();
10767 }
10768 if (true && ReactFiberInstrumentation_1.debugTool) {
10769 ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
10770 }
10771
10772 if (next === null) {
10773 // If this doesn't spawn new work, complete the current work.
10774 next = completeUnitOfWork(workInProgress);
10775 }
10776
10777 ReactCurrentOwner.current = null;
10778
10779 return next;
10780 }
10781
10782 function performFailedUnitOfWork(workInProgress) {
10783 // The current, flushed, state of this fiber is the alternate.
10784 // Ideally nothing should rely on this, but relying on it here
10785 // means that we don't need an additional field on the work in
10786 // progress.
10787 var current = workInProgress.alternate;
10788
10789 // See if beginning this work spawns more work.
10790 startWorkTimer(workInProgress);
10791 {
10792 ReactDebugCurrentFiber.setCurrentFiber(workInProgress);
10793 }
10794 var next = beginFailedWork(current, workInProgress, nextRenderExpirationTime);
10795 {
10796 ReactDebugCurrentFiber.resetCurrentFiber();
10797 }
10798 if (true && ReactFiberInstrumentation_1.debugTool) {
10799 ReactFiberInstrumentation_1.debugTool.onBeginWork(workInProgress);
10800 }
10801
10802 if (next === null) {
10803 // If this doesn't spawn new work, complete the current work.
10804 next = completeUnitOfWork(workInProgress);
10805 }
10806
10807 ReactCurrentOwner.current = null;
10808
10809 return next;
10810 }
10811
10812 function workLoop(expirationTime) {
10813 if (capturedErrors !== null) {
10814 // If there are unhandled errors, switch to the slow work loop.
10815 // TODO: How to avoid this check in the fast path? Maybe the renderer
10816 // could keep track of which roots have unhandled errors and call a
10817 // forked version of renderRoot.
10818 slowWorkLoopThatChecksForFailedWork(expirationTime);
10819 return;
10820 }
10821 if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
10822 return;
10823 }
10824
10825 if (nextRenderExpirationTime <= mostRecentCurrentTime) {
10826 // Flush all expired work.
10827 while (nextUnitOfWork !== null) {
10828 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10829 }
10830 } else {
10831 // Flush asynchronous work until the deadline runs out of time.
10832 while (nextUnitOfWork !== null && !shouldYield()) {
10833 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10834 }
10835 }
10836 }
10837
10838 function slowWorkLoopThatChecksForFailedWork(expirationTime) {
10839 if (nextRenderExpirationTime === NoWork || nextRenderExpirationTime > expirationTime) {
10840 return;
10841 }
10842
10843 if (nextRenderExpirationTime <= mostRecentCurrentTime) {
10844 // Flush all expired work.
10845 while (nextUnitOfWork !== null) {
10846 if (hasCapturedError(nextUnitOfWork)) {
10847 // Use a forked version of performUnitOfWork
10848 nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork);
10849 } else {
10850 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10851 }
10852 }
10853 } else {
10854 // Flush asynchronous work until the deadline runs out of time.
10855 while (nextUnitOfWork !== null && !shouldYield()) {
10856 if (hasCapturedError(nextUnitOfWork)) {
10857 // Use a forked version of performUnitOfWork
10858 nextUnitOfWork = performFailedUnitOfWork(nextUnitOfWork);
10859 } else {
10860 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
10861 }
10862 }
10863 }
10864 }
10865
10866 function renderRootCatchBlock(root, failedWork, boundary, expirationTime) {
10867 // We're going to restart the error boundary that captured the error.
10868 // Conceptually, we're unwinding the stack. We need to unwind the
10869 // context stack, too.
10870 unwindContexts(failedWork, boundary);
10871
10872 // Restart the error boundary using a forked version of
10873 // performUnitOfWork that deletes the boundary's children. The entire
10874 // failed subree will be unmounted. During the commit phase, a special
10875 // lifecycle method is called on the error boundary, which triggers
10876 // a re-render.
10877 nextUnitOfWork = performFailedUnitOfWork(boundary);
10878
10879 // Continue working.
10880 workLoop(expirationTime);
10881 }
10882
10883 function renderRoot(root, expirationTime) {
10884 !!isWorking ? invariant_1(false, 'renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
10885 isWorking = true;
10886
10887 // We're about to mutate the work-in-progress tree. If the root was pending
10888 // commit, it no longer is: we'll need to complete it again.
10889 root.isReadyForCommit = false;
10890
10891 // Check if we're starting from a fresh stack, or if we're resuming from
10892 // previously yielded work.
10893 if (root !== nextRoot || expirationTime !== nextRenderExpirationTime || nextUnitOfWork === null) {
10894 // Reset the stack and start working from the root.
10895 resetContextStack();
10896 nextRoot = root;
10897 nextRenderExpirationTime = expirationTime;
10898 nextUnitOfWork = createWorkInProgress(nextRoot.current, null, expirationTime);
10899 }
10900
10901 startWorkLoopTimer(nextUnitOfWork);
10902
10903 var didError = false;
10904 var error = null;
10905 {
10906 invokeGuardedCallback$2(null, workLoop, null, expirationTime);
10907 if (hasCaughtError()) {
10908 didError = true;
10909 error = clearCaughtError();
10910 }
10911 }
10912
10913 // An error was thrown during the render phase.
10914 while (didError) {
10915 if (didFatal) {
10916 // This was a fatal error. Don't attempt to recover from it.
10917 firstUncaughtError = error;
10918 break;
10919 }
10920
10921 var failedWork = nextUnitOfWork;
10922 if (failedWork === null) {
10923 // An error was thrown but there's no current unit of work. This can
10924 // happen during the commit phase if there's a bug in the renderer.
10925 didFatal = true;
10926 continue;
10927 }
10928
10929 // "Capture" the error by finding the nearest boundary. If there is no
10930 // error boundary, we use the root.
10931 var boundary = captureError(failedWork, error);
10932 !(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;
10933
10934 if (didFatal) {
10935 // The error we just captured was a fatal error. This happens
10936 // when the error propagates to the root more than once.
10937 continue;
10938 }
10939
10940 didError = false;
10941 error = null;
10942 {
10943 invokeGuardedCallback$2(null, renderRootCatchBlock, null, root, failedWork, boundary, expirationTime);
10944 if (hasCaughtError()) {
10945 didError = true;
10946 error = clearCaughtError();
10947 continue;
10948 }
10949 }
10950 // We're finished working. Exit the error loop.
10951 break;
10952 }
10953
10954 var uncaughtError = firstUncaughtError;
10955
10956 // We're done performing work. Time to clean up.
10957 stopWorkLoopTimer(interruptedBy);
10958 interruptedBy = null;
10959 isWorking = false;
10960 didFatal = false;
10961 firstUncaughtError = null;
10962
10963 if (uncaughtError !== null) {
10964 onUncaughtError(uncaughtError);
10965 }
10966
10967 return root.isReadyForCommit ? root.current.alternate : null;
10968 }
10969
10970 // Returns the boundary that captured the error, or null if the error is ignored
10971 function captureError(failedWork, error) {
10972 // It is no longer valid because we exited the user code.
10973 ReactCurrentOwner.current = null;
10974 {
10975 ReactDebugCurrentFiber.resetCurrentFiber();
10976 }
10977
10978 // Search for the nearest error boundary.
10979 var boundary = null;
10980
10981 // Passed to logCapturedError()
10982 var errorBoundaryFound = false;
10983 var willRetry = false;
10984 var errorBoundaryName = null;
10985
10986 // Host containers are a special case. If the failed work itself is a host
10987 // container, then it acts as its own boundary. In all other cases, we
10988 // ignore the work itself and only search through the parents.
10989 if (failedWork.tag === HostRoot) {
10990 boundary = failedWork;
10991
10992 if (isFailedBoundary(failedWork)) {
10993 // If this root already failed, there must have been an error when
10994 // attempting to unmount it. This is a worst-case scenario and
10995 // should only be possible if there's a bug in the renderer.
10996 didFatal = true;
10997 }
10998 } else {
10999 var node = failedWork['return'];
11000 while (node !== null && boundary === null) {
11001 if (node.tag === ClassComponent) {
11002 var instance = node.stateNode;
11003 if (typeof instance.componentDidCatch === 'function') {
11004 errorBoundaryFound = true;
11005 errorBoundaryName = getComponentName(node);
11006
11007 // Found an error boundary!
11008 boundary = node;
11009 willRetry = true;
11010 }
11011 } else if (node.tag === HostRoot) {
11012 // Treat the root like a no-op error boundary
11013 boundary = node;
11014 }
11015
11016 if (isFailedBoundary(node)) {
11017 // This boundary is already in a failed state.
11018
11019 // If we're currently unmounting, that means this error was
11020 // thrown while unmounting a failed subtree. We should ignore
11021 // the error.
11022 if (isUnmounting) {
11023 return null;
11024 }
11025
11026 // If we're in the commit phase, we should check to see if
11027 // this boundary already captured an error during this commit.
11028 // This case exists because multiple errors can be thrown during
11029 // a single commit without interruption.
11030 if (commitPhaseBoundaries !== null && (commitPhaseBoundaries.has(node) || node.alternate !== null && commitPhaseBoundaries.has(node.alternate))) {
11031 // If so, we should ignore this error.
11032 return null;
11033 }
11034
11035 // The error should propagate to the next boundary -? we keep looking.
11036 boundary = null;
11037 willRetry = false;
11038 }
11039
11040 node = node['return'];
11041 }
11042 }
11043
11044 if (boundary !== null) {
11045 // Add to the collection of failed boundaries. This lets us know that
11046 // subsequent errors in this subtree should propagate to the next boundary.
11047 if (failedBoundaries === null) {
11048 failedBoundaries = new Set();
11049 }
11050 failedBoundaries.add(boundary);
11051
11052 // This method is unsafe outside of the begin and complete phases.
11053 // We might be in the commit phase when an error is captured.
11054 // The risk is that the return path from this Fiber may not be accurate.
11055 // That risk is acceptable given the benefit of providing users more context.
11056 var _componentStack = getStackAddendumByWorkInProgressFiber(failedWork);
11057 var _componentName = getComponentName(failedWork);
11058
11059 // Add to the collection of captured errors. This is stored as a global
11060 // map of errors and their component stack location keyed by the boundaries
11061 // that capture them. We mostly use this Map as a Set; it's a Map only to
11062 // avoid adding a field to Fiber to store the error.
11063 if (capturedErrors === null) {
11064 capturedErrors = new Map();
11065 }
11066
11067 var capturedError = {
11068 componentName: _componentName,
11069 componentStack: _componentStack,
11070 error: error,
11071 errorBoundary: errorBoundaryFound ? boundary.stateNode : null,
11072 errorBoundaryFound: errorBoundaryFound,
11073 errorBoundaryName: errorBoundaryName,
11074 willRetry: willRetry
11075 };
11076
11077 capturedErrors.set(boundary, capturedError);
11078
11079 try {
11080 logCapturedError(capturedError);
11081 } catch (e) {
11082 // Prevent cycle if logCapturedError() throws.
11083 // A cycle may still occur if logCapturedError renders a component that throws.
11084 var suppressLogging = e && e.suppressReactErrorLogging;
11085 if (!suppressLogging) {
11086 console.error(e);
11087 }
11088 }
11089
11090 // If we're in the commit phase, defer scheduling an update on the
11091 // boundary until after the commit is complete
11092 if (isCommitting) {
11093 if (commitPhaseBoundaries === null) {
11094 commitPhaseBoundaries = new Set();
11095 }
11096 commitPhaseBoundaries.add(boundary);
11097 } else {
11098 // Otherwise, schedule an update now.
11099 // TODO: Is this actually necessary during the render phase? Is it
11100 // possible to unwind and continue rendering at the same priority,
11101 // without corrupting internal state?
11102 scheduleErrorRecovery(boundary);
11103 }
11104 return boundary;
11105 } else if (firstUncaughtError === null) {
11106 // If no boundary is found, we'll need to throw the error
11107 firstUncaughtError = error;
11108 }
11109 return null;
11110 }
11111
11112 function hasCapturedError(fiber) {
11113 // TODO: capturedErrors should store the boundary instance, to avoid needing
11114 // to check the alternate.
11115 return capturedErrors !== null && (capturedErrors.has(fiber) || fiber.alternate !== null && capturedErrors.has(fiber.alternate));
11116 }
11117
11118 function isFailedBoundary(fiber) {
11119 // TODO: failedBoundaries should store the boundary instance, to avoid
11120 // needing to check the alternate.
11121 return failedBoundaries !== null && (failedBoundaries.has(fiber) || fiber.alternate !== null && failedBoundaries.has(fiber.alternate));
11122 }
11123
11124 function commitErrorHandling(effectfulFiber) {
11125 var capturedError = void 0;
11126 if (capturedErrors !== null) {
11127 capturedError = capturedErrors.get(effectfulFiber);
11128 capturedErrors['delete'](effectfulFiber);
11129 if (capturedError == null) {
11130 if (effectfulFiber.alternate !== null) {
11131 effectfulFiber = effectfulFiber.alternate;
11132 capturedError = capturedErrors.get(effectfulFiber);
11133 capturedErrors['delete'](effectfulFiber);
11134 }
11135 }
11136 }
11137
11138 !(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;
11139
11140 switch (effectfulFiber.tag) {
11141 case ClassComponent:
11142 var instance = effectfulFiber.stateNode;
11143
11144 var info = {
11145 componentStack: capturedError.componentStack
11146 };
11147
11148 // Allow the boundary to handle the error, usually by scheduling
11149 // an update to itself
11150 instance.componentDidCatch(capturedError.error, info);
11151 return;
11152 case HostRoot:
11153 if (firstUncaughtError === null) {
11154 firstUncaughtError = capturedError.error;
11155 }
11156 return;
11157 default:
11158 invariant_1(false, 'Invalid type of work. This error is likely caused by a bug in React. Please file an issue.');
11159 }
11160 }
11161
11162 function unwindContexts(from, to) {
11163 var node = from;
11164 while (node !== null) {
11165 switch (node.tag) {
11166 case ClassComponent:
11167 popContextProvider(node);
11168 break;
11169 case HostComponent:
11170 popHostContext(node);
11171 break;
11172 case HostRoot:
11173 popHostContainer(node);
11174 break;
11175 case HostPortal:
11176 popHostContainer(node);
11177 break;
11178 }
11179 if (node === to || node.alternate === to) {
11180 stopFailedWorkTimer(node);
11181 break;
11182 } else {
11183 stopWorkTimer(node);
11184 }
11185 node = node['return'];
11186 }
11187 }
11188
11189 function computeAsyncExpiration() {
11190 // Given the current clock time, returns an expiration time. We use rounding
11191 // to batch like updates together.
11192 // Should complete within ~1000ms. 1200ms max.
11193 var currentTime = recalculateCurrentTime();
11194 var expirationMs = 1000;
11195 var bucketSizeMs = 200;
11196 return computeExpirationBucket(currentTime, expirationMs, bucketSizeMs);
11197 }
11198
11199 // Creates a unique async expiration time.
11200 function computeUniqueAsyncExpiration() {
11201 var result = computeAsyncExpiration();
11202 if (result <= lastUniqueAsyncExpiration) {
11203 // Since we assume the current time monotonically increases, we only hit
11204 // this branch when computeUniqueAsyncExpiration is fired multiple times
11205 // within a 200ms window (or whatever the async bucket size is).
11206 result = lastUniqueAsyncExpiration + 1;
11207 }
11208 lastUniqueAsyncExpiration = result;
11209 return lastUniqueAsyncExpiration;
11210 }
11211
11212 function computeExpirationForFiber(fiber) {
11213 var expirationTime = void 0;
11214 if (expirationContext !== NoWork) {
11215 // An explicit expiration context was set;
11216 expirationTime = expirationContext;
11217 } else if (isWorking) {
11218 if (isCommitting) {
11219 // Updates that occur during the commit phase should have sync priority
11220 // by default.
11221 expirationTime = Sync;
11222 } else {
11223 // Updates during the render phase should expire at the same time as
11224 // the work that is being rendered.
11225 expirationTime = nextRenderExpirationTime;
11226 }
11227 } else {
11228 // No explicit expiration context was set, and we're not currently
11229 // performing work. Calculate a new expiration time.
11230 if (fiber.internalContextTag & AsyncUpdates) {
11231 // This is an async update
11232 expirationTime = computeAsyncExpiration();
11233 } else {
11234 // This is a sync update
11235 expirationTime = Sync;
11236 }
11237 }
11238 return expirationTime;
11239 }
11240
11241 function scheduleWork(fiber, expirationTime) {
11242 return scheduleWorkImpl(fiber, expirationTime, false);
11243 }
11244
11245 function checkRootNeedsClearing(root, fiber, expirationTime) {
11246 if (!isWorking && root === nextRoot && expirationTime < nextRenderExpirationTime) {
11247 // Restart the root from the top.
11248 if (nextUnitOfWork !== null) {
11249 // This is an interruption. (Used for performance tracking.)
11250 interruptedBy = fiber;
11251 }
11252 nextRoot = null;
11253 nextUnitOfWork = null;
11254 nextRenderExpirationTime = NoWork;
11255 }
11256 }
11257
11258 function scheduleWorkImpl(fiber, expirationTime, isErrorRecovery) {
11259 recordScheduleUpdate();
11260
11261 {
11262 if (!isErrorRecovery && fiber.tag === ClassComponent) {
11263 var instance = fiber.stateNode;
11264 warnAboutInvalidUpdates(instance);
11265 }
11266 }
11267
11268 var node = fiber;
11269 while (node !== null) {
11270 // Walk the parent path to the root and update each node's
11271 // expiration time.
11272 if (node.expirationTime === NoWork || node.expirationTime > expirationTime) {
11273 node.expirationTime = expirationTime;
11274 }
11275 if (node.alternate !== null) {
11276 if (node.alternate.expirationTime === NoWork || node.alternate.expirationTime > expirationTime) {
11277 node.alternate.expirationTime = expirationTime;
11278 }
11279 }
11280 if (node['return'] === null) {
11281 if (node.tag === HostRoot) {
11282 var root = node.stateNode;
11283
11284 checkRootNeedsClearing(root, fiber, expirationTime);
11285 requestWork(root, expirationTime);
11286 checkRootNeedsClearing(root, fiber, expirationTime);
11287 } else {
11288 {
11289 if (!isErrorRecovery && fiber.tag === ClassComponent) {
11290 warnAboutUpdateOnUnmounted(fiber);
11291 }
11292 }
11293 return;
11294 }
11295 }
11296 node = node['return'];
11297 }
11298 }
11299
11300 function scheduleErrorRecovery(fiber) {
11301 scheduleWorkImpl(fiber, Sync, true);
11302 }
11303
11304 function recalculateCurrentTime() {
11305 // Subtract initial time so it fits inside 32bits
11306 var ms = now() - startTime;
11307 mostRecentCurrentTime = msToExpirationTime(ms);
11308 return mostRecentCurrentTime;
11309 }
11310
11311 function deferredUpdates(fn) {
11312 var previousExpirationContext = expirationContext;
11313 expirationContext = computeAsyncExpiration();
11314 try {
11315 return fn();
11316 } finally {
11317 expirationContext = previousExpirationContext;
11318 }
11319 }
11320
11321 function syncUpdates(fn) {
11322 var previousExpirationContext = expirationContext;
11323 expirationContext = Sync;
11324 try {
11325 return fn();
11326 } finally {
11327 expirationContext = previousExpirationContext;
11328 }
11329 }
11330
11331 // TODO: Everything below this is written as if it has been lifted to the
11332 // renderers. I'll do this in a follow-up.
11333
11334 // Linked-list of roots
11335 var firstScheduledRoot = null;
11336 var lastScheduledRoot = null;
11337
11338 var callbackExpirationTime = NoWork;
11339 var callbackID = -1;
11340 var isRendering = false;
11341 var nextFlushedRoot = null;
11342 var nextFlushedExpirationTime = NoWork;
11343 var deadlineDidExpire = false;
11344 var hasUnhandledError = false;
11345 var unhandledError = null;
11346 var deadline = null;
11347
11348 var isBatchingUpdates = false;
11349 var isUnbatchingUpdates = false;
11350
11351 var completedBatches = null;
11352
11353 // Use these to prevent an infinite loop of nested updates
11354 var NESTED_UPDATE_LIMIT = 1000;
11355 var nestedUpdateCount = 0;
11356
11357 var timeHeuristicForUnitOfWork = 1;
11358
11359 function scheduleCallbackWithExpiration(expirationTime) {
11360 if (callbackExpirationTime !== NoWork) {
11361 // A callback is already scheduled. Check its expiration time (timeout).
11362 if (expirationTime > callbackExpirationTime) {
11363 // Existing callback has sufficient timeout. Exit.
11364 return;
11365 } else {
11366 // Existing callback has insufficient timeout. Cancel and schedule a
11367 // new one.
11368 cancelDeferredCallback(callbackID);
11369 }
11370 // The request callback timer is already running. Don't start a new one.
11371 } else {
11372 startRequestCallbackTimer();
11373 }
11374
11375 // Compute a timeout for the given expiration time.
11376 var currentMs = now() - startTime;
11377 var expirationMs = expirationTimeToMs(expirationTime);
11378 var timeout = expirationMs - currentMs;
11379
11380 callbackExpirationTime = expirationTime;
11381 callbackID = scheduleDeferredCallback(performAsyncWork, { timeout: timeout });
11382 }
11383
11384 // requestWork is called by the scheduler whenever a root receives an update.
11385 // It's up to the renderer to call renderRoot at some point in the future.
11386 function requestWork(root, expirationTime) {
11387 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) {
11388 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.');
11389 }
11390
11391 // Add the root to the schedule.
11392 // Check if this root is already part of the schedule.
11393 if (root.nextScheduledRoot === null) {
11394 // This root is not already scheduled. Add it.
11395 root.remainingExpirationTime = expirationTime;
11396 if (lastScheduledRoot === null) {
11397 firstScheduledRoot = lastScheduledRoot = root;
11398 root.nextScheduledRoot = root;
11399 } else {
11400 lastScheduledRoot.nextScheduledRoot = root;
11401 lastScheduledRoot = root;
11402 lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
11403 }
11404 } else {
11405 // This root is already scheduled, but its priority may have increased.
11406 var remainingExpirationTime = root.remainingExpirationTime;
11407 if (remainingExpirationTime === NoWork || expirationTime < remainingExpirationTime) {
11408 // Update the priority.
11409 root.remainingExpirationTime = expirationTime;
11410 }
11411 }
11412
11413 if (isRendering) {
11414 // Prevent reentrancy. Remaining work will be scheduled at the end of
11415 // the currently rendering batch.
11416 return;
11417 }
11418
11419 if (isBatchingUpdates) {
11420 // Flush work at the end of the batch.
11421 if (isUnbatchingUpdates) {
11422 // ...unless we're inside unbatchedUpdates, in which case we should
11423 // flush it now.
11424 nextFlushedRoot = root;
11425 nextFlushedExpirationTime = Sync;
11426 performWorkOnRoot(root, Sync, recalculateCurrentTime());
11427 }
11428 return;
11429 }
11430
11431 // TODO: Get rid of Sync and use current time?
11432 if (expirationTime === Sync) {
11433 performWork(Sync, null);
11434 } else {
11435 scheduleCallbackWithExpiration(expirationTime);
11436 }
11437 }
11438
11439 function findHighestPriorityRoot() {
11440 var highestPriorityWork = NoWork;
11441 var highestPriorityRoot = null;
11442
11443 if (lastScheduledRoot !== null) {
11444 var previousScheduledRoot = lastScheduledRoot;
11445 var root = firstScheduledRoot;
11446 while (root !== null) {
11447 var remainingExpirationTime = root.remainingExpirationTime;
11448 if (remainingExpirationTime === NoWork) {
11449 // This root no longer has work. Remove it from the scheduler.
11450
11451 // TODO: This check is redudant, but Flow is confused by the branch
11452 // below where we set lastScheduledRoot to null, even though we break
11453 // from the loop right after.
11454 !(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;
11455 if (root === root.nextScheduledRoot) {
11456 // This is the only root in the list.
11457 root.nextScheduledRoot = null;
11458 firstScheduledRoot = lastScheduledRoot = null;
11459 break;
11460 } else if (root === firstScheduledRoot) {
11461 // This is the first root in the list.
11462 var next = root.nextScheduledRoot;
11463 firstScheduledRoot = next;
11464 lastScheduledRoot.nextScheduledRoot = next;
11465 root.nextScheduledRoot = null;
11466 } else if (root === lastScheduledRoot) {
11467 // This is the last root in the list.
11468 lastScheduledRoot = previousScheduledRoot;
11469 lastScheduledRoot.nextScheduledRoot = firstScheduledRoot;
11470 root.nextScheduledRoot = null;
11471 break;
11472 } else {
11473 previousScheduledRoot.nextScheduledRoot = root.nextScheduledRoot;
11474 root.nextScheduledRoot = null;
11475 }
11476 root = previousScheduledRoot.nextScheduledRoot;
11477 } else {
11478 if (highestPriorityWork === NoWork || remainingExpirationTime < highestPriorityWork) {
11479 // Update the priority, if it's higher
11480 highestPriorityWork = remainingExpirationTime;
11481 highestPriorityRoot = root;
11482 }
11483 if (root === lastScheduledRoot) {
11484 break;
11485 }
11486 previousScheduledRoot = root;
11487 root = root.nextScheduledRoot;
11488 }
11489 }
11490 }
11491
11492 // If the next root is the same as the previous root, this is a nested
11493 // update. To prevent an infinite loop, increment the nested update count.
11494 var previousFlushedRoot = nextFlushedRoot;
11495 if (previousFlushedRoot !== null && previousFlushedRoot === highestPriorityRoot) {
11496 nestedUpdateCount++;
11497 } else {
11498 // Reset whenever we switch roots.
11499 nestedUpdateCount = 0;
11500 }
11501 nextFlushedRoot = highestPriorityRoot;
11502 nextFlushedExpirationTime = highestPriorityWork;
11503 }
11504
11505 function performAsyncWork(dl) {
11506 performWork(NoWork, dl);
11507 }
11508
11509 function performWork(minExpirationTime, dl) {
11510 deadline = dl;
11511
11512 // Keep working on roots until there's no more work, or until the we reach
11513 // the deadline.
11514 findHighestPriorityRoot();
11515
11516 if (enableUserTimingAPI && deadline !== null) {
11517 var didExpire = nextFlushedExpirationTime < recalculateCurrentTime();
11518 stopRequestCallbackTimer(didExpire);
11519 }
11520
11521 while (nextFlushedRoot !== null && nextFlushedExpirationTime !== NoWork && (minExpirationTime === NoWork || nextFlushedExpirationTime <= minExpirationTime) && !deadlineDidExpire) {
11522 performWorkOnRoot(nextFlushedRoot, nextFlushedExpirationTime, recalculateCurrentTime());
11523 // Find the next highest priority work.
11524 findHighestPriorityRoot();
11525 }
11526
11527 // We're done flushing work. Either we ran out of time in this callback,
11528 // or there's no more work left with sufficient priority.
11529
11530 // If we're inside a callback, set this to false since we just completed it.
11531 if (deadline !== null) {
11532 callbackExpirationTime = NoWork;
11533 callbackID = -1;
11534 }
11535 // If there's work left over, schedule a new callback.
11536 if (nextFlushedExpirationTime !== NoWork) {
11537 scheduleCallbackWithExpiration(nextFlushedExpirationTime);
11538 }
11539
11540 // Clean-up.
11541 deadline = null;
11542 deadlineDidExpire = false;
11543 nestedUpdateCount = 0;
11544
11545 finishRendering();
11546 }
11547
11548 function flushRoot(root, expirationTime) {
11549 !!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;
11550 // Perform work on root as if the given expiration time is the current time.
11551 // This has the effect of synchronously flushing all work up to and
11552 // including the given time.
11553 performWorkOnRoot(root, expirationTime, expirationTime);
11554 finishRendering();
11555 }
11556
11557 function finishRendering() {
11558 if (completedBatches !== null) {
11559 var batches = completedBatches;
11560 completedBatches = null;
11561 for (var i = 0; i < batches.length; i++) {
11562 var batch = batches[i];
11563 try {
11564 batch._onComplete();
11565 } catch (error) {
11566 if (!hasUnhandledError) {
11567 hasUnhandledError = true;
11568 unhandledError = error;
11569 }
11570 }
11571 }
11572 }
11573
11574 if (hasUnhandledError) {
11575 var _error4 = unhandledError;
11576 unhandledError = null;
11577 hasUnhandledError = false;
11578 throw _error4;
11579 }
11580 }
11581
11582 function performWorkOnRoot(root, expirationTime, currentTime) {
11583 !!isRendering ? invariant_1(false, 'performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.') : void 0;
11584
11585 isRendering = true;
11586
11587 // Check if this is async work or sync/expired work.
11588 if (expirationTime <= currentTime) {
11589 // Flush sync work.
11590 var finishedWork = root.finishedWork;
11591 if (finishedWork !== null) {
11592 // This root is already complete. We can commit it.
11593 completeRoot(root, finishedWork, expirationTime);
11594 } else {
11595 root.finishedWork = null;
11596 finishedWork = renderRoot(root, expirationTime);
11597 if (finishedWork !== null) {
11598 // We've completed the root. Commit it.
11599 completeRoot(root, finishedWork, expirationTime);
11600 }
11601 }
11602 } else {
11603 // Flush async work.
11604 var _finishedWork = root.finishedWork;
11605 if (_finishedWork !== null) {
11606 // This root is already complete. We can commit it.
11607 completeRoot(root, _finishedWork, expirationTime);
11608 } else {
11609 root.finishedWork = null;
11610 _finishedWork = renderRoot(root, expirationTime);
11611 if (_finishedWork !== null) {
11612 // We've completed the root. Check the deadline one more time
11613 // before committing.
11614 if (!shouldYield()) {
11615 // Still time left. Commit the root.
11616 completeRoot(root, _finishedWork, expirationTime);
11617 } else {
11618 // There's no time left. Mark this root as complete. We'll come
11619 // back and commit it later.
11620 root.finishedWork = _finishedWork;
11621 }
11622 }
11623 }
11624 }
11625
11626 isRendering = false;
11627 }
11628
11629 function completeRoot(root, finishedWork, expirationTime) {
11630 // Check if there's a batch that matches this expiration time.
11631 var firstBatch = root.firstBatch;
11632 if (firstBatch !== null && firstBatch._expirationTime <= expirationTime) {
11633 if (completedBatches === null) {
11634 completedBatches = [firstBatch];
11635 } else {
11636 completedBatches.push(firstBatch);
11637 }
11638 if (firstBatch._defer) {
11639 // This root is blocked from committing by a batch. Unschedule it until
11640 // we receive another update.
11641 root.finishedWork = finishedWork;
11642 root.remainingExpirationTime = NoWork;
11643 return;
11644 }
11645 }
11646
11647 // Commit the root.
11648 root.finishedWork = null;
11649 root.remainingExpirationTime = commitRoot(finishedWork);
11650 }
11651
11652 // When working on async work, the reconciler asks the renderer if it should
11653 // yield execution. For DOM, we implement this with requestIdleCallback.
11654 function shouldYield() {
11655 if (deadline === null) {
11656 return false;
11657 }
11658 if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
11659 // Disregard deadline.didTimeout. Only expired work should be flushed
11660 // during a timeout. This path is only hit for non-expired work.
11661 return false;
11662 }
11663 deadlineDidExpire = true;
11664 return true;
11665 }
11666
11667 // TODO: Not happy about this hook. Conceptually, renderRoot should return a
11668 // tuple of (isReadyForCommit, didError, error)
11669 function onUncaughtError(error) {
11670 !(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;
11671 // Unschedule this root so we don't work on it again until there's
11672 // another update.
11673 nextFlushedRoot.remainingExpirationTime = NoWork;
11674 if (!hasUnhandledError) {
11675 hasUnhandledError = true;
11676 unhandledError = error;
11677 }
11678 }
11679
11680 // TODO: Batching should be implemented at the renderer level, not inside
11681 // the reconciler.
11682 function batchedUpdates(fn, a) {
11683 var previousIsBatchingUpdates = isBatchingUpdates;
11684 isBatchingUpdates = true;
11685 try {
11686 return fn(a);
11687 } finally {
11688 isBatchingUpdates = previousIsBatchingUpdates;
11689 if (!isBatchingUpdates && !isRendering) {
11690 performWork(Sync, null);
11691 }
11692 }
11693 }
11694
11695 // TODO: Batching should be implemented at the renderer level, not inside
11696 // the reconciler.
11697 function unbatchedUpdates(fn) {
11698 if (isBatchingUpdates && !isUnbatchingUpdates) {
11699 isUnbatchingUpdates = true;
11700 try {
11701 return fn();
11702 } finally {
11703 isUnbatchingUpdates = false;
11704 }
11705 }
11706 return fn();
11707 }
11708
11709 // TODO: Batching should be implemented at the renderer level, not within
11710 // the reconciler.
11711 function flushSync(fn) {
11712 var previousIsBatchingUpdates = isBatchingUpdates;
11713 isBatchingUpdates = true;
11714 try {
11715 return syncUpdates(fn);
11716 } finally {
11717 isBatchingUpdates = previousIsBatchingUpdates;
11718 !!isRendering ? invariant_1(false, 'flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.') : void 0;
11719 performWork(Sync, null);
11720 }
11721 }
11722
11723 return {
11724 computeExpirationForFiber: computeExpirationForFiber,
11725 scheduleWork: scheduleWork,
11726 requestWork: requestWork,
11727 flushRoot: flushRoot,
11728 batchedUpdates: batchedUpdates,
11729 unbatchedUpdates: unbatchedUpdates,
11730 flushSync: flushSync,
11731 deferredUpdates: deferredUpdates,
11732 computeUniqueAsyncExpiration: computeUniqueAsyncExpiration
11733 };
11734};
11735
11736var didWarnAboutNestedUpdates = void 0;
11737
11738{
11739 didWarnAboutNestedUpdates = false;
11740}
11741
11742// 0 is PROD, 1 is DEV.
11743// Might add PROFILE later.
11744
11745
11746function getContextForSubtree(parentComponent) {
11747 if (!parentComponent) {
11748 return emptyObject_1;
11749 }
11750
11751 var fiber = get(parentComponent);
11752 var parentContext = findCurrentUnmaskedContext(fiber);
11753 return isContextProvider(fiber) ? processChildContext(fiber, parentContext) : parentContext;
11754}
11755
11756var ReactFiberReconciler$1 = function (config) {
11757 var getPublicInstance = config.getPublicInstance;
11758
11759 var _ReactFiberScheduler = ReactFiberScheduler(config),
11760 computeUniqueAsyncExpiration = _ReactFiberScheduler.computeUniqueAsyncExpiration,
11761 computeExpirationForFiber = _ReactFiberScheduler.computeExpirationForFiber,
11762 scheduleWork = _ReactFiberScheduler.scheduleWork,
11763 requestWork = _ReactFiberScheduler.requestWork,
11764 flushRoot = _ReactFiberScheduler.flushRoot,
11765 batchedUpdates = _ReactFiberScheduler.batchedUpdates,
11766 unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates,
11767 flushSync = _ReactFiberScheduler.flushSync,
11768 deferredUpdates = _ReactFiberScheduler.deferredUpdates;
11769
11770 function scheduleRootUpdate(current, element, expirationTime, callback) {
11771 {
11772 if (ReactDebugCurrentFiber.phase === 'render' && ReactDebugCurrentFiber.current !== null && !didWarnAboutNestedUpdates) {
11773 didWarnAboutNestedUpdates = true;
11774 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');
11775 }
11776 }
11777
11778 callback = callback === undefined ? null : callback;
11779 {
11780 warning_1(callback === null || typeof callback === 'function', 'render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback);
11781 }
11782
11783 var update = {
11784 expirationTime: expirationTime,
11785 partialState: { element: element },
11786 callback: callback,
11787 isReplace: false,
11788 isForced: false,
11789 next: null
11790 };
11791 insertUpdateIntoFiber(current, update);
11792 scheduleWork(current, expirationTime);
11793
11794 return expirationTime;
11795 }
11796
11797 function updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback) {
11798 // TODO: If this is a nested container, this won't be the root.
11799 var current = container.current;
11800
11801 {
11802 if (ReactFiberInstrumentation_1.debugTool) {
11803 if (current.alternate === null) {
11804 ReactFiberInstrumentation_1.debugTool.onMountContainer(container);
11805 } else if (element === null) {
11806 ReactFiberInstrumentation_1.debugTool.onUnmountContainer(container);
11807 } else {
11808 ReactFiberInstrumentation_1.debugTool.onUpdateContainer(container);
11809 }
11810 }
11811 }
11812
11813 var context = getContextForSubtree(parentComponent);
11814 if (container.context === null) {
11815 container.context = context;
11816 } else {
11817 container.pendingContext = context;
11818 }
11819
11820 return scheduleRootUpdate(current, element, expirationTime, callback);
11821 }
11822
11823 function findHostInstance(fiber) {
11824 var hostFiber = findCurrentHostFiber(fiber);
11825 if (hostFiber === null) {
11826 return null;
11827 }
11828 return hostFiber.stateNode;
11829 }
11830
11831 return {
11832 createContainer: function (containerInfo, isAsync, hydrate) {
11833 return createFiberRoot(containerInfo, isAsync, hydrate);
11834 },
11835 updateContainer: function (element, container, parentComponent, callback) {
11836 var current = container.current;
11837 var expirationTime = computeExpirationForFiber(current);
11838 return updateContainerAtExpirationTime(element, container, parentComponent, expirationTime, callback);
11839 },
11840
11841
11842 updateContainerAtExpirationTime: updateContainerAtExpirationTime,
11843
11844 flushRoot: flushRoot,
11845
11846 requestWork: requestWork,
11847
11848 computeUniqueAsyncExpiration: computeUniqueAsyncExpiration,
11849
11850 batchedUpdates: batchedUpdates,
11851
11852 unbatchedUpdates: unbatchedUpdates,
11853
11854 deferredUpdates: deferredUpdates,
11855
11856 flushSync: flushSync,
11857
11858 getPublicRootInstance: function (container) {
11859 var containerFiber = container.current;
11860 if (!containerFiber.child) {
11861 return null;
11862 }
11863 switch (containerFiber.child.tag) {
11864 case HostComponent:
11865 return getPublicInstance(containerFiber.child.stateNode);
11866 default:
11867 return containerFiber.child.stateNode;
11868 }
11869 },
11870
11871
11872 findHostInstance: findHostInstance,
11873
11874 findHostInstanceWithNoPortals: function (fiber) {
11875 var hostFiber = findCurrentHostFiberWithNoPortals(fiber);
11876 if (hostFiber === null) {
11877 return null;
11878 }
11879 return hostFiber.stateNode;
11880 },
11881 injectIntoDevTools: function (devToolsConfig) {
11882 var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance;
11883
11884 return injectInternals(_assign({}, devToolsConfig, {
11885 findHostInstanceByFiber: function (fiber) {
11886 return findHostInstance(fiber);
11887 },
11888 findFiberByHostInstance: function (instance) {
11889 if (!findFiberByHostInstance) {
11890 // Might not be implemented by the renderer.
11891 return null;
11892 }
11893 return findFiberByHostInstance(instance);
11894 }
11895 }));
11896 }
11897 };
11898};
11899
11900var ReactFiberReconciler$2 = Object.freeze({
11901 default: ReactFiberReconciler$1
11902});
11903
11904var ReactFiberReconciler$3 = ( ReactFiberReconciler$2 && ReactFiberReconciler$1 ) || ReactFiberReconciler$2;
11905
11906// TODO: bundle Flow types with the package.
11907
11908
11909
11910// TODO: decide on the top-level export form.
11911// This is hacky but makes it work with both Rollup and Jest.
11912var reactReconciler = ReactFiberReconciler$3['default'] ? ReactFiberReconciler$3['default'] : ReactFiberReconciler$3;
11913
11914function createPortal$1(children, containerInfo,
11915// TODO: figure out the API for cross-renderer implementation.
11916implementation) {
11917 var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
11918
11919 return {
11920 // This tag allow us to uniquely identify this as a React Portal
11921 $$typeof: REACT_PORTAL_TYPE,
11922 key: key == null ? null : '' + key,
11923 children: children,
11924 containerInfo: containerInfo,
11925 implementation: implementation
11926 };
11927}
11928
11929// TODO: this is special because it gets imported during build.
11930
11931var ReactVersion = '16.2.0';
11932
11933// a requestAnimationFrame, storing the time for the start of the frame, then
11934// scheduling a postMessage which gets scheduled after paint. Within the
11935// postMessage handler do as much work as possible until time + frame rate.
11936// By separating the idle call into a separate event tick we ensure that
11937// layout, paint and other browser work is counted against the available time.
11938// The frame rate is dynamically adjusted.
11939
11940{
11941 if (ExecutionEnvironment_1.canUseDOM && typeof requestAnimationFrame !== 'function') {
11942 warning_1(false, 'React depends on requestAnimationFrame. Make sure that you load a ' + 'polyfill in older browsers. https://fb.me/react-polyfills');
11943 }
11944}
11945
11946var hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function';
11947
11948var now = void 0;
11949if (hasNativePerformanceNow) {
11950 now = function () {
11951 return performance.now();
11952 };
11953} else {
11954 now = function () {
11955 return Date.now();
11956 };
11957}
11958
11959// TODO: There's no way to cancel, because Fiber doesn't atm.
11960var rIC = void 0;
11961var cIC = void 0;
11962
11963if (!ExecutionEnvironment_1.canUseDOM) {
11964 rIC = function (frameCallback) {
11965 return setTimeout(function () {
11966 frameCallback({
11967 timeRemaining: function () {
11968 return Infinity;
11969 }
11970 });
11971 });
11972 };
11973 cIC = function (timeoutID) {
11974 clearTimeout(timeoutID);
11975 };
11976} else if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') {
11977 // Polyfill requestIdleCallback and cancelIdleCallback
11978
11979 var scheduledRICCallback = null;
11980 var isIdleScheduled = false;
11981 var timeoutTime = -1;
11982
11983 var isAnimationFrameScheduled = false;
11984
11985 var frameDeadline = 0;
11986 // We start out assuming that we run at 30fps but then the heuristic tracking
11987 // will adjust this value to a faster fps if we get more frequent animation
11988 // frames.
11989 var previousFrameTime = 33;
11990 var activeFrameTime = 33;
11991
11992 var frameDeadlineObject = void 0;
11993 if (hasNativePerformanceNow) {
11994 frameDeadlineObject = {
11995 didTimeout: false,
11996 timeRemaining: function () {
11997 // We assume that if we have a performance timer that the rAF callback
11998 // gets a performance timer value. Not sure if this is always true.
11999 var remaining = frameDeadline - performance.now();
12000 return remaining > 0 ? remaining : 0;
12001 }
12002 };
12003 } else {
12004 frameDeadlineObject = {
12005 didTimeout: false,
12006 timeRemaining: function () {
12007 // Fallback to Date.now()
12008 var remaining = frameDeadline - Date.now();
12009 return remaining > 0 ? remaining : 0;
12010 }
12011 };
12012 }
12013
12014 // We use the postMessage trick to defer idle work until after the repaint.
12015 var messageKey = '__reactIdleCallback$' + Math.random().toString(36).slice(2);
12016 var idleTick = function (event) {
12017 if (event.source !== window || event.data !== messageKey) {
12018 return;
12019 }
12020
12021 isIdleScheduled = false;
12022
12023 var currentTime = now();
12024 if (frameDeadline - currentTime <= 0) {
12025 // There's no time left in this idle period. Check if the callback has
12026 // a timeout and whether it's been exceeded.
12027 if (timeoutTime !== -1 && timeoutTime <= currentTime) {
12028 // Exceeded the timeout. Invoke the callback even though there's no
12029 // time left.
12030 frameDeadlineObject.didTimeout = true;
12031 } else {
12032 // No timeout.
12033 if (!isAnimationFrameScheduled) {
12034 // Schedule another animation callback so we retry later.
12035 isAnimationFrameScheduled = true;
12036 requestAnimationFrame(animationTick);
12037 }
12038 // Exit without invoking the callback.
12039 return;
12040 }
12041 } else {
12042 // There's still time left in this idle period.
12043 frameDeadlineObject.didTimeout = false;
12044 }
12045
12046 timeoutTime = -1;
12047 var callback = scheduledRICCallback;
12048 scheduledRICCallback = null;
12049 if (callback !== null) {
12050 callback(frameDeadlineObject);
12051 }
12052 };
12053 // Assumes that we have addEventListener in this environment. Might need
12054 // something better for old IE.
12055 window.addEventListener('message', idleTick, false);
12056
12057 var animationTick = function (rafTime) {
12058 isAnimationFrameScheduled = false;
12059 var nextFrameTime = rafTime - frameDeadline + activeFrameTime;
12060 if (nextFrameTime < activeFrameTime && previousFrameTime < activeFrameTime) {
12061 if (nextFrameTime < 8) {
12062 // Defensive coding. We don't support higher frame rates than 120hz.
12063 // If we get lower than that, it is probably a bug.
12064 nextFrameTime = 8;
12065 }
12066 // If one frame goes long, then the next one can be short to catch up.
12067 // If two frames are short in a row, then that's an indication that we
12068 // actually have a higher frame rate than what we're currently optimizing.
12069 // We adjust our heuristic dynamically accordingly. For example, if we're
12070 // running on 120hz display or 90hz VR display.
12071 // Take the max of the two in case one of them was an anomaly due to
12072 // missed frame deadlines.
12073 activeFrameTime = nextFrameTime < previousFrameTime ? previousFrameTime : nextFrameTime;
12074 } else {
12075 previousFrameTime = nextFrameTime;
12076 }
12077 frameDeadline = rafTime + activeFrameTime;
12078 if (!isIdleScheduled) {
12079 isIdleScheduled = true;
12080 window.postMessage(messageKey, '*');
12081 }
12082 };
12083
12084 rIC = function (callback, options) {
12085 // This assumes that we only schedule one callback at a time because that's
12086 // how Fiber uses it.
12087 scheduledRICCallback = callback;
12088 if (options != null && typeof options.timeout === 'number') {
12089 timeoutTime = now() + options.timeout;
12090 }
12091 if (!isAnimationFrameScheduled) {
12092 // If rAF didn't already schedule one, we need to schedule a frame.
12093 // TODO: If this rAF doesn't materialize because the browser throttles, we
12094 // might want to still have setTimeout trigger rIC as a backup to ensure
12095 // that we keep performing work.
12096 isAnimationFrameScheduled = true;
12097 requestAnimationFrame(animationTick);
12098 }
12099 return 0;
12100 };
12101
12102 cIC = function () {
12103 scheduledRICCallback = null;
12104 isIdleScheduled = false;
12105 timeoutTime = -1;
12106 };
12107} else {
12108 rIC = window.requestIdleCallback;
12109 cIC = window.cancelIdleCallback;
12110}
12111
12112var didWarnSelectedSetOnOption = false;
12113
12114function flattenChildren(children) {
12115 var content = '';
12116
12117 // Flatten children and warn if they aren't strings or numbers;
12118 // invalid types are ignored.
12119 // We can silently skip them because invalid DOM nesting warning
12120 // catches these cases in Fiber.
12121 React.Children.forEach(children, function (child) {
12122 if (child == null) {
12123 return;
12124 }
12125 if (typeof child === 'string' || typeof child === 'number') {
12126 content += child;
12127 }
12128 });
12129
12130 return content;
12131}
12132
12133/**
12134 * Implements an <option> host component that warns when `selected` is set.
12135 */
12136
12137function validateProps(element, props) {
12138 // TODO (yungsters): Remove support for `selected` in <option>.
12139 {
12140 if (props.selected != null && !didWarnSelectedSetOnOption) {
12141 warning_1(false, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.');
12142 didWarnSelectedSetOnOption = true;
12143 }
12144 }
12145}
12146
12147function postMountWrapper$1(element, props) {
12148 // value="" should make a value attribute (#6219)
12149 if (props.value != null) {
12150 element.setAttribute('value', props.value);
12151 }
12152}
12153
12154function getHostProps$1(element, props) {
12155 var hostProps = _assign({ children: undefined }, props);
12156 var content = flattenChildren(props.children);
12157
12158 if (content) {
12159 hostProps.children = content;
12160 }
12161
12162 return hostProps;
12163}
12164
12165// TODO: direct imports like some-package/src/* are bad. Fix me.
12166var getCurrentFiberOwnerName$3 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
12167var getCurrentFiberStackAddendum$4 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
12168
12169
12170var didWarnValueDefaultValue$1 = void 0;
12171
12172{
12173 didWarnValueDefaultValue$1 = false;
12174}
12175
12176function getDeclarationErrorAddendum() {
12177 var ownerName = getCurrentFiberOwnerName$3();
12178 if (ownerName) {
12179 return '\n\nCheck the render method of `' + ownerName + '`.';
12180 }
12181 return '';
12182}
12183
12184var valuePropNames = ['value', 'defaultValue'];
12185
12186/**
12187 * Validation function for `value` and `defaultValue`.
12188 */
12189function checkSelectPropTypes(props) {
12190 ReactControlledValuePropTypes.checkPropTypes('select', props, getCurrentFiberStackAddendum$4);
12191
12192 for (var i = 0; i < valuePropNames.length; i++) {
12193 var propName = valuePropNames[i];
12194 if (props[propName] == null) {
12195 continue;
12196 }
12197 var isArray = Array.isArray(props[propName]);
12198 if (props.multiple && !isArray) {
12199 warning_1(false, 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum());
12200 } else if (!props.multiple && isArray) {
12201 warning_1(false, 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum());
12202 }
12203 }
12204}
12205
12206function updateOptions(node, multiple, propValue, setDefaultSelected) {
12207 var options = node.options;
12208
12209 if (multiple) {
12210 var selectedValues = propValue;
12211 var selectedValue = {};
12212 for (var i = 0; i < selectedValues.length; i++) {
12213 // Prefix to avoid chaos with special keys.
12214 selectedValue['$' + selectedValues[i]] = true;
12215 }
12216 for (var _i = 0; _i < options.length; _i++) {
12217 var selected = selectedValue.hasOwnProperty('$' + options[_i].value);
12218 if (options[_i].selected !== selected) {
12219 options[_i].selected = selected;
12220 }
12221 if (selected && setDefaultSelected) {
12222 options[_i].defaultSelected = true;
12223 }
12224 }
12225 } else {
12226 // Do not set `select.value` as exact behavior isn't consistent across all
12227 // browsers for all cases.
12228 var _selectedValue = '' + propValue;
12229 var defaultSelected = null;
12230 for (var _i2 = 0; _i2 < options.length; _i2++) {
12231 if (options[_i2].value === _selectedValue) {
12232 options[_i2].selected = true;
12233 if (setDefaultSelected) {
12234 options[_i2].defaultSelected = true;
12235 }
12236 return;
12237 }
12238 if (defaultSelected === null && !options[_i2].disabled) {
12239 defaultSelected = options[_i2];
12240 }
12241 }
12242 if (defaultSelected !== null) {
12243 defaultSelected.selected = true;
12244 }
12245 }
12246}
12247
12248/**
12249 * Implements a <select> host component that allows optionally setting the
12250 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a
12251 * stringable. If `multiple` is true, the prop must be an array of stringables.
12252 *
12253 * If `value` is not supplied (or null/undefined), user actions that change the
12254 * selected option will trigger updates to the rendered options.
12255 *
12256 * If it is supplied (and not null/undefined), the rendered options will not
12257 * update in response to user actions. Instead, the `value` prop must change in
12258 * order for the rendered options to update.
12259 *
12260 * If `defaultValue` is provided, any options with the supplied values will be
12261 * selected.
12262 */
12263
12264function getHostProps$2(element, props) {
12265 return _assign({}, props, {
12266 value: undefined
12267 });
12268}
12269
12270function initWrapperState$1(element, props) {
12271 var node = element;
12272 {
12273 checkSelectPropTypes(props);
12274 }
12275
12276 var value = props.value;
12277 node._wrapperState = {
12278 initialValue: value != null ? value : props.defaultValue,
12279 wasMultiple: !!props.multiple
12280 };
12281
12282 {
12283 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) {
12284 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');
12285 didWarnValueDefaultValue$1 = true;
12286 }
12287 }
12288}
12289
12290function postMountWrapper$2(element, props) {
12291 var node = element;
12292 node.multiple = !!props.multiple;
12293 var value = props.value;
12294 if (value != null) {
12295 updateOptions(node, !!props.multiple, value, false);
12296 } else if (props.defaultValue != null) {
12297 updateOptions(node, !!props.multiple, props.defaultValue, true);
12298 }
12299}
12300
12301function postUpdateWrapper(element, props) {
12302 var node = element;
12303 // After the initial mount, we control selected-ness manually so don't pass
12304 // this value down
12305 node._wrapperState.initialValue = undefined;
12306
12307 var wasMultiple = node._wrapperState.wasMultiple;
12308 node._wrapperState.wasMultiple = !!props.multiple;
12309
12310 var value = props.value;
12311 if (value != null) {
12312 updateOptions(node, !!props.multiple, value, false);
12313 } else if (wasMultiple !== !!props.multiple) {
12314 // For simplicity, reapply `defaultValue` if `multiple` is toggled.
12315 if (props.defaultValue != null) {
12316 updateOptions(node, !!props.multiple, props.defaultValue, true);
12317 } else {
12318 // Revert the select back to its default unselected state.
12319 updateOptions(node, !!props.multiple, props.multiple ? [] : '', false);
12320 }
12321 }
12322}
12323
12324function restoreControlledState$2(element, props) {
12325 var node = element;
12326 var value = props.value;
12327
12328 if (value != null) {
12329 updateOptions(node, !!props.multiple, value, false);
12330 }
12331}
12332
12333// TODO: direct imports like some-package/src/* are bad. Fix me.
12334var getCurrentFiberStackAddendum$5 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
12335
12336var didWarnValDefaultVal = false;
12337
12338/**
12339 * Implements a <textarea> host component that allows setting `value`, and
12340 * `defaultValue`. This differs from the traditional DOM API because value is
12341 * usually set as PCDATA children.
12342 *
12343 * If `value` is not supplied (or null/undefined), user actions that affect the
12344 * value will trigger updates to the element.
12345 *
12346 * If `value` is supplied (and not null/undefined), the rendered element will
12347 * not trigger updates to the element. Instead, the `value` prop must change in
12348 * order for the rendered element to be updated.
12349 *
12350 * The rendered element will be initialized with an empty value, the prop
12351 * `defaultValue` if specified, or the children content (deprecated).
12352 */
12353
12354function getHostProps$3(element, props) {
12355 var node = element;
12356 !(props.dangerouslySetInnerHTML == null) ? invariant_1(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : void 0;
12357
12358 // Always set children to the same thing. In IE9, the selection range will
12359 // get reset if `textContent` is mutated. We could add a check in setTextContent
12360 // to only set the value if/when the value differs from the node value (which would
12361 // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this
12362 // solution. The value can be a boolean or object so that's why it's forced
12363 // to be a string.
12364 var hostProps = _assign({}, props, {
12365 value: undefined,
12366 defaultValue: undefined,
12367 children: '' + node._wrapperState.initialValue
12368 });
12369
12370 return hostProps;
12371}
12372
12373function initWrapperState$2(element, props) {
12374 var node = element;
12375 {
12376 ReactControlledValuePropTypes.checkPropTypes('textarea', props, getCurrentFiberStackAddendum$5);
12377 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {
12378 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');
12379 didWarnValDefaultVal = true;
12380 }
12381 }
12382
12383 var initialValue = props.value;
12384
12385 // Only bother fetching default value if we're going to use it
12386 if (initialValue == null) {
12387 var defaultValue = props.defaultValue;
12388 // TODO (yungsters): Remove support for children content in <textarea>.
12389 var children = props.children;
12390 if (children != null) {
12391 {
12392 warning_1(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.');
12393 }
12394 !(defaultValue == null) ? invariant_1(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : void 0;
12395 if (Array.isArray(children)) {
12396 !(children.length <= 1) ? invariant_1(false, '<textarea> can only have at most one child.') : void 0;
12397 children = children[0];
12398 }
12399
12400 defaultValue = '' + children;
12401 }
12402 if (defaultValue == null) {
12403 defaultValue = '';
12404 }
12405 initialValue = defaultValue;
12406 }
12407
12408 node._wrapperState = {
12409 initialValue: '' + initialValue
12410 };
12411}
12412
12413function updateWrapper$1(element, props) {
12414 var node = element;
12415 var value = props.value;
12416 if (value != null) {
12417 // Cast `value` to a string to ensure the value is set correctly. While
12418 // browsers typically do this as necessary, jsdom doesn't.
12419 var newValue = '' + value;
12420
12421 // To avoid side effects (such as losing text selection), only set value if changed
12422 if (newValue !== node.value) {
12423 node.value = newValue;
12424 }
12425 if (props.defaultValue == null) {
12426 node.defaultValue = newValue;
12427 }
12428 }
12429 if (props.defaultValue != null) {
12430 node.defaultValue = props.defaultValue;
12431 }
12432}
12433
12434function postMountWrapper$3(element, props) {
12435 var node = element;
12436 // This is in postMount because we need access to the DOM node, which is not
12437 // available until after the component has mounted.
12438 var textContent = node.textContent;
12439
12440 // Only set node.value if textContent is equal to the expected
12441 // initial value. In IE10/IE11 there is a bug where the placeholder attribute
12442 // will populate textContent as well.
12443 // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/
12444 if (textContent === node._wrapperState.initialValue) {
12445 node.value = textContent;
12446 }
12447}
12448
12449function restoreControlledState$3(element, props) {
12450 // DOM component is still mounted; update
12451 updateWrapper$1(element, props);
12452}
12453
12454var HTML_NAMESPACE$1 = 'http://www.w3.org/1999/xhtml';
12455var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
12456var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
12457
12458var Namespaces = {
12459 html: HTML_NAMESPACE$1,
12460 mathml: MATH_NAMESPACE,
12461 svg: SVG_NAMESPACE
12462};
12463
12464// Assumes there is no parent namespace.
12465function getIntrinsicNamespace(type) {
12466 switch (type) {
12467 case 'svg':
12468 return SVG_NAMESPACE;
12469 case 'math':
12470 return MATH_NAMESPACE;
12471 default:
12472 return HTML_NAMESPACE$1;
12473 }
12474}
12475
12476function getChildNamespace(parentNamespace, type) {
12477 if (parentNamespace == null || parentNamespace === HTML_NAMESPACE$1) {
12478 // No (or default) parent namespace: potential entry point.
12479 return getIntrinsicNamespace(type);
12480 }
12481 if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') {
12482 // We're leaving SVG.
12483 return HTML_NAMESPACE$1;
12484 }
12485 // By default, pass namespace below.
12486 return parentNamespace;
12487}
12488
12489/* globals MSApp */
12490
12491/**
12492 * Create a function which has 'unsafe' privileges (required by windows8 apps)
12493 */
12494var createMicrosoftUnsafeLocalFunction = function (func) {
12495 if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {
12496 return function (arg0, arg1, arg2, arg3) {
12497 MSApp.execUnsafeLocalFunction(function () {
12498 return func(arg0, arg1, arg2, arg3);
12499 });
12500 };
12501 } else {
12502 return func;
12503 }
12504};
12505
12506// SVG temp container for IE lacking innerHTML
12507var reusableSVGContainer = void 0;
12508
12509/**
12510 * Set the innerHTML property of a node
12511 *
12512 * @param {DOMElement} node
12513 * @param {string} html
12514 * @internal
12515 */
12516var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {
12517 // IE does not have innerHTML for SVG nodes, so instead we inject the
12518 // new markup in a temp node and then move the child nodes across into
12519 // the target node
12520
12521 if (node.namespaceURI === Namespaces.svg && !('innerHTML' in node)) {
12522 reusableSVGContainer = reusableSVGContainer || document.createElement('div');
12523 reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';
12524 var svgNode = reusableSVGContainer.firstChild;
12525 while (node.firstChild) {
12526 node.removeChild(node.firstChild);
12527 }
12528 while (svgNode.firstChild) {
12529 node.appendChild(svgNode.firstChild);
12530 }
12531 } else {
12532 node.innerHTML = html;
12533 }
12534});
12535
12536/**
12537 * Set the textContent property of a node. For text updates, it's faster
12538 * to set the `nodeValue` of the Text node directly instead of using
12539 * `.textContent` which will remove the existing node and create a new one.
12540 *
12541 * @param {DOMElement} node
12542 * @param {string} text
12543 * @internal
12544 */
12545var setTextContent = function (node, text) {
12546 if (text) {
12547 var firstChild = node.firstChild;
12548
12549 if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) {
12550 firstChild.nodeValue = text;
12551 return;
12552 }
12553 }
12554 node.textContent = text;
12555};
12556
12557/**
12558 * CSS properties which accept numbers but are not in units of "px".
12559 */
12560var isUnitlessNumber = {
12561 animationIterationCount: true,
12562 borderImageOutset: true,
12563 borderImageSlice: true,
12564 borderImageWidth: true,
12565 boxFlex: true,
12566 boxFlexGroup: true,
12567 boxOrdinalGroup: true,
12568 columnCount: true,
12569 columns: true,
12570 flex: true,
12571 flexGrow: true,
12572 flexPositive: true,
12573 flexShrink: true,
12574 flexNegative: true,
12575 flexOrder: true,
12576 gridRow: true,
12577 gridRowEnd: true,
12578 gridRowSpan: true,
12579 gridRowStart: true,
12580 gridColumn: true,
12581 gridColumnEnd: true,
12582 gridColumnSpan: true,
12583 gridColumnStart: true,
12584 fontWeight: true,
12585 lineClamp: true,
12586 lineHeight: true,
12587 opacity: true,
12588 order: true,
12589 orphans: true,
12590 tabSize: true,
12591 widows: true,
12592 zIndex: true,
12593 zoom: true,
12594
12595 // SVG-related properties
12596 fillOpacity: true,
12597 floodOpacity: true,
12598 stopOpacity: true,
12599 strokeDasharray: true,
12600 strokeDashoffset: true,
12601 strokeMiterlimit: true,
12602 strokeOpacity: true,
12603 strokeWidth: true
12604};
12605
12606/**
12607 * @param {string} prefix vendor-specific prefix, eg: Webkit
12608 * @param {string} key style name, eg: transitionDuration
12609 * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
12610 * WebkitTransitionDuration
12611 */
12612function prefixKey(prefix, key) {
12613 return prefix + key.charAt(0).toUpperCase() + key.substring(1);
12614}
12615
12616/**
12617 * Support style names that may come passed in prefixed by adding permutations
12618 * of vendor prefixes.
12619 */
12620var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
12621
12622// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
12623// infinite loop, because it iterates over the newly added props too.
12624Object.keys(isUnitlessNumber).forEach(function (prop) {
12625 prefixes.forEach(function (prefix) {
12626 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
12627 });
12628});
12629
12630/**
12631 * Convert a value into the proper css writable value. The style name `name`
12632 * should be logical (no hyphens), as specified
12633 * in `CSSProperty.isUnitlessNumber`.
12634 *
12635 * @param {string} name CSS property name such as `topMargin`.
12636 * @param {*} value CSS property value such as `10px`.
12637 * @return {string} Normalized style value with dimensions applied.
12638 */
12639function dangerousStyleValue(name, value, isCustomProperty) {
12640 // Note that we've removed escapeTextForBrowser() calls here since the
12641 // whole string will be escaped when the attribute is injected into
12642 // the markup. If you provide unsafe user data here they can inject
12643 // arbitrary CSS which may be problematic (I couldn't repro this):
12644 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
12645 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
12646 // This is not an XSS hole but instead a potential CSS injection issue
12647 // which has lead to a greater discussion about how we're going to
12648 // trust URLs moving forward. See #2115901
12649
12650 var isEmpty = value == null || typeof value === 'boolean' || value === '';
12651 if (isEmpty) {
12652 return '';
12653 }
12654
12655 if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) {
12656 return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
12657 }
12658
12659 return ('' + value).trim();
12660}
12661
12662/**
12663 * Copyright (c) 2013-present, Facebook, Inc.
12664 *
12665 * This source code is licensed under the MIT license found in the
12666 * LICENSE file in the root directory of this source tree.
12667 *
12668 * @typechecks
12669 */
12670
12671var _uppercasePattern = /([A-Z])/g;
12672
12673/**
12674 * Hyphenates a camelcased string, for example:
12675 *
12676 * > hyphenate('backgroundColor')
12677 * < "background-color"
12678 *
12679 * For CSS style names, use `hyphenateStyleName` instead which works properly
12680 * with all vendor prefixes, including `ms`.
12681 *
12682 * @param {string} string
12683 * @return {string}
12684 */
12685function hyphenate(string) {
12686 return string.replace(_uppercasePattern, '-$1').toLowerCase();
12687}
12688
12689var hyphenate_1 = hyphenate;
12690
12691/**
12692 * Copyright (c) 2013-present, Facebook, Inc.
12693 *
12694 * This source code is licensed under the MIT license found in the
12695 * LICENSE file in the root directory of this source tree.
12696 *
12697 * @typechecks
12698 */
12699
12700
12701
12702
12703
12704var msPattern = /^ms-/;
12705
12706/**
12707 * Hyphenates a camelcased CSS property name, for example:
12708 *
12709 * > hyphenateStyleName('backgroundColor')
12710 * < "background-color"
12711 * > hyphenateStyleName('MozTransition')
12712 * < "-moz-transition"
12713 * > hyphenateStyleName('msTransition')
12714 * < "-ms-transition"
12715 *
12716 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
12717 * is converted to `-ms-`.
12718 *
12719 * @param {string} string
12720 * @return {string}
12721 */
12722function hyphenateStyleName(string) {
12723 return hyphenate_1(string).replace(msPattern, '-ms-');
12724}
12725
12726var hyphenateStyleName_1 = hyphenateStyleName;
12727
12728/**
12729 * Copyright (c) 2013-present, Facebook, Inc.
12730 *
12731 * This source code is licensed under the MIT license found in the
12732 * LICENSE file in the root directory of this source tree.
12733 *
12734 * @typechecks
12735 */
12736
12737var _hyphenPattern = /-(.)/g;
12738
12739/**
12740 * Camelcases a hyphenated string, for example:
12741 *
12742 * > camelize('background-color')
12743 * < "backgroundColor"
12744 *
12745 * @param {string} string
12746 * @return {string}
12747 */
12748function camelize(string) {
12749 return string.replace(_hyphenPattern, function (_, character) {
12750 return character.toUpperCase();
12751 });
12752}
12753
12754var camelize_1 = camelize;
12755
12756/**
12757 * Copyright (c) 2013-present, Facebook, Inc.
12758 *
12759 * This source code is licensed under the MIT license found in the
12760 * LICENSE file in the root directory of this source tree.
12761 *
12762 * @typechecks
12763 */
12764
12765
12766
12767
12768
12769var msPattern$1 = /^-ms-/;
12770
12771/**
12772 * Camelcases a hyphenated CSS property name, for example:
12773 *
12774 * > camelizeStyleName('background-color')
12775 * < "backgroundColor"
12776 * > camelizeStyleName('-moz-transition')
12777 * < "MozTransition"
12778 * > camelizeStyleName('-ms-transition')
12779 * < "msTransition"
12780 *
12781 * As Andi Smith suggests
12782 * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix
12783 * is converted to lowercase `ms`.
12784 *
12785 * @param {string} string
12786 * @return {string}
12787 */
12788function camelizeStyleName(string) {
12789 return camelize_1(string.replace(msPattern$1, 'ms-'));
12790}
12791
12792var camelizeStyleName_1 = camelizeStyleName;
12793
12794var warnValidStyle = emptyFunction_1;
12795
12796{
12797 // 'msTransform' is correct, but the other prefixes should be capitalized
12798 var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
12799
12800 // style values shouldn't contain a semicolon
12801 var badStyleValueWithSemicolonPattern = /;\s*$/;
12802
12803 var warnedStyleNames = {};
12804 var warnedStyleValues = {};
12805 var warnedForNaNValue = false;
12806 var warnedForInfinityValue = false;
12807
12808 var warnHyphenatedStyleName = function (name, getStack) {
12809 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
12810 return;
12811 }
12812
12813 warnedStyleNames[name] = true;
12814 warning_1(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName_1(name), getStack());
12815 };
12816
12817 var warnBadVendoredStyleName = function (name, getStack) {
12818 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
12819 return;
12820 }
12821
12822 warnedStyleNames[name] = true;
12823 warning_1(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), getStack());
12824 };
12825
12826 var warnStyleValueWithSemicolon = function (name, value, getStack) {
12827 if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
12828 return;
12829 }
12830
12831 warnedStyleValues[value] = true;
12832 warning_1(false, "Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.%s', name, value.replace(badStyleValueWithSemicolonPattern, ''), getStack());
12833 };
12834
12835 var warnStyleValueIsNaN = function (name, value, getStack) {
12836 if (warnedForNaNValue) {
12837 return;
12838 }
12839
12840 warnedForNaNValue = true;
12841 warning_1(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, getStack());
12842 };
12843
12844 var warnStyleValueIsInfinity = function (name, value, getStack) {
12845 if (warnedForInfinityValue) {
12846 return;
12847 }
12848
12849 warnedForInfinityValue = true;
12850 warning_1(false, '`Infinity` is an invalid value for the `%s` css style property.%s', name, getStack());
12851 };
12852
12853 warnValidStyle = function (name, value, getStack) {
12854 if (name.indexOf('-') > -1) {
12855 warnHyphenatedStyleName(name, getStack);
12856 } else if (badVendoredStyleNamePattern.test(name)) {
12857 warnBadVendoredStyleName(name, getStack);
12858 } else if (badStyleValueWithSemicolonPattern.test(value)) {
12859 warnStyleValueWithSemicolon(name, value, getStack);
12860 }
12861
12862 if (typeof value === 'number') {
12863 if (isNaN(value)) {
12864 warnStyleValueIsNaN(name, value, getStack);
12865 } else if (!isFinite(value)) {
12866 warnStyleValueIsInfinity(name, value, getStack);
12867 }
12868 }
12869 };
12870}
12871
12872var warnValidStyle$1 = warnValidStyle;
12873
12874/**
12875 * Operations for dealing with CSS properties.
12876 */
12877
12878/**
12879 * This creates a string that is expected to be equivalent to the style
12880 * attribute generated by server-side rendering. It by-passes warnings and
12881 * security checks so it's not safe to use this value for anything other than
12882 * comparison. It is only used in DEV for SSR validation.
12883 */
12884function createDangerousStringForStyles(styles) {
12885 {
12886 var serialized = '';
12887 var delimiter = '';
12888 for (var styleName in styles) {
12889 if (!styles.hasOwnProperty(styleName)) {
12890 continue;
12891 }
12892 var styleValue = styles[styleName];
12893 if (styleValue != null) {
12894 var isCustomProperty = styleName.indexOf('--') === 0;
12895 serialized += delimiter + hyphenateStyleName_1(styleName) + ':';
12896 serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty);
12897
12898 delimiter = ';';
12899 }
12900 }
12901 return serialized || null;
12902 }
12903}
12904
12905/**
12906 * Sets the value for multiple styles on a node. If a value is specified as
12907 * '' (empty string), the corresponding style property will be unset.
12908 *
12909 * @param {DOMElement} node
12910 * @param {object} styles
12911 */
12912function setValueForStyles(node, styles, getStack) {
12913 var style = node.style;
12914 for (var styleName in styles) {
12915 if (!styles.hasOwnProperty(styleName)) {
12916 continue;
12917 }
12918 var isCustomProperty = styleName.indexOf('--') === 0;
12919 {
12920 if (!isCustomProperty) {
12921 warnValidStyle$1(styleName, styles[styleName], getStack);
12922 }
12923 }
12924 var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty);
12925 if (styleName === 'float') {
12926 styleName = 'cssFloat';
12927 }
12928 if (isCustomProperty) {
12929 style.setProperty(styleName, styleValue);
12930 } else {
12931 style[styleName] = styleValue;
12932 }
12933 }
12934}
12935
12936// For HTML, certain tags should omit their close tag. We keep a whitelist for
12937// those special-case tags.
12938
12939var omittedCloseTags = {
12940 area: true,
12941 base: true,
12942 br: true,
12943 col: true,
12944 embed: true,
12945 hr: true,
12946 img: true,
12947 input: true,
12948 keygen: true,
12949 link: true,
12950 meta: true,
12951 param: true,
12952 source: true,
12953 track: true,
12954 wbr: true
12955};
12956
12957// For HTML, certain tags cannot have children. This has the same purpose as
12958// `omittedCloseTags` except that `menuitem` should still have its closing tag.
12959
12960var voidElementTags = _assign({
12961 menuitem: true
12962}, omittedCloseTags);
12963
12964var HTML$1 = '__html';
12965
12966function assertValidProps(tag, props, getStack) {
12967 if (!props) {
12968 return;
12969 }
12970 // Note the use of `==` which checks for null or undefined.
12971 if (voidElementTags[tag]) {
12972 !(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;
12973 }
12974 if (props.dangerouslySetInnerHTML != null) {
12975 !(props.children == null) ? invariant_1(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : void 0;
12976 !(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;
12977 }
12978 {
12979 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());
12980 }
12981 !(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;
12982}
12983
12984function isCustomComponent(tagName, props) {
12985 if (tagName.indexOf('-') === -1) {
12986 return typeof props.is === 'string';
12987 }
12988 switch (tagName) {
12989 // These are reserved SVG and MathML elements.
12990 // We don't mind this whitelist too much because we expect it to never grow.
12991 // The alternative is to track the namespace in a few places which is convoluted.
12992 // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
12993 case 'annotation-xml':
12994 case 'color-profile':
12995 case 'font-face':
12996 case 'font-face-src':
12997 case 'font-face-uri':
12998 case 'font-face-format':
12999 case 'font-face-name':
13000 case 'missing-glyph':
13001 return false;
13002 default:
13003 return true;
13004 }
13005}
13006
13007// When adding attributes to the HTML or SVG whitelist, be sure to
13008// also add them to this module to ensure casing and incorrect name
13009// warnings.
13010var possibleStandardNames = {
13011 // HTML
13012 accept: 'accept',
13013 acceptcharset: 'acceptCharset',
13014 'accept-charset': 'acceptCharset',
13015 accesskey: 'accessKey',
13016 action: 'action',
13017 allowfullscreen: 'allowFullScreen',
13018 alt: 'alt',
13019 as: 'as',
13020 async: 'async',
13021 autocapitalize: 'autoCapitalize',
13022 autocomplete: 'autoComplete',
13023 autocorrect: 'autoCorrect',
13024 autofocus: 'autoFocus',
13025 autoplay: 'autoPlay',
13026 autosave: 'autoSave',
13027 capture: 'capture',
13028 cellpadding: 'cellPadding',
13029 cellspacing: 'cellSpacing',
13030 challenge: 'challenge',
13031 charset: 'charSet',
13032 checked: 'checked',
13033 children: 'children',
13034 cite: 'cite',
13035 'class': 'className',
13036 classid: 'classID',
13037 classname: 'className',
13038 cols: 'cols',
13039 colspan: 'colSpan',
13040 content: 'content',
13041 contenteditable: 'contentEditable',
13042 contextmenu: 'contextMenu',
13043 controls: 'controls',
13044 controlslist: 'controlsList',
13045 coords: 'coords',
13046 crossorigin: 'crossOrigin',
13047 dangerouslysetinnerhtml: 'dangerouslySetInnerHTML',
13048 data: 'data',
13049 datetime: 'dateTime',
13050 'default': 'default',
13051 defaultchecked: 'defaultChecked',
13052 defaultvalue: 'defaultValue',
13053 defer: 'defer',
13054 dir: 'dir',
13055 disabled: 'disabled',
13056 download: 'download',
13057 draggable: 'draggable',
13058 enctype: 'encType',
13059 'for': 'htmlFor',
13060 form: 'form',
13061 formmethod: 'formMethod',
13062 formaction: 'formAction',
13063 formenctype: 'formEncType',
13064 formnovalidate: 'formNoValidate',
13065 formtarget: 'formTarget',
13066 frameborder: 'frameBorder',
13067 headers: 'headers',
13068 height: 'height',
13069 hidden: 'hidden',
13070 high: 'high',
13071 href: 'href',
13072 hreflang: 'hrefLang',
13073 htmlfor: 'htmlFor',
13074 httpequiv: 'httpEquiv',
13075 'http-equiv': 'httpEquiv',
13076 icon: 'icon',
13077 id: 'id',
13078 innerhtml: 'innerHTML',
13079 inputmode: 'inputMode',
13080 integrity: 'integrity',
13081 is: 'is',
13082 itemid: 'itemID',
13083 itemprop: 'itemProp',
13084 itemref: 'itemRef',
13085 itemscope: 'itemScope',
13086 itemtype: 'itemType',
13087 keyparams: 'keyParams',
13088 keytype: 'keyType',
13089 kind: 'kind',
13090 label: 'label',
13091 lang: 'lang',
13092 list: 'list',
13093 loop: 'loop',
13094 low: 'low',
13095 manifest: 'manifest',
13096 marginwidth: 'marginWidth',
13097 marginheight: 'marginHeight',
13098 max: 'max',
13099 maxlength: 'maxLength',
13100 media: 'media',
13101 mediagroup: 'mediaGroup',
13102 method: 'method',
13103 min: 'min',
13104 minlength: 'minLength',
13105 multiple: 'multiple',
13106 muted: 'muted',
13107 name: 'name',
13108 nomodule: 'noModule',
13109 nonce: 'nonce',
13110 novalidate: 'noValidate',
13111 open: 'open',
13112 optimum: 'optimum',
13113 pattern: 'pattern',
13114 placeholder: 'placeholder',
13115 playsinline: 'playsInline',
13116 poster: 'poster',
13117 preload: 'preload',
13118 profile: 'profile',
13119 radiogroup: 'radioGroup',
13120 readonly: 'readOnly',
13121 referrerpolicy: 'referrerPolicy',
13122 rel: 'rel',
13123 required: 'required',
13124 reversed: 'reversed',
13125 role: 'role',
13126 rows: 'rows',
13127 rowspan: 'rowSpan',
13128 sandbox: 'sandbox',
13129 scope: 'scope',
13130 scoped: 'scoped',
13131 scrolling: 'scrolling',
13132 seamless: 'seamless',
13133 selected: 'selected',
13134 shape: 'shape',
13135 size: 'size',
13136 sizes: 'sizes',
13137 span: 'span',
13138 spellcheck: 'spellCheck',
13139 src: 'src',
13140 srcdoc: 'srcDoc',
13141 srclang: 'srcLang',
13142 srcset: 'srcSet',
13143 start: 'start',
13144 step: 'step',
13145 style: 'style',
13146 summary: 'summary',
13147 tabindex: 'tabIndex',
13148 target: 'target',
13149 title: 'title',
13150 type: 'type',
13151 usemap: 'useMap',
13152 value: 'value',
13153 width: 'width',
13154 wmode: 'wmode',
13155 wrap: 'wrap',
13156
13157 // SVG
13158 about: 'about',
13159 accentheight: 'accentHeight',
13160 'accent-height': 'accentHeight',
13161 accumulate: 'accumulate',
13162 additive: 'additive',
13163 alignmentbaseline: 'alignmentBaseline',
13164 'alignment-baseline': 'alignmentBaseline',
13165 allowreorder: 'allowReorder',
13166 alphabetic: 'alphabetic',
13167 amplitude: 'amplitude',
13168 arabicform: 'arabicForm',
13169 'arabic-form': 'arabicForm',
13170 ascent: 'ascent',
13171 attributename: 'attributeName',
13172 attributetype: 'attributeType',
13173 autoreverse: 'autoReverse',
13174 azimuth: 'azimuth',
13175 basefrequency: 'baseFrequency',
13176 baselineshift: 'baselineShift',
13177 'baseline-shift': 'baselineShift',
13178 baseprofile: 'baseProfile',
13179 bbox: 'bbox',
13180 begin: 'begin',
13181 bias: 'bias',
13182 by: 'by',
13183 calcmode: 'calcMode',
13184 capheight: 'capHeight',
13185 'cap-height': 'capHeight',
13186 clip: 'clip',
13187 clippath: 'clipPath',
13188 'clip-path': 'clipPath',
13189 clippathunits: 'clipPathUnits',
13190 cliprule: 'clipRule',
13191 'clip-rule': 'clipRule',
13192 color: 'color',
13193 colorinterpolation: 'colorInterpolation',
13194 'color-interpolation': 'colorInterpolation',
13195 colorinterpolationfilters: 'colorInterpolationFilters',
13196 'color-interpolation-filters': 'colorInterpolationFilters',
13197 colorprofile: 'colorProfile',
13198 'color-profile': 'colorProfile',
13199 colorrendering: 'colorRendering',
13200 'color-rendering': 'colorRendering',
13201 contentscripttype: 'contentScriptType',
13202 contentstyletype: 'contentStyleType',
13203 cursor: 'cursor',
13204 cx: 'cx',
13205 cy: 'cy',
13206 d: 'd',
13207 datatype: 'datatype',
13208 decelerate: 'decelerate',
13209 descent: 'descent',
13210 diffuseconstant: 'diffuseConstant',
13211 direction: 'direction',
13212 display: 'display',
13213 divisor: 'divisor',
13214 dominantbaseline: 'dominantBaseline',
13215 'dominant-baseline': 'dominantBaseline',
13216 dur: 'dur',
13217 dx: 'dx',
13218 dy: 'dy',
13219 edgemode: 'edgeMode',
13220 elevation: 'elevation',
13221 enablebackground: 'enableBackground',
13222 'enable-background': 'enableBackground',
13223 end: 'end',
13224 exponent: 'exponent',
13225 externalresourcesrequired: 'externalResourcesRequired',
13226 fill: 'fill',
13227 fillopacity: 'fillOpacity',
13228 'fill-opacity': 'fillOpacity',
13229 fillrule: 'fillRule',
13230 'fill-rule': 'fillRule',
13231 filter: 'filter',
13232 filterres: 'filterRes',
13233 filterunits: 'filterUnits',
13234 floodopacity: 'floodOpacity',
13235 'flood-opacity': 'floodOpacity',
13236 floodcolor: 'floodColor',
13237 'flood-color': 'floodColor',
13238 focusable: 'focusable',
13239 fontfamily: 'fontFamily',
13240 'font-family': 'fontFamily',
13241 fontsize: 'fontSize',
13242 'font-size': 'fontSize',
13243 fontsizeadjust: 'fontSizeAdjust',
13244 'font-size-adjust': 'fontSizeAdjust',
13245 fontstretch: 'fontStretch',
13246 'font-stretch': 'fontStretch',
13247 fontstyle: 'fontStyle',
13248 'font-style': 'fontStyle',
13249 fontvariant: 'fontVariant',
13250 'font-variant': 'fontVariant',
13251 fontweight: 'fontWeight',
13252 'font-weight': 'fontWeight',
13253 format: 'format',
13254 from: 'from',
13255 fx: 'fx',
13256 fy: 'fy',
13257 g1: 'g1',
13258 g2: 'g2',
13259 glyphname: 'glyphName',
13260 'glyph-name': 'glyphName',
13261 glyphorientationhorizontal: 'glyphOrientationHorizontal',
13262 'glyph-orientation-horizontal': 'glyphOrientationHorizontal',
13263 glyphorientationvertical: 'glyphOrientationVertical',
13264 'glyph-orientation-vertical': 'glyphOrientationVertical',
13265 glyphref: 'glyphRef',
13266 gradienttransform: 'gradientTransform',
13267 gradientunits: 'gradientUnits',
13268 hanging: 'hanging',
13269 horizadvx: 'horizAdvX',
13270 'horiz-adv-x': 'horizAdvX',
13271 horizoriginx: 'horizOriginX',
13272 'horiz-origin-x': 'horizOriginX',
13273 ideographic: 'ideographic',
13274 imagerendering: 'imageRendering',
13275 'image-rendering': 'imageRendering',
13276 in2: 'in2',
13277 'in': 'in',
13278 inlist: 'inlist',
13279 intercept: 'intercept',
13280 k1: 'k1',
13281 k2: 'k2',
13282 k3: 'k3',
13283 k4: 'k4',
13284 k: 'k',
13285 kernelmatrix: 'kernelMatrix',
13286 kernelunitlength: 'kernelUnitLength',
13287 kerning: 'kerning',
13288 keypoints: 'keyPoints',
13289 keysplines: 'keySplines',
13290 keytimes: 'keyTimes',
13291 lengthadjust: 'lengthAdjust',
13292 letterspacing: 'letterSpacing',
13293 'letter-spacing': 'letterSpacing',
13294 lightingcolor: 'lightingColor',
13295 'lighting-color': 'lightingColor',
13296 limitingconeangle: 'limitingConeAngle',
13297 local: 'local',
13298 markerend: 'markerEnd',
13299 'marker-end': 'markerEnd',
13300 markerheight: 'markerHeight',
13301 markermid: 'markerMid',
13302 'marker-mid': 'markerMid',
13303 markerstart: 'markerStart',
13304 'marker-start': 'markerStart',
13305 markerunits: 'markerUnits',
13306 markerwidth: 'markerWidth',
13307 mask: 'mask',
13308 maskcontentunits: 'maskContentUnits',
13309 maskunits: 'maskUnits',
13310 mathematical: 'mathematical',
13311 mode: 'mode',
13312 numoctaves: 'numOctaves',
13313 offset: 'offset',
13314 opacity: 'opacity',
13315 operator: 'operator',
13316 order: 'order',
13317 orient: 'orient',
13318 orientation: 'orientation',
13319 origin: 'origin',
13320 overflow: 'overflow',
13321 overlineposition: 'overlinePosition',
13322 'overline-position': 'overlinePosition',
13323 overlinethickness: 'overlineThickness',
13324 'overline-thickness': 'overlineThickness',
13325 paintorder: 'paintOrder',
13326 'paint-order': 'paintOrder',
13327 panose1: 'panose1',
13328 'panose-1': 'panose1',
13329 pathlength: 'pathLength',
13330 patterncontentunits: 'patternContentUnits',
13331 patterntransform: 'patternTransform',
13332 patternunits: 'patternUnits',
13333 pointerevents: 'pointerEvents',
13334 'pointer-events': 'pointerEvents',
13335 points: 'points',
13336 pointsatx: 'pointsAtX',
13337 pointsaty: 'pointsAtY',
13338 pointsatz: 'pointsAtZ',
13339 prefix: 'prefix',
13340 preservealpha: 'preserveAlpha',
13341 preserveaspectratio: 'preserveAspectRatio',
13342 primitiveunits: 'primitiveUnits',
13343 property: 'property',
13344 r: 'r',
13345 radius: 'radius',
13346 refx: 'refX',
13347 refy: 'refY',
13348 renderingintent: 'renderingIntent',
13349 'rendering-intent': 'renderingIntent',
13350 repeatcount: 'repeatCount',
13351 repeatdur: 'repeatDur',
13352 requiredextensions: 'requiredExtensions',
13353 requiredfeatures: 'requiredFeatures',
13354 resource: 'resource',
13355 restart: 'restart',
13356 result: 'result',
13357 results: 'results',
13358 rotate: 'rotate',
13359 rx: 'rx',
13360 ry: 'ry',
13361 scale: 'scale',
13362 security: 'security',
13363 seed: 'seed',
13364 shaperendering: 'shapeRendering',
13365 'shape-rendering': 'shapeRendering',
13366 slope: 'slope',
13367 spacing: 'spacing',
13368 specularconstant: 'specularConstant',
13369 specularexponent: 'specularExponent',
13370 speed: 'speed',
13371 spreadmethod: 'spreadMethod',
13372 startoffset: 'startOffset',
13373 stddeviation: 'stdDeviation',
13374 stemh: 'stemh',
13375 stemv: 'stemv',
13376 stitchtiles: 'stitchTiles',
13377 stopcolor: 'stopColor',
13378 'stop-color': 'stopColor',
13379 stopopacity: 'stopOpacity',
13380 'stop-opacity': 'stopOpacity',
13381 strikethroughposition: 'strikethroughPosition',
13382 'strikethrough-position': 'strikethroughPosition',
13383 strikethroughthickness: 'strikethroughThickness',
13384 'strikethrough-thickness': 'strikethroughThickness',
13385 string: 'string',
13386 stroke: 'stroke',
13387 strokedasharray: 'strokeDasharray',
13388 'stroke-dasharray': 'strokeDasharray',
13389 strokedashoffset: 'strokeDashoffset',
13390 'stroke-dashoffset': 'strokeDashoffset',
13391 strokelinecap: 'strokeLinecap',
13392 'stroke-linecap': 'strokeLinecap',
13393 strokelinejoin: 'strokeLinejoin',
13394 'stroke-linejoin': 'strokeLinejoin',
13395 strokemiterlimit: 'strokeMiterlimit',
13396 'stroke-miterlimit': 'strokeMiterlimit',
13397 strokewidth: 'strokeWidth',
13398 'stroke-width': 'strokeWidth',
13399 strokeopacity: 'strokeOpacity',
13400 'stroke-opacity': 'strokeOpacity',
13401 suppresscontenteditablewarning: 'suppressContentEditableWarning',
13402 suppresshydrationwarning: 'suppressHydrationWarning',
13403 surfacescale: 'surfaceScale',
13404 systemlanguage: 'systemLanguage',
13405 tablevalues: 'tableValues',
13406 targetx: 'targetX',
13407 targety: 'targetY',
13408 textanchor: 'textAnchor',
13409 'text-anchor': 'textAnchor',
13410 textdecoration: 'textDecoration',
13411 'text-decoration': 'textDecoration',
13412 textlength: 'textLength',
13413 textrendering: 'textRendering',
13414 'text-rendering': 'textRendering',
13415 to: 'to',
13416 transform: 'transform',
13417 'typeof': 'typeof',
13418 u1: 'u1',
13419 u2: 'u2',
13420 underlineposition: 'underlinePosition',
13421 'underline-position': 'underlinePosition',
13422 underlinethickness: 'underlineThickness',
13423 'underline-thickness': 'underlineThickness',
13424 unicode: 'unicode',
13425 unicodebidi: 'unicodeBidi',
13426 'unicode-bidi': 'unicodeBidi',
13427 unicoderange: 'unicodeRange',
13428 'unicode-range': 'unicodeRange',
13429 unitsperem: 'unitsPerEm',
13430 'units-per-em': 'unitsPerEm',
13431 unselectable: 'unselectable',
13432 valphabetic: 'vAlphabetic',
13433 'v-alphabetic': 'vAlphabetic',
13434 values: 'values',
13435 vectoreffect: 'vectorEffect',
13436 'vector-effect': 'vectorEffect',
13437 version: 'version',
13438 vertadvy: 'vertAdvY',
13439 'vert-adv-y': 'vertAdvY',
13440 vertoriginx: 'vertOriginX',
13441 'vert-origin-x': 'vertOriginX',
13442 vertoriginy: 'vertOriginY',
13443 'vert-origin-y': 'vertOriginY',
13444 vhanging: 'vHanging',
13445 'v-hanging': 'vHanging',
13446 videographic: 'vIdeographic',
13447 'v-ideographic': 'vIdeographic',
13448 viewbox: 'viewBox',
13449 viewtarget: 'viewTarget',
13450 visibility: 'visibility',
13451 vmathematical: 'vMathematical',
13452 'v-mathematical': 'vMathematical',
13453 vocab: 'vocab',
13454 widths: 'widths',
13455 wordspacing: 'wordSpacing',
13456 'word-spacing': 'wordSpacing',
13457 writingmode: 'writingMode',
13458 'writing-mode': 'writingMode',
13459 x1: 'x1',
13460 x2: 'x2',
13461 x: 'x',
13462 xchannelselector: 'xChannelSelector',
13463 xheight: 'xHeight',
13464 'x-height': 'xHeight',
13465 xlinkactuate: 'xlinkActuate',
13466 'xlink:actuate': 'xlinkActuate',
13467 xlinkarcrole: 'xlinkArcrole',
13468 'xlink:arcrole': 'xlinkArcrole',
13469 xlinkhref: 'xlinkHref',
13470 'xlink:href': 'xlinkHref',
13471 xlinkrole: 'xlinkRole',
13472 'xlink:role': 'xlinkRole',
13473 xlinkshow: 'xlinkShow',
13474 'xlink:show': 'xlinkShow',
13475 xlinktitle: 'xlinkTitle',
13476 'xlink:title': 'xlinkTitle',
13477 xlinktype: 'xlinkType',
13478 'xlink:type': 'xlinkType',
13479 xmlbase: 'xmlBase',
13480 'xml:base': 'xmlBase',
13481 xmllang: 'xmlLang',
13482 'xml:lang': 'xmlLang',
13483 xmlns: 'xmlns',
13484 'xml:space': 'xmlSpace',
13485 xmlnsxlink: 'xmlnsXlink',
13486 'xmlns:xlink': 'xmlnsXlink',
13487 xmlspace: 'xmlSpace',
13488 y1: 'y1',
13489 y2: 'y2',
13490 y: 'y',
13491 ychannelselector: 'yChannelSelector',
13492 z: 'z',
13493 zoomandpan: 'zoomAndPan'
13494};
13495
13496var ariaProperties = {
13497 'aria-current': 0, // state
13498 'aria-details': 0,
13499 'aria-disabled': 0, // state
13500 'aria-hidden': 0, // state
13501 'aria-invalid': 0, // state
13502 'aria-keyshortcuts': 0,
13503 'aria-label': 0,
13504 'aria-roledescription': 0,
13505 // Widget Attributes
13506 'aria-autocomplete': 0,
13507 'aria-checked': 0,
13508 'aria-expanded': 0,
13509 'aria-haspopup': 0,
13510 'aria-level': 0,
13511 'aria-modal': 0,
13512 'aria-multiline': 0,
13513 'aria-multiselectable': 0,
13514 'aria-orientation': 0,
13515 'aria-placeholder': 0,
13516 'aria-pressed': 0,
13517 'aria-readonly': 0,
13518 'aria-required': 0,
13519 'aria-selected': 0,
13520 'aria-sort': 0,
13521 'aria-valuemax': 0,
13522 'aria-valuemin': 0,
13523 'aria-valuenow': 0,
13524 'aria-valuetext': 0,
13525 // Live Region Attributes
13526 'aria-atomic': 0,
13527 'aria-busy': 0,
13528 'aria-live': 0,
13529 'aria-relevant': 0,
13530 // Drag-and-Drop Attributes
13531 'aria-dropeffect': 0,
13532 'aria-grabbed': 0,
13533 // Relationship Attributes
13534 'aria-activedescendant': 0,
13535 'aria-colcount': 0,
13536 'aria-colindex': 0,
13537 'aria-colspan': 0,
13538 'aria-controls': 0,
13539 'aria-describedby': 0,
13540 'aria-errormessage': 0,
13541 'aria-flowto': 0,
13542 'aria-labelledby': 0,
13543 'aria-owns': 0,
13544 'aria-posinset': 0,
13545 'aria-rowcount': 0,
13546 'aria-rowindex': 0,
13547 'aria-rowspan': 0,
13548 'aria-setsize': 0
13549};
13550
13551var warnedProperties = {};
13552var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
13553var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
13554
13555var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
13556
13557function getStackAddendum() {
13558 var stack = ReactDebugCurrentFrame.getStackAddendum();
13559 return stack != null ? stack : '';
13560}
13561
13562function validateProperty(tagName, name) {
13563 if (hasOwnProperty$1.call(warnedProperties, name) && warnedProperties[name]) {
13564 return true;
13565 }
13566
13567 if (rARIACamel.test(name)) {
13568 var ariaName = 'aria-' + name.slice(4).toLowerCase();
13569 var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null;
13570
13571 // If this is an aria-* attribute, but is not listed in the known DOM
13572 // DOM properties, then it is an invalid aria-* attribute.
13573 if (correctName == null) {
13574 warning_1(false, 'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.%s', name, getStackAddendum());
13575 warnedProperties[name] = true;
13576 return true;
13577 }
13578 // aria-* attributes should be lowercase; suggest the lowercase version.
13579 if (name !== correctName) {
13580 warning_1(false, 'Invalid ARIA attribute `%s`. Did you mean `%s`?%s', name, correctName, getStackAddendum());
13581 warnedProperties[name] = true;
13582 return true;
13583 }
13584 }
13585
13586 if (rARIA.test(name)) {
13587 var lowerCasedName = name.toLowerCase();
13588 var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null;
13589
13590 // If this is an aria-* attribute, but is not listed in the known DOM
13591 // DOM properties, then it is an invalid aria-* attribute.
13592 if (standardName == null) {
13593 warnedProperties[name] = true;
13594 return false;
13595 }
13596 // aria-* attributes should be lowercase; suggest the lowercase version.
13597 if (name !== standardName) {
13598 warning_1(false, 'Unknown ARIA attribute `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum());
13599 warnedProperties[name] = true;
13600 return true;
13601 }
13602 }
13603
13604 return true;
13605}
13606
13607function warnInvalidARIAProps(type, props) {
13608 var invalidProps = [];
13609
13610 for (var key in props) {
13611 var isValid = validateProperty(type, key);
13612 if (!isValid) {
13613 invalidProps.push(key);
13614 }
13615 }
13616
13617 var unknownPropString = invalidProps.map(function (prop) {
13618 return '`' + prop + '`';
13619 }).join(', ');
13620
13621 if (invalidProps.length === 1) {
13622 warning_1(false, 'Invalid aria prop %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum());
13623 } else if (invalidProps.length > 1) {
13624 warning_1(false, 'Invalid aria props %s on <%s> tag. ' + 'For details, see https://fb.me/invalid-aria-prop%s', unknownPropString, type, getStackAddendum());
13625 }
13626}
13627
13628function validateProperties(type, props) {
13629 if (isCustomComponent(type, props)) {
13630 return;
13631 }
13632 warnInvalidARIAProps(type, props);
13633}
13634
13635var didWarnValueNull = false;
13636
13637function getStackAddendum$1() {
13638 var stack = ReactDebugCurrentFrame.getStackAddendum();
13639 return stack != null ? stack : '';
13640}
13641
13642function validateProperties$1(type, props) {
13643 if (type !== 'input' && type !== 'textarea' && type !== 'select') {
13644 return;
13645 }
13646
13647 if (props != null && props.value === null && !didWarnValueNull) {
13648 didWarnValueNull = true;
13649 if (type === 'select' && props.multiple) {
13650 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());
13651 } else {
13652 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());
13653 }
13654 }
13655}
13656
13657function getStackAddendum$2() {
13658 var stack = ReactDebugCurrentFrame.getStackAddendum();
13659 return stack != null ? stack : '';
13660}
13661
13662var validateProperty$1 = function () {};
13663
13664{
13665 var warnedProperties$1 = {};
13666 var _hasOwnProperty = Object.prototype.hasOwnProperty;
13667 var EVENT_NAME_REGEX = /^on./;
13668 var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/;
13669 var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
13670 var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
13671
13672 validateProperty$1 = function (tagName, name, value, canUseEventSystem) {
13673 if (_hasOwnProperty.call(warnedProperties$1, name) && warnedProperties$1[name]) {
13674 return true;
13675 }
13676
13677 var lowerCasedName = name.toLowerCase();
13678 if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') {
13679 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.');
13680 warnedProperties$1[name] = true;
13681 return true;
13682 }
13683
13684 // We can't rely on the event system being injected on the server.
13685 if (canUseEventSystem) {
13686 if (registrationNameModules.hasOwnProperty(name)) {
13687 return true;
13688 }
13689 var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null;
13690 if (registrationName != null) {
13691 warning_1(false, 'Invalid event handler property `%s`. Did you mean `%s`?%s', name, registrationName, getStackAddendum$2());
13692 warnedProperties$1[name] = true;
13693 return true;
13694 }
13695 if (EVENT_NAME_REGEX.test(name)) {
13696 warning_1(false, 'Unknown event handler property `%s`. It will be ignored.%s', name, getStackAddendum$2());
13697 warnedProperties$1[name] = true;
13698 return true;
13699 }
13700 } else if (EVENT_NAME_REGEX.test(name)) {
13701 // If no event plugins have been injected, we are in a server environment.
13702 // So we can't tell if the event name is correct for sure, but we can filter
13703 // out known bad ones like `onclick`. We can't suggest a specific replacement though.
13704 if (INVALID_EVENT_NAME_REGEX.test(name)) {
13705 warning_1(false, 'Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.%s', name, getStackAddendum$2());
13706 }
13707 warnedProperties$1[name] = true;
13708 return true;
13709 }
13710
13711 // Let the ARIA attribute hook validate ARIA attributes
13712 if (rARIA$1.test(name) || rARIACamel$1.test(name)) {
13713 return true;
13714 }
13715
13716 if (lowerCasedName === 'innerhtml') {
13717 warning_1(false, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.');
13718 warnedProperties$1[name] = true;
13719 return true;
13720 }
13721
13722 if (lowerCasedName === 'aria') {
13723 warning_1(false, 'The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.');
13724 warnedProperties$1[name] = true;
13725 return true;
13726 }
13727
13728 if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') {
13729 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());
13730 warnedProperties$1[name] = true;
13731 return true;
13732 }
13733
13734 if (typeof value === 'number' && isNaN(value)) {
13735 warning_1(false, 'Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.%s', name, getStackAddendum$2());
13736 warnedProperties$1[name] = true;
13737 return true;
13738 }
13739
13740 var propertyInfo = getPropertyInfo(name);
13741 var isReserved = propertyInfo !== null && propertyInfo.type === RESERVED;
13742
13743 // Known attributes should match the casing specified in the property config.
13744 if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
13745 var standardName = possibleStandardNames[lowerCasedName];
13746 if (standardName !== name) {
13747 warning_1(false, 'Invalid DOM property `%s`. Did you mean `%s`?%s', name, standardName, getStackAddendum$2());
13748 warnedProperties$1[name] = true;
13749 return true;
13750 }
13751 } else if (!isReserved && name !== lowerCasedName) {
13752 // Unknown attributes should have lowercase casing since that's how they
13753 // will be cased anyway with server rendering.
13754 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());
13755 warnedProperties$1[name] = true;
13756 return true;
13757 }
13758
13759 if (typeof value === 'boolean' && shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) {
13760 if (value) {
13761 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());
13762 } else {
13763 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());
13764 }
13765 warnedProperties$1[name] = true;
13766 return true;
13767 }
13768
13769 // Now that we've validated casing, do not validate
13770 // data types for reserved props
13771 if (isReserved) {
13772 return true;
13773 }
13774
13775 // Warn when a known attribute is a bad type
13776 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) {
13777 warnedProperties$1[name] = true;
13778 return false;
13779 }
13780
13781 return true;
13782 };
13783}
13784
13785var warnUnknownProperties = function (type, props, canUseEventSystem) {
13786 var unknownProps = [];
13787 for (var key in props) {
13788 var isValid = validateProperty$1(type, key, props[key], canUseEventSystem);
13789 if (!isValid) {
13790 unknownProps.push(key);
13791 }
13792 }
13793
13794 var unknownPropString = unknownProps.map(function (prop) {
13795 return '`' + prop + '`';
13796 }).join(', ');
13797 if (unknownProps.length === 1) {
13798 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());
13799 } else if (unknownProps.length > 1) {
13800 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());
13801 }
13802};
13803
13804function validateProperties$2(type, props, canUseEventSystem) {
13805 if (isCustomComponent(type, props)) {
13806 return;
13807 }
13808 warnUnknownProperties(type, props, canUseEventSystem);
13809}
13810
13811// TODO: direct imports like some-package/src/* are bad. Fix me.
13812var getCurrentFiberOwnerName$2 = ReactDebugCurrentFiber.getCurrentFiberOwnerName;
13813var getCurrentFiberStackAddendum$3 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
13814
13815var didWarnInvalidHydration = false;
13816var didWarnShadyDOM = false;
13817
13818var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
13819var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
13820var SUPPRESS_HYDRATION_WARNING$1 = 'suppressHydrationWarning';
13821var AUTOFOCUS = 'autoFocus';
13822var CHILDREN = 'children';
13823var STYLE = 'style';
13824var HTML = '__html';
13825
13826var HTML_NAMESPACE = Namespaces.html;
13827
13828
13829var getStack = emptyFunction_1.thatReturns('');
13830
13831var warnedUnknownTags = void 0;
13832var suppressHydrationWarning = void 0;
13833
13834var validatePropertiesInDevelopment = void 0;
13835var warnForTextDifference = void 0;
13836var warnForPropDifference = void 0;
13837var warnForExtraAttributes = void 0;
13838var warnForInvalidEventListener = void 0;
13839
13840var normalizeMarkupForTextOrAttribute = void 0;
13841var normalizeHTML = void 0;
13842
13843{
13844 getStack = getCurrentFiberStackAddendum$3;
13845
13846 warnedUnknownTags = {
13847 // Chrome is the only major browser not shipping <time>. But as of July
13848 // 2017 it intends to ship it due to widespread usage. We intentionally
13849 // *don't* warn for <time> even if it's unrecognized by Chrome because
13850 // it soon will be, and many apps have been using it anyway.
13851 time: true,
13852 // There are working polyfills for <dialog>. Let people use it.
13853 dialog: true
13854 };
13855
13856 validatePropertiesInDevelopment = function (type, props) {
13857 validateProperties(type, props);
13858 validateProperties$1(type, props);
13859 validateProperties$2(type, props, /* canUseEventSystem */true);
13860 };
13861
13862 // HTML parsing normalizes CR and CRLF to LF.
13863 // It also can turn \u0000 into \uFFFD inside attributes.
13864 // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream
13865 // If we have a mismatch, it might be caused by that.
13866 // We will still patch up in this case but not fire the warning.
13867 var NORMALIZE_NEWLINES_REGEX = /\r\n?/g;
13868 var NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g;
13869
13870 normalizeMarkupForTextOrAttribute = function (markup) {
13871 var markupString = typeof markup === 'string' ? markup : '' + markup;
13872 return markupString.replace(NORMALIZE_NEWLINES_REGEX, '\n').replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, '');
13873 };
13874
13875 warnForTextDifference = function (serverText, clientText) {
13876 if (didWarnInvalidHydration) {
13877 return;
13878 }
13879 var normalizedClientText = normalizeMarkupForTextOrAttribute(clientText);
13880 var normalizedServerText = normalizeMarkupForTextOrAttribute(serverText);
13881 if (normalizedServerText === normalizedClientText) {
13882 return;
13883 }
13884 didWarnInvalidHydration = true;
13885 warning_1(false, 'Text content did not match. Server: "%s" Client: "%s"', normalizedServerText, normalizedClientText);
13886 };
13887
13888 warnForPropDifference = function (propName, serverValue, clientValue) {
13889 if (didWarnInvalidHydration) {
13890 return;
13891 }
13892 var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue);
13893 var normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);
13894 if (normalizedServerValue === normalizedClientValue) {
13895 return;
13896 }
13897 didWarnInvalidHydration = true;
13898 warning_1(false, 'Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue));
13899 };
13900
13901 warnForExtraAttributes = function (attributeNames) {
13902 if (didWarnInvalidHydration) {
13903 return;
13904 }
13905 didWarnInvalidHydration = true;
13906 var names = [];
13907 attributeNames.forEach(function (name) {
13908 names.push(name);
13909 });
13910 warning_1(false, 'Extra attributes from the server: %s', names);
13911 };
13912
13913 warnForInvalidEventListener = function (registrationName, listener) {
13914 if (listener === false) {
13915 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());
13916 } else {
13917 warning_1(false, 'Expected `%s` listener to be a function, instead got a value of `%s` type.%s', registrationName, typeof listener, getCurrentFiberStackAddendum$3());
13918 }
13919 };
13920
13921 // Parse the HTML and read it back to normalize the HTML string so that it
13922 // can be used for comparison.
13923 normalizeHTML = function (parent, html) {
13924 // We could have created a separate document here to avoid
13925 // re-initializing custom elements if they exist. But this breaks
13926 // how <noscript> is being handled. So we use the same document.
13927 // See the discussion in https://github.com/facebook/react/pull/11157.
13928 var testElement = parent.namespaceURI === HTML_NAMESPACE ? parent.ownerDocument.createElement(parent.tagName) : parent.ownerDocument.createElementNS(parent.namespaceURI, parent.tagName);
13929 testElement.innerHTML = html;
13930 return testElement.innerHTML;
13931 };
13932}
13933
13934function ensureListeningTo(rootContainerElement, registrationName) {
13935 var isDocumentOrFragment = rootContainerElement.nodeType === DOCUMENT_NODE || rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE;
13936 var doc = isDocumentOrFragment ? rootContainerElement : rootContainerElement.ownerDocument;
13937 listenTo(registrationName, doc);
13938}
13939
13940function getOwnerDocumentFromRootContainer(rootContainerElement) {
13941 return rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument;
13942}
13943
13944function trapClickOnNonInteractiveElement(node) {
13945 // Mobile Safari does not fire properly bubble click events on
13946 // non-interactive elements, which means delegated click listeners do not
13947 // fire. The workaround for this bug involves attaching an empty click
13948 // listener on the target node.
13949 // http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
13950 // Just set it using the onclick property so that we don't have to manage any
13951 // bookkeeping for it. Not sure if we need to clear it when the listener is
13952 // removed.
13953 // TODO: Only do this for the relevant Safaris maybe?
13954 node.onclick = emptyFunction_1;
13955}
13956
13957function setInitialDOMProperties(tag, domElement, rootContainerElement, nextProps, isCustomComponentTag) {
13958 for (var propKey in nextProps) {
13959 if (!nextProps.hasOwnProperty(propKey)) {
13960 continue;
13961 }
13962 var nextProp = nextProps[propKey];
13963 if (propKey === STYLE) {
13964 {
13965 if (nextProp) {
13966 // Freeze the next style object so that we can assume it won't be
13967 // mutated. We have already warned for this in the past.
13968 Object.freeze(nextProp);
13969 }
13970 }
13971 // Relies on `updateStylesByID` not mutating `styleUpdates`.
13972 setValueForStyles(domElement, nextProp, getStack);
13973 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
13974 var nextHtml = nextProp ? nextProp[HTML] : undefined;
13975 if (nextHtml != null) {
13976 setInnerHTML(domElement, nextHtml);
13977 }
13978 } else if (propKey === CHILDREN) {
13979 if (typeof nextProp === 'string') {
13980 // Avoid setting initial textContent when the text is empty. In IE11 setting
13981 // textContent on a <textarea> will cause the placeholder to not
13982 // show within the <textarea> until it has been focused and blurred again.
13983 // https://github.com/facebook/react/issues/6731#issuecomment-254874553
13984 var canSetTextContent = tag !== 'textarea' || nextProp !== '';
13985 if (canSetTextContent) {
13986 setTextContent(domElement, nextProp);
13987 }
13988 } else if (typeof nextProp === 'number') {
13989 setTextContent(domElement, '' + nextProp);
13990 }
13991 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
13992 // Noop
13993 } else if (propKey === AUTOFOCUS) {
13994 // We polyfill it separately on the client during commit.
13995 // We blacklist it here rather than in the property list because we emit it in SSR.
13996 } else if (registrationNameModules.hasOwnProperty(propKey)) {
13997 if (nextProp != null) {
13998 if (true && typeof nextProp !== 'function') {
13999 warnForInvalidEventListener(propKey, nextProp);
14000 }
14001 ensureListeningTo(rootContainerElement, propKey);
14002 }
14003 } else if (nextProp != null) {
14004 setValueForProperty(domElement, propKey, nextProp, isCustomComponentTag);
14005 }
14006 }
14007}
14008
14009function updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag) {
14010 // TODO: Handle wasCustomComponentTag
14011 for (var i = 0; i < updatePayload.length; i += 2) {
14012 var propKey = updatePayload[i];
14013 var propValue = updatePayload[i + 1];
14014 if (propKey === STYLE) {
14015 setValueForStyles(domElement, propValue, getStack);
14016 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14017 setInnerHTML(domElement, propValue);
14018 } else if (propKey === CHILDREN) {
14019 setTextContent(domElement, propValue);
14020 } else {
14021 setValueForProperty(domElement, propKey, propValue, isCustomComponentTag);
14022 }
14023 }
14024}
14025
14026function createElement$1(type, props, rootContainerElement, parentNamespace) {
14027 var isCustomComponentTag = void 0;
14028
14029 // We create tags in the namespace of their parent container, except HTML
14030 // tags get no namespace.
14031 var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement);
14032 var domElement = void 0;
14033 var namespaceURI = parentNamespace;
14034 if (namespaceURI === HTML_NAMESPACE) {
14035 namespaceURI = getIntrinsicNamespace(type);
14036 }
14037 if (namespaceURI === HTML_NAMESPACE) {
14038 {
14039 isCustomComponentTag = isCustomComponent(type, props);
14040 // Should this check be gated by parent namespace? Not sure we want to
14041 // allow <SVG> or <mATH>.
14042 warning_1(isCustomComponentTag || type === type.toLowerCase(), '<%s /> is using uppercase HTML. Always use lowercase HTML tags ' + 'in React.', type);
14043 }
14044
14045 if (type === 'script') {
14046 // Create the script via .innerHTML so its "parser-inserted" flag is
14047 // set to true and it does not execute
14048 var div = ownerDocument.createElement('div');
14049 div.innerHTML = '<script><' + '/script>'; // eslint-disable-line
14050 // This is guaranteed to yield a script element.
14051 var firstChild = div.firstChild;
14052 domElement = div.removeChild(firstChild);
14053 } else if (typeof props.is === 'string') {
14054 // $FlowIssue `createElement` should be updated for Web Components
14055 domElement = ownerDocument.createElement(type, { is: props.is });
14056 } else {
14057 // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
14058 // See discussion in https://github.com/facebook/react/pull/6896
14059 // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
14060 domElement = ownerDocument.createElement(type);
14061 }
14062 } else {
14063 domElement = ownerDocument.createElementNS(namespaceURI, type);
14064 }
14065
14066 {
14067 if (namespaceURI === HTML_NAMESPACE) {
14068 if (!isCustomComponentTag && Object.prototype.toString.call(domElement) === '[object HTMLUnknownElement]' && !Object.prototype.hasOwnProperty.call(warnedUnknownTags, type)) {
14069 warnedUnknownTags[type] = true;
14070 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);
14071 }
14072 }
14073 }
14074
14075 return domElement;
14076}
14077
14078function createTextNode$1(text, rootContainerElement) {
14079 return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(text);
14080}
14081
14082function setInitialProperties$1(domElement, tag, rawProps, rootContainerElement) {
14083 var isCustomComponentTag = isCustomComponent(tag, rawProps);
14084 {
14085 validatePropertiesInDevelopment(tag, rawProps);
14086 if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
14087 warning_1(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName$2() || 'A component');
14088 didWarnShadyDOM = true;
14089 }
14090 }
14091
14092 // TODO: Make sure that we check isMounted before firing any of these events.
14093 var props = void 0;
14094 switch (tag) {
14095 case 'iframe':
14096 case 'object':
14097 trapBubbledEvent('topLoad', 'load', domElement);
14098 props = rawProps;
14099 break;
14100 case 'video':
14101 case 'audio':
14102 // Create listener for each media event
14103 for (var event in mediaEventTypes) {
14104 if (mediaEventTypes.hasOwnProperty(event)) {
14105 trapBubbledEvent(event, mediaEventTypes[event], domElement);
14106 }
14107 }
14108 props = rawProps;
14109 break;
14110 case 'source':
14111 trapBubbledEvent('topError', 'error', domElement);
14112 props = rawProps;
14113 break;
14114 case 'img':
14115 case 'image':
14116 case 'link':
14117 trapBubbledEvent('topError', 'error', domElement);
14118 trapBubbledEvent('topLoad', 'load', domElement);
14119 props = rawProps;
14120 break;
14121 case 'form':
14122 trapBubbledEvent('topReset', 'reset', domElement);
14123 trapBubbledEvent('topSubmit', 'submit', domElement);
14124 props = rawProps;
14125 break;
14126 case 'details':
14127 trapBubbledEvent('topToggle', 'toggle', domElement);
14128 props = rawProps;
14129 break;
14130 case 'input':
14131 initWrapperState(domElement, rawProps);
14132 props = getHostProps(domElement, rawProps);
14133 trapBubbledEvent('topInvalid', 'invalid', domElement);
14134 // For controlled components we always need to ensure we're listening
14135 // to onChange. Even if there is no listener.
14136 ensureListeningTo(rootContainerElement, 'onChange');
14137 break;
14138 case 'option':
14139 validateProps(domElement, rawProps);
14140 props = getHostProps$1(domElement, rawProps);
14141 break;
14142 case 'select':
14143 initWrapperState$1(domElement, rawProps);
14144 props = getHostProps$2(domElement, rawProps);
14145 trapBubbledEvent('topInvalid', 'invalid', domElement);
14146 // For controlled components we always need to ensure we're listening
14147 // to onChange. Even if there is no listener.
14148 ensureListeningTo(rootContainerElement, 'onChange');
14149 break;
14150 case 'textarea':
14151 initWrapperState$2(domElement, rawProps);
14152 props = getHostProps$3(domElement, rawProps);
14153 trapBubbledEvent('topInvalid', 'invalid', domElement);
14154 // For controlled components we always need to ensure we're listening
14155 // to onChange. Even if there is no listener.
14156 ensureListeningTo(rootContainerElement, 'onChange');
14157 break;
14158 default:
14159 props = rawProps;
14160 }
14161
14162 assertValidProps(tag, props, getStack);
14163
14164 setInitialDOMProperties(tag, domElement, rootContainerElement, props, isCustomComponentTag);
14165
14166 switch (tag) {
14167 case 'input':
14168 // TODO: Make sure we check if this is still unmounted or do any clean
14169 // up necessary since we never stop tracking anymore.
14170 track(domElement);
14171 postMountWrapper(domElement, rawProps);
14172 break;
14173 case 'textarea':
14174 // TODO: Make sure we check if this is still unmounted or do any clean
14175 // up necessary since we never stop tracking anymore.
14176 track(domElement);
14177 postMountWrapper$3(domElement, rawProps);
14178 break;
14179 case 'option':
14180 postMountWrapper$1(domElement, rawProps);
14181 break;
14182 case 'select':
14183 postMountWrapper$2(domElement, rawProps);
14184 break;
14185 default:
14186 if (typeof props.onClick === 'function') {
14187 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14188 trapClickOnNonInteractiveElement(domElement);
14189 }
14190 break;
14191 }
14192}
14193
14194// Calculate the diff between the two objects.
14195function diffProperties$1(domElement, tag, lastRawProps, nextRawProps, rootContainerElement) {
14196 {
14197 validatePropertiesInDevelopment(tag, nextRawProps);
14198 }
14199
14200 var updatePayload = null;
14201
14202 var lastProps = void 0;
14203 var nextProps = void 0;
14204 switch (tag) {
14205 case 'input':
14206 lastProps = getHostProps(domElement, lastRawProps);
14207 nextProps = getHostProps(domElement, nextRawProps);
14208 updatePayload = [];
14209 break;
14210 case 'option':
14211 lastProps = getHostProps$1(domElement, lastRawProps);
14212 nextProps = getHostProps$1(domElement, nextRawProps);
14213 updatePayload = [];
14214 break;
14215 case 'select':
14216 lastProps = getHostProps$2(domElement, lastRawProps);
14217 nextProps = getHostProps$2(domElement, nextRawProps);
14218 updatePayload = [];
14219 break;
14220 case 'textarea':
14221 lastProps = getHostProps$3(domElement, lastRawProps);
14222 nextProps = getHostProps$3(domElement, nextRawProps);
14223 updatePayload = [];
14224 break;
14225 default:
14226 lastProps = lastRawProps;
14227 nextProps = nextRawProps;
14228 if (typeof lastProps.onClick !== 'function' && typeof nextProps.onClick === 'function') {
14229 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14230 trapClickOnNonInteractiveElement(domElement);
14231 }
14232 break;
14233 }
14234
14235 assertValidProps(tag, nextProps, getStack);
14236
14237 var propKey = void 0;
14238 var styleName = void 0;
14239 var styleUpdates = null;
14240 for (propKey in lastProps) {
14241 if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
14242 continue;
14243 }
14244 if (propKey === STYLE) {
14245 var lastStyle = lastProps[propKey];
14246 for (styleName in lastStyle) {
14247 if (lastStyle.hasOwnProperty(styleName)) {
14248 if (!styleUpdates) {
14249 styleUpdates = {};
14250 }
14251 styleUpdates[styleName] = '';
14252 }
14253 }
14254 } else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN) {
14255 // Noop. This is handled by the clear text mechanism.
14256 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
14257 // Noop
14258 } else if (propKey === AUTOFOCUS) {
14259 // Noop. It doesn't work on updates anyway.
14260 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14261 // This is a special case. If any listener updates we need to ensure
14262 // that the "current" fiber pointer gets updated so we need a commit
14263 // to update this element.
14264 if (!updatePayload) {
14265 updatePayload = [];
14266 }
14267 } else {
14268 // For all other deleted properties we add it to the queue. We use
14269 // the whitelist in the commit phase instead.
14270 (updatePayload = updatePayload || []).push(propKey, null);
14271 }
14272 }
14273 for (propKey in nextProps) {
14274 var nextProp = nextProps[propKey];
14275 var lastProp = lastProps != null ? lastProps[propKey] : undefined;
14276 if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
14277 continue;
14278 }
14279 if (propKey === STYLE) {
14280 {
14281 if (nextProp) {
14282 // Freeze the next style object so that we can assume it won't be
14283 // mutated. We have already warned for this in the past.
14284 Object.freeze(nextProp);
14285 }
14286 }
14287 if (lastProp) {
14288 // Unset styles on `lastProp` but not on `nextProp`.
14289 for (styleName in lastProp) {
14290 if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
14291 if (!styleUpdates) {
14292 styleUpdates = {};
14293 }
14294 styleUpdates[styleName] = '';
14295 }
14296 }
14297 // Update styles that changed since `lastProp`.
14298 for (styleName in nextProp) {
14299 if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {
14300 if (!styleUpdates) {
14301 styleUpdates = {};
14302 }
14303 styleUpdates[styleName] = nextProp[styleName];
14304 }
14305 }
14306 } else {
14307 // Relies on `updateStylesByID` not mutating `styleUpdates`.
14308 if (!styleUpdates) {
14309 if (!updatePayload) {
14310 updatePayload = [];
14311 }
14312 updatePayload.push(propKey, styleUpdates);
14313 }
14314 styleUpdates = nextProp;
14315 }
14316 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14317 var nextHtml = nextProp ? nextProp[HTML] : undefined;
14318 var lastHtml = lastProp ? lastProp[HTML] : undefined;
14319 if (nextHtml != null) {
14320 if (lastHtml !== nextHtml) {
14321 (updatePayload = updatePayload || []).push(propKey, '' + nextHtml);
14322 }
14323 } else {
14324 // TODO: It might be too late to clear this if we have children
14325 // inserted already.
14326 }
14327 } else if (propKey === CHILDREN) {
14328 if (lastProp !== nextProp && (typeof nextProp === 'string' || typeof nextProp === 'number')) {
14329 (updatePayload = updatePayload || []).push(propKey, '' + nextProp);
14330 }
14331 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1) {
14332 // Noop
14333 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14334 if (nextProp != null) {
14335 // We eagerly listen to this even though we haven't committed yet.
14336 if (true && typeof nextProp !== 'function') {
14337 warnForInvalidEventListener(propKey, nextProp);
14338 }
14339 ensureListeningTo(rootContainerElement, propKey);
14340 }
14341 if (!updatePayload && lastProp !== nextProp) {
14342 // This is a special case. If any listener updates we need to ensure
14343 // that the "current" props pointer gets updated so we need a commit
14344 // to update this element.
14345 updatePayload = [];
14346 }
14347 } else {
14348 // For any other property we always add it to the queue and then we
14349 // filter it out using the whitelist during the commit.
14350 (updatePayload = updatePayload || []).push(propKey, nextProp);
14351 }
14352 }
14353 if (styleUpdates) {
14354 (updatePayload = updatePayload || []).push(STYLE, styleUpdates);
14355 }
14356 return updatePayload;
14357}
14358
14359// Apply the diff.
14360function updateProperties$1(domElement, updatePayload, tag, lastRawProps, nextRawProps) {
14361 // Update checked *before* name.
14362 // In the middle of an update, it is possible to have multiple checked.
14363 // When a checked radio tries to change name, browser makes another radio's checked false.
14364 if (tag === 'input' && nextRawProps.type === 'radio' && nextRawProps.name != null) {
14365 updateChecked(domElement, nextRawProps);
14366 }
14367
14368 var wasCustomComponentTag = isCustomComponent(tag, lastRawProps);
14369 var isCustomComponentTag = isCustomComponent(tag, nextRawProps);
14370 // Apply the diff.
14371 updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag);
14372
14373 // TODO: Ensure that an update gets scheduled if any of the special props
14374 // changed.
14375 switch (tag) {
14376 case 'input':
14377 // Update the wrapper around inputs *after* updating props. This has to
14378 // happen after `updateDOMProperties`. Otherwise HTML5 input validations
14379 // raise warnings and prevent the new value from being assigned.
14380 updateWrapper(domElement, nextRawProps);
14381 break;
14382 case 'textarea':
14383 updateWrapper$1(domElement, nextRawProps);
14384 break;
14385 case 'select':
14386 // <select> value update needs to occur after <option> children
14387 // reconciliation
14388 postUpdateWrapper(domElement, nextRawProps);
14389 break;
14390 }
14391}
14392
14393function getPossibleStandardName(propName) {
14394 {
14395 var lowerCasedName = propName.toLowerCase();
14396 if (!possibleStandardNames.hasOwnProperty(lowerCasedName)) {
14397 return null;
14398 }
14399 return possibleStandardNames[lowerCasedName] || null;
14400 }
14401 return null;
14402}
14403
14404function diffHydratedProperties$1(domElement, tag, rawProps, parentNamespace, rootContainerElement) {
14405 var isCustomComponentTag = void 0;
14406 var extraAttributeNames = void 0;
14407
14408 {
14409 suppressHydrationWarning = rawProps[SUPPRESS_HYDRATION_WARNING$1] === true;
14410 isCustomComponentTag = isCustomComponent(tag, rawProps);
14411 validatePropertiesInDevelopment(tag, rawProps);
14412 if (isCustomComponentTag && !didWarnShadyDOM && domElement.shadyRoot) {
14413 warning_1(false, '%s is using shady DOM. Using shady DOM with React can ' + 'cause things to break subtly.', getCurrentFiberOwnerName$2() || 'A component');
14414 didWarnShadyDOM = true;
14415 }
14416 }
14417
14418 // TODO: Make sure that we check isMounted before firing any of these events.
14419 switch (tag) {
14420 case 'iframe':
14421 case 'object':
14422 trapBubbledEvent('topLoad', 'load', domElement);
14423 break;
14424 case 'video':
14425 case 'audio':
14426 // Create listener for each media event
14427 for (var event in mediaEventTypes) {
14428 if (mediaEventTypes.hasOwnProperty(event)) {
14429 trapBubbledEvent(event, mediaEventTypes[event], domElement);
14430 }
14431 }
14432 break;
14433 case 'source':
14434 trapBubbledEvent('topError', 'error', domElement);
14435 break;
14436 case 'img':
14437 case 'image':
14438 case 'link':
14439 trapBubbledEvent('topError', 'error', domElement);
14440 trapBubbledEvent('topLoad', 'load', domElement);
14441 break;
14442 case 'form':
14443 trapBubbledEvent('topReset', 'reset', domElement);
14444 trapBubbledEvent('topSubmit', 'submit', domElement);
14445 break;
14446 case 'details':
14447 trapBubbledEvent('topToggle', 'toggle', domElement);
14448 break;
14449 case 'input':
14450 initWrapperState(domElement, rawProps);
14451 trapBubbledEvent('topInvalid', 'invalid', domElement);
14452 // For controlled components we always need to ensure we're listening
14453 // to onChange. Even if there is no listener.
14454 ensureListeningTo(rootContainerElement, 'onChange');
14455 break;
14456 case 'option':
14457 validateProps(domElement, rawProps);
14458 break;
14459 case 'select':
14460 initWrapperState$1(domElement, rawProps);
14461 trapBubbledEvent('topInvalid', 'invalid', domElement);
14462 // For controlled components we always need to ensure we're listening
14463 // to onChange. Even if there is no listener.
14464 ensureListeningTo(rootContainerElement, 'onChange');
14465 break;
14466 case 'textarea':
14467 initWrapperState$2(domElement, rawProps);
14468 trapBubbledEvent('topInvalid', 'invalid', domElement);
14469 // For controlled components we always need to ensure we're listening
14470 // to onChange. Even if there is no listener.
14471 ensureListeningTo(rootContainerElement, 'onChange');
14472 break;
14473 }
14474
14475 assertValidProps(tag, rawProps, getStack);
14476
14477 {
14478 extraAttributeNames = new Set();
14479 var attributes = domElement.attributes;
14480 for (var i = 0; i < attributes.length; i++) {
14481 var name = attributes[i].name.toLowerCase();
14482 switch (name) {
14483 // Built-in SSR attribute is whitelisted
14484 case 'data-reactroot':
14485 break;
14486 // Controlled attributes are not validated
14487 // TODO: Only ignore them on controlled tags.
14488 case 'value':
14489 break;
14490 case 'checked':
14491 break;
14492 case 'selected':
14493 break;
14494 default:
14495 // Intentionally use the original name.
14496 // See discussion in https://github.com/facebook/react/pull/10676.
14497 extraAttributeNames.add(attributes[i].name);
14498 }
14499 }
14500 }
14501
14502 var updatePayload = null;
14503 for (var propKey in rawProps) {
14504 if (!rawProps.hasOwnProperty(propKey)) {
14505 continue;
14506 }
14507 var nextProp = rawProps[propKey];
14508 if (propKey === CHILDREN) {
14509 // For text content children we compare against textContent. This
14510 // might match additional HTML that is hidden when we read it using
14511 // textContent. E.g. "foo" will match "f<span>oo</span>" but that still
14512 // satisfies our requirement. Our requirement is not to produce perfect
14513 // HTML and attributes. Ideally we should preserve structure but it's
14514 // ok not to if the visible content is still enough to indicate what
14515 // even listeners these nodes might be wired up to.
14516 // TODO: Warn if there is more than a single textNode as a child.
14517 // TODO: Should we use domElement.firstChild.nodeValue to compare?
14518 if (typeof nextProp === 'string') {
14519 if (domElement.textContent !== nextProp) {
14520 if (true && !suppressHydrationWarning) {
14521 warnForTextDifference(domElement.textContent, nextProp);
14522 }
14523 updatePayload = [CHILDREN, nextProp];
14524 }
14525 } else if (typeof nextProp === 'number') {
14526 if (domElement.textContent !== '' + nextProp) {
14527 if (true && !suppressHydrationWarning) {
14528 warnForTextDifference(domElement.textContent, nextProp);
14529 }
14530 updatePayload = [CHILDREN, '' + nextProp];
14531 }
14532 }
14533 } else if (registrationNameModules.hasOwnProperty(propKey)) {
14534 if (nextProp != null) {
14535 if (true && typeof nextProp !== 'function') {
14536 warnForInvalidEventListener(propKey, nextProp);
14537 }
14538 ensureListeningTo(rootContainerElement, propKey);
14539 }
14540 } else if (true &&
14541 // Convince Flow we've calculated it (it's DEV-only in this method.)
14542 typeof isCustomComponentTag === 'boolean') {
14543 // Validate that the properties correspond to their expected values.
14544 var serverValue = void 0;
14545 var propertyInfo = getPropertyInfo(propKey);
14546 if (suppressHydrationWarning) {
14547 // Don't bother comparing. We're ignoring all these warnings.
14548 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING$1 ||
14549 // Controlled attributes are not validated
14550 // TODO: Only ignore them on controlled tags.
14551 propKey === 'value' || propKey === 'checked' || propKey === 'selected') {
14552 // Noop
14553 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
14554 var rawHtml = nextProp ? nextProp[HTML] || '' : '';
14555 var serverHTML = domElement.innerHTML;
14556 var expectedHTML = normalizeHTML(domElement, rawHtml);
14557 if (expectedHTML !== serverHTML) {
14558 warnForPropDifference(propKey, serverHTML, expectedHTML);
14559 }
14560 } else if (propKey === STYLE) {
14561 // $FlowFixMe - Should be inferred as not undefined.
14562 extraAttributeNames['delete'](propKey);
14563 var expectedStyle = createDangerousStringForStyles(nextProp);
14564 serverValue = domElement.getAttribute('style');
14565 if (expectedStyle !== serverValue) {
14566 warnForPropDifference(propKey, serverValue, expectedStyle);
14567 }
14568 } else if (isCustomComponentTag) {
14569 // $FlowFixMe - Should be inferred as not undefined.
14570 extraAttributeNames['delete'](propKey.toLowerCase());
14571 serverValue = getValueForAttribute(domElement, propKey, nextProp);
14572
14573 if (nextProp !== serverValue) {
14574 warnForPropDifference(propKey, serverValue, nextProp);
14575 }
14576 } else if (!shouldIgnoreAttribute(propKey, propertyInfo, isCustomComponentTag) && !shouldRemoveAttribute(propKey, nextProp, propertyInfo, isCustomComponentTag)) {
14577 var isMismatchDueToBadCasing = false;
14578 if (propertyInfo !== null) {
14579 // $FlowFixMe - Should be inferred as not undefined.
14580 extraAttributeNames['delete'](propertyInfo.attributeName);
14581 serverValue = getValueForProperty(domElement, propKey, nextProp, propertyInfo);
14582 } else {
14583 var ownNamespace = parentNamespace;
14584 if (ownNamespace === HTML_NAMESPACE) {
14585 ownNamespace = getIntrinsicNamespace(tag);
14586 }
14587 if (ownNamespace === HTML_NAMESPACE) {
14588 // $FlowFixMe - Should be inferred as not undefined.
14589 extraAttributeNames['delete'](propKey.toLowerCase());
14590 } else {
14591 var standardName = getPossibleStandardName(propKey);
14592 if (standardName !== null && standardName !== propKey) {
14593 // If an SVG prop is supplied with bad casing, it will
14594 // be successfully parsed from HTML, but will produce a mismatch
14595 // (and would be incorrectly rendered on the client).
14596 // However, we already warn about bad casing elsewhere.
14597 // So we'll skip the misleading extra mismatch warning in this case.
14598 isMismatchDueToBadCasing = true;
14599 // $FlowFixMe - Should be inferred as not undefined.
14600 extraAttributeNames['delete'](standardName);
14601 }
14602 // $FlowFixMe - Should be inferred as not undefined.
14603 extraAttributeNames['delete'](propKey);
14604 }
14605 serverValue = getValueForAttribute(domElement, propKey, nextProp);
14606 }
14607
14608 if (nextProp !== serverValue && !isMismatchDueToBadCasing) {
14609 warnForPropDifference(propKey, serverValue, nextProp);
14610 }
14611 }
14612 }
14613 }
14614
14615 {
14616 // $FlowFixMe - Should be inferred as not undefined.
14617 if (extraAttributeNames.size > 0 && !suppressHydrationWarning) {
14618 // $FlowFixMe - Should be inferred as not undefined.
14619 warnForExtraAttributes(extraAttributeNames);
14620 }
14621 }
14622
14623 switch (tag) {
14624 case 'input':
14625 // TODO: Make sure we check if this is still unmounted or do any clean
14626 // up necessary since we never stop tracking anymore.
14627 track(domElement);
14628 postMountWrapper(domElement, rawProps);
14629 break;
14630 case 'textarea':
14631 // TODO: Make sure we check if this is still unmounted or do any clean
14632 // up necessary since we never stop tracking anymore.
14633 track(domElement);
14634 postMountWrapper$3(domElement, rawProps);
14635 break;
14636 case 'select':
14637 case 'option':
14638 // For input and textarea we current always set the value property at
14639 // post mount to force it to diverge from attributes. However, for
14640 // option and select we don't quite do the same thing and select
14641 // is not resilient to the DOM state changing so we don't do that here.
14642 // TODO: Consider not doing this for input and textarea.
14643 break;
14644 default:
14645 if (typeof rawProps.onClick === 'function') {
14646 // TODO: This cast may not be sound for SVG, MathML or custom elements.
14647 trapClickOnNonInteractiveElement(domElement);
14648 }
14649 break;
14650 }
14651
14652 return updatePayload;
14653}
14654
14655function diffHydratedText$1(textNode, text) {
14656 var isDifferent = textNode.nodeValue !== text;
14657 return isDifferent;
14658}
14659
14660function warnForUnmatchedText$1(textNode, text) {
14661 {
14662 warnForTextDifference(textNode.nodeValue, text);
14663 }
14664}
14665
14666function warnForDeletedHydratableElement$1(parentNode, child) {
14667 {
14668 if (didWarnInvalidHydration) {
14669 return;
14670 }
14671 didWarnInvalidHydration = true;
14672 warning_1(false, 'Did not expect server HTML to contain a <%s> in <%s>.', child.nodeName.toLowerCase(), parentNode.nodeName.toLowerCase());
14673 }
14674}
14675
14676function warnForDeletedHydratableText$1(parentNode, child) {
14677 {
14678 if (didWarnInvalidHydration) {
14679 return;
14680 }
14681 didWarnInvalidHydration = true;
14682 warning_1(false, 'Did not expect server HTML to contain the text node "%s" in <%s>.', child.nodeValue, parentNode.nodeName.toLowerCase());
14683 }
14684}
14685
14686function warnForInsertedHydratedElement$1(parentNode, tag, props) {
14687 {
14688 if (didWarnInvalidHydration) {
14689 return;
14690 }
14691 didWarnInvalidHydration = true;
14692 warning_1(false, 'Expected server HTML to contain a matching <%s> in <%s>.', tag, parentNode.nodeName.toLowerCase());
14693 }
14694}
14695
14696function warnForInsertedHydratedText$1(parentNode, text) {
14697 {
14698 if (text === '') {
14699 // We expect to insert empty text nodes since they're not represented in
14700 // the HTML.
14701 // TODO: Remove this special case if we can just avoid inserting empty
14702 // text nodes.
14703 return;
14704 }
14705 if (didWarnInvalidHydration) {
14706 return;
14707 }
14708 didWarnInvalidHydration = true;
14709 warning_1(false, 'Expected server HTML to contain a matching text node for "%s" in <%s>.', text, parentNode.nodeName.toLowerCase());
14710 }
14711}
14712
14713function restoreControlledState$1(domElement, tag, props) {
14714 switch (tag) {
14715 case 'input':
14716 restoreControlledState(domElement, props);
14717 return;
14718 case 'textarea':
14719 restoreControlledState$3(domElement, props);
14720 return;
14721 case 'select':
14722 restoreControlledState$2(domElement, props);
14723 return;
14724 }
14725}
14726
14727var ReactDOMFiberComponent = Object.freeze({
14728 createElement: createElement$1,
14729 createTextNode: createTextNode$1,
14730 setInitialProperties: setInitialProperties$1,
14731 diffProperties: diffProperties$1,
14732 updateProperties: updateProperties$1,
14733 diffHydratedProperties: diffHydratedProperties$1,
14734 diffHydratedText: diffHydratedText$1,
14735 warnForUnmatchedText: warnForUnmatchedText$1,
14736 warnForDeletedHydratableElement: warnForDeletedHydratableElement$1,
14737 warnForDeletedHydratableText: warnForDeletedHydratableText$1,
14738 warnForInsertedHydratedElement: warnForInsertedHydratedElement$1,
14739 warnForInsertedHydratedText: warnForInsertedHydratedText$1,
14740 restoreControlledState: restoreControlledState$1
14741});
14742
14743// TODO: direct imports like some-package/src/* are bad. Fix me.
14744var getCurrentFiberStackAddendum$6 = ReactDebugCurrentFiber.getCurrentFiberStackAddendum;
14745
14746var validateDOMNesting = emptyFunction_1;
14747
14748{
14749 // This validation code was written based on the HTML5 parsing spec:
14750 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
14751 //
14752 // Note: this does not catch all invalid nesting, nor does it try to (as it's
14753 // not clear what practical benefit doing so provides); instead, we warn only
14754 // for cases where the parser will give a parse tree differing from what React
14755 // intended. For example, <b><div></div></b> is invalid but we don't warn
14756 // because it still parses correctly; we do warn for other cases like nested
14757 // <p> tags where the beginning of the second element implicitly closes the
14758 // first, causing a confusing mess.
14759
14760 // https://html.spec.whatwg.org/multipage/syntax.html#special
14761 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'];
14762
14763 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope
14764 var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',
14765
14766 // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point
14767 // TODO: Distinguish by namespace here -- for <title>, including it here
14768 // errs on the side of fewer warnings
14769 'foreignObject', 'desc', 'title'];
14770
14771 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope
14772 var buttonScopeTags = inScopeTags.concat(['button']);
14773
14774 // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags
14775 var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];
14776
14777 var emptyAncestorInfo = {
14778 current: null,
14779
14780 formTag: null,
14781 aTagInScope: null,
14782 buttonTagInScope: null,
14783 nobrTagInScope: null,
14784 pTagInButtonScope: null,
14785
14786 listItemTagAutoclosing: null,
14787 dlItemTagAutoclosing: null
14788 };
14789
14790 var updatedAncestorInfo$1 = function (oldInfo, tag, instance) {
14791 var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);
14792 var info = { tag: tag, instance: instance };
14793
14794 if (inScopeTags.indexOf(tag) !== -1) {
14795 ancestorInfo.aTagInScope = null;
14796 ancestorInfo.buttonTagInScope = null;
14797 ancestorInfo.nobrTagInScope = null;
14798 }
14799 if (buttonScopeTags.indexOf(tag) !== -1) {
14800 ancestorInfo.pTagInButtonScope = null;
14801 }
14802
14803 // See rules for 'li', 'dd', 'dt' start tags in
14804 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
14805 if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {
14806 ancestorInfo.listItemTagAutoclosing = null;
14807 ancestorInfo.dlItemTagAutoclosing = null;
14808 }
14809
14810 ancestorInfo.current = info;
14811
14812 if (tag === 'form') {
14813 ancestorInfo.formTag = info;
14814 }
14815 if (tag === 'a') {
14816 ancestorInfo.aTagInScope = info;
14817 }
14818 if (tag === 'button') {
14819 ancestorInfo.buttonTagInScope = info;
14820 }
14821 if (tag === 'nobr') {
14822 ancestorInfo.nobrTagInScope = info;
14823 }
14824 if (tag === 'p') {
14825 ancestorInfo.pTagInButtonScope = info;
14826 }
14827 if (tag === 'li') {
14828 ancestorInfo.listItemTagAutoclosing = info;
14829 }
14830 if (tag === 'dd' || tag === 'dt') {
14831 ancestorInfo.dlItemTagAutoclosing = info;
14832 }
14833
14834 return ancestorInfo;
14835 };
14836
14837 /**
14838 * Returns whether
14839 */
14840 var isTagValidWithParent = function (tag, parentTag) {
14841 // First, let's check if we're in an unusual parsing mode...
14842 switch (parentTag) {
14843 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
14844 case 'select':
14845 return tag === 'option' || tag === 'optgroup' || tag === '#text';
14846 case 'optgroup':
14847 return tag === 'option' || tag === '#text';
14848 // Strictly speaking, seeing an <option> doesn't mean we're in a <select>
14849 // but
14850 case 'option':
14851 return tag === '#text';
14852 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
14853 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
14854 // No special behavior since these rules fall back to "in body" mode for
14855 // all except special table nodes which cause bad parsing behavior anyway.
14856
14857 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
14858 case 'tr':
14859 return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';
14860 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
14861 case 'tbody':
14862 case 'thead':
14863 case 'tfoot':
14864 return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';
14865 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
14866 case 'colgroup':
14867 return tag === 'col' || tag === 'template';
14868 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
14869 case 'table':
14870 return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';
14871 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
14872 case 'head':
14873 return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';
14874 // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
14875 case 'html':
14876 return tag === 'head' || tag === 'body';
14877 case '#document':
14878 return tag === 'html';
14879 }
14880
14881 // Probably in the "in body" parsing mode, so we outlaw only tag combos
14882 // where the parsing rules cause implicit opens or closes to be added.
14883 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody
14884 switch (tag) {
14885 case 'h1':
14886 case 'h2':
14887 case 'h3':
14888 case 'h4':
14889 case 'h5':
14890 case 'h6':
14891 return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';
14892
14893 case 'rp':
14894 case 'rt':
14895 return impliedEndTags.indexOf(parentTag) === -1;
14896
14897 case 'body':
14898 case 'caption':
14899 case 'col':
14900 case 'colgroup':
14901 case 'frame':
14902 case 'head':
14903 case 'html':
14904 case 'tbody':
14905 case 'td':
14906 case 'tfoot':
14907 case 'th':
14908 case 'thead':
14909 case 'tr':
14910 // These tags are only valid with a few parents that have special child
14911 // parsing rules -- if we're down here, then none of those matched and
14912 // so we allow it only if we don't know what the parent is, as all other
14913 // cases are invalid.
14914 return parentTag == null;
14915 }
14916
14917 return true;
14918 };
14919
14920 /**
14921 * Returns whether
14922 */
14923 var findInvalidAncestorForTag = function (tag, ancestorInfo) {
14924 switch (tag) {
14925 case 'address':
14926 case 'article':
14927 case 'aside':
14928 case 'blockquote':
14929 case 'center':
14930 case 'details':
14931 case 'dialog':
14932 case 'dir':
14933 case 'div':
14934 case 'dl':
14935 case 'fieldset':
14936 case 'figcaption':
14937 case 'figure':
14938 case 'footer':
14939 case 'header':
14940 case 'hgroup':
14941 case 'main':
14942 case 'menu':
14943 case 'nav':
14944 case 'ol':
14945 case 'p':
14946 case 'section':
14947 case 'summary':
14948 case 'ul':
14949 case 'pre':
14950 case 'listing':
14951 case 'table':
14952 case 'hr':
14953 case 'xmp':
14954 case 'h1':
14955 case 'h2':
14956 case 'h3':
14957 case 'h4':
14958 case 'h5':
14959 case 'h6':
14960 return ancestorInfo.pTagInButtonScope;
14961
14962 case 'form':
14963 return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;
14964
14965 case 'li':
14966 return ancestorInfo.listItemTagAutoclosing;
14967
14968 case 'dd':
14969 case 'dt':
14970 return ancestorInfo.dlItemTagAutoclosing;
14971
14972 case 'button':
14973 return ancestorInfo.buttonTagInScope;
14974
14975 case 'a':
14976 // Spec says something about storing a list of markers, but it sounds
14977 // equivalent to this check.
14978 return ancestorInfo.aTagInScope;
14979
14980 case 'nobr':
14981 return ancestorInfo.nobrTagInScope;
14982 }
14983
14984 return null;
14985 };
14986
14987 var didWarn = {};
14988
14989 validateDOMNesting = function (childTag, childText, ancestorInfo) {
14990 ancestorInfo = ancestorInfo || emptyAncestorInfo;
14991 var parentInfo = ancestorInfo.current;
14992 var parentTag = parentInfo && parentInfo.tag;
14993
14994 if (childText != null) {
14995 warning_1(childTag == null, 'validateDOMNesting: when childText is passed, childTag should be null');
14996 childTag = '#text';
14997 }
14998
14999 var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;
15000 var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);
15001 var invalidParentOrAncestor = invalidParent || invalidAncestor;
15002 if (!invalidParentOrAncestor) {
15003 return;
15004 }
15005
15006 var ancestorTag = invalidParentOrAncestor.tag;
15007 var addendum = getCurrentFiberStackAddendum$6();
15008
15009 var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + addendum;
15010 if (didWarn[warnKey]) {
15011 return;
15012 }
15013 didWarn[warnKey] = true;
15014
15015 var tagDisplayName = childTag;
15016 var whitespaceInfo = '';
15017 if (childTag === '#text') {
15018 if (/\S/.test(childText)) {
15019 tagDisplayName = 'Text nodes';
15020 } else {
15021 tagDisplayName = 'Whitespace text nodes';
15022 whitespaceInfo = " Make sure you don't have any extra whitespace between tags on " + 'each line of your source code.';
15023 }
15024 } else {
15025 tagDisplayName = '<' + childTag + '>';
15026 }
15027
15028 if (invalidParent) {
15029 var info = '';
15030 if (ancestorTag === 'table' && childTag === 'tr') {
15031 info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';
15032 }
15033 warning_1(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>.%s%s%s', tagDisplayName, ancestorTag, whitespaceInfo, info, addendum);
15034 } else {
15035 warning_1(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>.%s', tagDisplayName, ancestorTag, addendum);
15036 }
15037 };
15038
15039 // TODO: turn this into a named export
15040 validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo$1;
15041}
15042
15043var validateDOMNesting$1 = validateDOMNesting;
15044
15045// TODO: This type is shared between the reconciler and ReactDOM, but will
15046// eventually be lifted out to the renderer.
15047
15048// TODO: direct imports like some-package/src/* are bad. Fix me.
15049var createElement = createElement$1;
15050var createTextNode = createTextNode$1;
15051var setInitialProperties = setInitialProperties$1;
15052var diffProperties = diffProperties$1;
15053var updateProperties = updateProperties$1;
15054var diffHydratedProperties = diffHydratedProperties$1;
15055var diffHydratedText = diffHydratedText$1;
15056var warnForUnmatchedText = warnForUnmatchedText$1;
15057var warnForDeletedHydratableElement = warnForDeletedHydratableElement$1;
15058var warnForDeletedHydratableText = warnForDeletedHydratableText$1;
15059var warnForInsertedHydratedElement = warnForInsertedHydratedElement$1;
15060var warnForInsertedHydratedText = warnForInsertedHydratedText$1;
15061var updatedAncestorInfo = validateDOMNesting$1.updatedAncestorInfo;
15062var precacheFiberNode = precacheFiberNode$1;
15063var updateFiberProps = updateFiberProps$1;
15064
15065
15066var SUPPRESS_HYDRATION_WARNING = void 0;
15067var topLevelUpdateWarnings = void 0;
15068var warnOnInvalidCallback = void 0;
15069var didWarnAboutUnstableCreatePortal = false;
15070
15071{
15072 SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
15073 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') {
15074 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');
15075 }
15076
15077 topLevelUpdateWarnings = function (container) {
15078 if (container._reactRootContainer && container.nodeType !== COMMENT_NODE) {
15079 var hostInstance = DOMRenderer.findHostInstanceWithNoPortals(container._reactRootContainer._internalRoot.current);
15080 if (hostInstance) {
15081 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.');
15082 }
15083 }
15084
15085 var isRootRenderedBySomeReact = !!container._reactRootContainer;
15086 var rootEl = getReactRootElementInContainer(container);
15087 var hasNonRootReactChild = !!(rootEl && getInstanceFromNode$1(rootEl));
15088
15089 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.');
15090
15091 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.');
15092 };
15093
15094 warnOnInvalidCallback = function (callback, callerName) {
15095 warning_1(callback === null || typeof callback === 'function', '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback);
15096 };
15097}
15098
15099injection$2.injectFiberControlledHostComponent(ReactDOMFiberComponent);
15100
15101var eventsEnabled = null;
15102var selectionInformation = null;
15103
15104function ReactBatch(root) {
15105 var expirationTime = DOMRenderer.computeUniqueAsyncExpiration();
15106 this._expirationTime = expirationTime;
15107 this._root = root;
15108 this._next = null;
15109 this._callbacks = null;
15110 this._didComplete = false;
15111 this._hasChildren = false;
15112 this._children = null;
15113 this._defer = true;
15114}
15115ReactBatch.prototype.render = function (children) {
15116 !this._defer ? invariant_1(false, 'batch.render: Cannot render a batch that already committed.') : void 0;
15117 this._hasChildren = true;
15118 this._children = children;
15119 var internalRoot = this._root._internalRoot;
15120 var expirationTime = this._expirationTime;
15121 var work = new ReactWork();
15122 DOMRenderer.updateContainerAtExpirationTime(children, internalRoot, null, expirationTime, work._onCommit);
15123 return work;
15124};
15125ReactBatch.prototype.then = function (onComplete) {
15126 if (this._didComplete) {
15127 onComplete();
15128 return;
15129 }
15130 var callbacks = this._callbacks;
15131 if (callbacks === null) {
15132 callbacks = this._callbacks = [];
15133 }
15134 callbacks.push(onComplete);
15135};
15136ReactBatch.prototype.commit = function () {
15137 var internalRoot = this._root._internalRoot;
15138 var firstBatch = internalRoot.firstBatch;
15139 !(this._defer && firstBatch !== null) ? invariant_1(false, 'batch.commit: Cannot commit a batch multiple times.') : void 0;
15140
15141 if (!this._hasChildren) {
15142 // This batch is empty. Return.
15143 this._next = null;
15144 this._defer = false;
15145 return;
15146 }
15147
15148 var expirationTime = this._expirationTime;
15149
15150 // Ensure this is the first batch in the list.
15151 if (firstBatch !== this) {
15152 // This batch is not the earliest batch. We need to move it to the front.
15153 // Update its expiration time to be the expiration time of the earliest
15154 // batch, so that we can flush it without flushing the other batches.
15155 if (this._hasChildren) {
15156 expirationTime = this._expirationTime = firstBatch._expirationTime;
15157 // Rendering this batch again ensures its children will be the final state
15158 // when we flush (updates are processed in insertion order: last
15159 // update wins).
15160 // TODO: This forces a restart. Should we print a warning?
15161 this.render(this._children);
15162 }
15163
15164 // Remove the batch from the list.
15165 var previous = null;
15166 var batch = firstBatch;
15167 while (batch !== this) {
15168 previous = batch;
15169 batch = batch._next;
15170 }
15171 !(previous !== null) ? invariant_1(false, 'batch.commit: Cannot commit a batch multiple times.') : void 0;
15172 previous._next = batch._next;
15173
15174 // Add it to the front.
15175 this._next = firstBatch;
15176 firstBatch = internalRoot.firstBatch = this;
15177 }
15178
15179 // Synchronously flush all the work up to this batch's expiration time.
15180 this._defer = false;
15181 DOMRenderer.flushRoot(internalRoot, expirationTime);
15182
15183 // Pop the batch from the list.
15184 var next = this._next;
15185 this._next = null;
15186 firstBatch = internalRoot.firstBatch = next;
15187
15188 // Append the next earliest batch's children to the update queue.
15189 if (firstBatch !== null && firstBatch._hasChildren) {
15190 firstBatch.render(firstBatch._children);
15191 }
15192};
15193ReactBatch.prototype._onComplete = function () {
15194 if (this._didComplete) {
15195 return;
15196 }
15197 this._didComplete = true;
15198 var callbacks = this._callbacks;
15199 if (callbacks === null) {
15200 return;
15201 }
15202 // TODO: Error handling.
15203 for (var i = 0; i < callbacks.length; i++) {
15204 var _callback = callbacks[i];
15205 _callback();
15206 }
15207};
15208
15209function ReactWork() {
15210 this._callbacks = null;
15211 this._didCommit = false;
15212 // TODO: Avoid need to bind by replacing callbacks in the update queue with
15213 // list of Work objects.
15214 this._onCommit = this._onCommit.bind(this);
15215}
15216ReactWork.prototype.then = function (onCommit) {
15217 if (this._didCommit) {
15218 onCommit();
15219 return;
15220 }
15221 var callbacks = this._callbacks;
15222 if (callbacks === null) {
15223 callbacks = this._callbacks = [];
15224 }
15225 callbacks.push(onCommit);
15226};
15227ReactWork.prototype._onCommit = function () {
15228 if (this._didCommit) {
15229 return;
15230 }
15231 this._didCommit = true;
15232 var callbacks = this._callbacks;
15233 if (callbacks === null) {
15234 return;
15235 }
15236 // TODO: Error handling.
15237 for (var i = 0; i < callbacks.length; i++) {
15238 var _callback2 = callbacks[i];
15239 !(typeof _callback2 === 'function') ? invariant_1(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback2) : void 0;
15240 _callback2();
15241 }
15242};
15243
15244function ReactRoot(container, isAsync, hydrate) {
15245 var root = DOMRenderer.createContainer(container, isAsync, hydrate);
15246 this._internalRoot = root;
15247}
15248ReactRoot.prototype.render = function (children, callback) {
15249 var root = this._internalRoot;
15250 var work = new ReactWork();
15251 callback = callback === undefined ? null : callback;
15252 {
15253 warnOnInvalidCallback(callback, 'render');
15254 }
15255 if (callback !== null) {
15256 work.then(callback);
15257 }
15258 DOMRenderer.updateContainer(children, root, null, work._onCommit);
15259 return work;
15260};
15261ReactRoot.prototype.unmount = function (callback) {
15262 var root = this._internalRoot;
15263 var work = new ReactWork();
15264 callback = callback === undefined ? null : callback;
15265 {
15266 warnOnInvalidCallback(callback, 'render');
15267 }
15268 if (callback !== null) {
15269 work.then(callback);
15270 }
15271 DOMRenderer.updateContainer(null, root, null, work._onCommit);
15272 return work;
15273};
15274ReactRoot.prototype.legacy_renderSubtreeIntoContainer = function (parentComponent, children, callback) {
15275 var root = this._internalRoot;
15276 var work = new ReactWork();
15277 callback = callback === undefined ? null : callback;
15278 {
15279 warnOnInvalidCallback(callback, 'render');
15280 }
15281 if (callback !== null) {
15282 work.then(callback);
15283 }
15284 DOMRenderer.updateContainer(children, root, parentComponent, work._onCommit);
15285 return work;
15286};
15287ReactRoot.prototype.createBatch = function () {
15288 var batch = new ReactBatch(this);
15289 var expirationTime = batch._expirationTime;
15290
15291 var internalRoot = this._internalRoot;
15292 var firstBatch = internalRoot.firstBatch;
15293 if (firstBatch === null) {
15294 internalRoot.firstBatch = batch;
15295 batch._next = null;
15296 } else {
15297 // Insert sorted by expiration time then insertion order
15298 var insertAfter = null;
15299 var insertBefore = firstBatch;
15300 while (insertBefore !== null && insertBefore._expirationTime <= expirationTime) {
15301 insertAfter = insertBefore;
15302 insertBefore = insertBefore._next;
15303 }
15304 batch._next = insertBefore;
15305 if (insertAfter !== null) {
15306 insertAfter._next = batch;
15307 }
15308 }
15309
15310 return batch;
15311};
15312
15313/**
15314 * True if the supplied DOM node is a valid node element.
15315 *
15316 * @param {?DOMElement} node The candidate DOM node.
15317 * @return {boolean} True if the DOM is a valid DOM node.
15318 * @internal
15319 */
15320function isValidContainer(node) {
15321 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 '));
15322}
15323
15324function getReactRootElementInContainer(container) {
15325 if (!container) {
15326 return null;
15327 }
15328
15329 if (container.nodeType === DOCUMENT_NODE) {
15330 return container.documentElement;
15331 } else {
15332 return container.firstChild;
15333 }
15334}
15335
15336function shouldHydrateDueToLegacyHeuristic(container) {
15337 var rootElement = getReactRootElementInContainer(container);
15338 return !!(rootElement && rootElement.nodeType === ELEMENT_NODE && rootElement.hasAttribute(ROOT_ATTRIBUTE_NAME));
15339}
15340
15341function shouldAutoFocusHostComponent(type, props) {
15342 switch (type) {
15343 case 'button':
15344 case 'input':
15345 case 'select':
15346 case 'textarea':
15347 return !!props.autoFocus;
15348 }
15349 return false;
15350}
15351
15352var DOMRenderer = reactReconciler({
15353 getRootHostContext: function (rootContainerInstance) {
15354 var type = void 0;
15355 var namespace = void 0;
15356 var nodeType = rootContainerInstance.nodeType;
15357 switch (nodeType) {
15358 case DOCUMENT_NODE:
15359 case DOCUMENT_FRAGMENT_NODE:
15360 {
15361 type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment';
15362 var root = rootContainerInstance.documentElement;
15363 namespace = root ? root.namespaceURI : getChildNamespace(null, '');
15364 break;
15365 }
15366 default:
15367 {
15368 var container = nodeType === COMMENT_NODE ? rootContainerInstance.parentNode : rootContainerInstance;
15369 var ownNamespace = container.namespaceURI || null;
15370 type = container.tagName;
15371 namespace = getChildNamespace(ownNamespace, type);
15372 break;
15373 }
15374 }
15375 {
15376 var validatedTag = type.toLowerCase();
15377 var _ancestorInfo = updatedAncestorInfo(null, validatedTag, null);
15378 return { namespace: namespace, ancestorInfo: _ancestorInfo };
15379 }
15380 return namespace;
15381 },
15382 getChildHostContext: function (parentHostContext, type) {
15383 {
15384 var parentHostContextDev = parentHostContext;
15385 var _namespace = getChildNamespace(parentHostContextDev.namespace, type);
15386 var _ancestorInfo2 = updatedAncestorInfo(parentHostContextDev.ancestorInfo, type, null);
15387 return { namespace: _namespace, ancestorInfo: _ancestorInfo2 };
15388 }
15389 var parentNamespace = parentHostContext;
15390 return getChildNamespace(parentNamespace, type);
15391 },
15392 getPublicInstance: function (instance) {
15393 return instance;
15394 },
15395 prepareForCommit: function () {
15396 eventsEnabled = isEnabled();
15397 selectionInformation = getSelectionInformation();
15398 setEnabled(false);
15399 },
15400 resetAfterCommit: function () {
15401 restoreSelection(selectionInformation);
15402 selectionInformation = null;
15403 setEnabled(eventsEnabled);
15404 eventsEnabled = null;
15405 },
15406 createInstance: function (type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
15407 var parentNamespace = void 0;
15408 {
15409 // TODO: take namespace into account when validating.
15410 var hostContextDev = hostContext;
15411 validateDOMNesting$1(type, null, hostContextDev.ancestorInfo);
15412 if (typeof props.children === 'string' || typeof props.children === 'number') {
15413 var string = '' + props.children;
15414 var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type, null);
15415 validateDOMNesting$1(null, string, ownAncestorInfo);
15416 }
15417 parentNamespace = hostContextDev.namespace;
15418 }
15419 var domElement = createElement(type, props, rootContainerInstance, parentNamespace);
15420 precacheFiberNode(internalInstanceHandle, domElement);
15421 updateFiberProps(domElement, props);
15422 return domElement;
15423 },
15424 appendInitialChild: function (parentInstance, child) {
15425 parentInstance.appendChild(child);
15426 },
15427 finalizeInitialChildren: function (domElement, type, props, rootContainerInstance) {
15428 setInitialProperties(domElement, type, props, rootContainerInstance);
15429 return shouldAutoFocusHostComponent(type, props);
15430 },
15431 prepareUpdate: function (domElement, type, oldProps, newProps, rootContainerInstance, hostContext) {
15432 {
15433 var hostContextDev = hostContext;
15434 if (typeof newProps.children !== typeof oldProps.children && (typeof newProps.children === 'string' || typeof newProps.children === 'number')) {
15435 var string = '' + newProps.children;
15436 var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type, null);
15437 validateDOMNesting$1(null, string, ownAncestorInfo);
15438 }
15439 }
15440 return diffProperties(domElement, type, oldProps, newProps, rootContainerInstance);
15441 },
15442 shouldSetTextContent: function (type, props) {
15443 return type === 'textarea' || typeof props.children === 'string' || typeof props.children === 'number' || typeof props.dangerouslySetInnerHTML === 'object' && props.dangerouslySetInnerHTML !== null && typeof props.dangerouslySetInnerHTML.__html === 'string';
15444 },
15445 shouldDeprioritizeSubtree: function (type, props) {
15446 return !!props.hidden;
15447 },
15448 createTextInstance: function (text, rootContainerInstance, hostContext, internalInstanceHandle) {
15449 {
15450 var hostContextDev = hostContext;
15451 validateDOMNesting$1(null, text, hostContextDev.ancestorInfo);
15452 }
15453 var textNode = createTextNode(text, rootContainerInstance);
15454 precacheFiberNode(internalInstanceHandle, textNode);
15455 return textNode;
15456 },
15457
15458
15459 now: now,
15460
15461 mutation: {
15462 commitMount: function (domElement, type, newProps, internalInstanceHandle) {
15463 // Despite the naming that might imply otherwise, this method only
15464 // fires if there is an `Update` effect scheduled during mounting.
15465 // This happens if `finalizeInitialChildren` returns `true` (which it
15466 // does to implement the `autoFocus` attribute on the client). But
15467 // there are also other cases when this might happen (such as patching
15468 // up text content during hydration mismatch). So we'll check this again.
15469 if (shouldAutoFocusHostComponent(type, newProps)) {
15470 domElement.focus();
15471 }
15472 },
15473 commitUpdate: function (domElement, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
15474 // Update the props handle so that we know which props are the ones with
15475 // with current event handlers.
15476 updateFiberProps(domElement, newProps);
15477 // Apply the diff to the DOM node.
15478 updateProperties(domElement, updatePayload, type, oldProps, newProps);
15479 },
15480 resetTextContent: function (domElement) {
15481 setTextContent(domElement, '');
15482 },
15483 commitTextUpdate: function (textInstance, oldText, newText) {
15484 textInstance.nodeValue = newText;
15485 },
15486 appendChild: function (parentInstance, child) {
15487 parentInstance.appendChild(child);
15488 },
15489 appendChildToContainer: function (container, child) {
15490 if (container.nodeType === COMMENT_NODE) {
15491 container.parentNode.insertBefore(child, container);
15492 } else {
15493 container.appendChild(child);
15494 }
15495 },
15496 insertBefore: function (parentInstance, child, beforeChild) {
15497 parentInstance.insertBefore(child, beforeChild);
15498 },
15499 insertInContainerBefore: function (container, child, beforeChild) {
15500 if (container.nodeType === COMMENT_NODE) {
15501 container.parentNode.insertBefore(child, beforeChild);
15502 } else {
15503 container.insertBefore(child, beforeChild);
15504 }
15505 },
15506 removeChild: function (parentInstance, child) {
15507 parentInstance.removeChild(child);
15508 },
15509 removeChildFromContainer: function (container, child) {
15510 if (container.nodeType === COMMENT_NODE) {
15511 container.parentNode.removeChild(child);
15512 } else {
15513 container.removeChild(child);
15514 }
15515 }
15516 },
15517
15518 hydration: {
15519 canHydrateInstance: function (instance, type, props) {
15520 if (instance.nodeType !== ELEMENT_NODE || type.toLowerCase() !== instance.nodeName.toLowerCase()) {
15521 return null;
15522 }
15523 // This has now been refined to an element node.
15524 return instance;
15525 },
15526 canHydrateTextInstance: function (instance, text) {
15527 if (text === '' || instance.nodeType !== TEXT_NODE) {
15528 // Empty strings are not parsed by HTML so there won't be a correct match here.
15529 return null;
15530 }
15531 // This has now been refined to a text node.
15532 return instance;
15533 },
15534 getNextHydratableSibling: function (instance) {
15535 var node = instance.nextSibling;
15536 // Skip non-hydratable nodes.
15537 while (node && node.nodeType !== ELEMENT_NODE && node.nodeType !== TEXT_NODE) {
15538 node = node.nextSibling;
15539 }
15540 return node;
15541 },
15542 getFirstHydratableChild: function (parentInstance) {
15543 var next = parentInstance.firstChild;
15544 // Skip non-hydratable nodes.
15545 while (next && next.nodeType !== ELEMENT_NODE && next.nodeType !== TEXT_NODE) {
15546 next = next.nextSibling;
15547 }
15548 return next;
15549 },
15550 hydrateInstance: function (instance, type, props, rootContainerInstance, hostContext, internalInstanceHandle) {
15551 precacheFiberNode(internalInstanceHandle, instance);
15552 // TODO: Possibly defer this until the commit phase where all the events
15553 // get attached.
15554 updateFiberProps(instance, props);
15555 var parentNamespace = void 0;
15556 {
15557 var hostContextDev = hostContext;
15558 parentNamespace = hostContextDev.namespace;
15559 }
15560 return diffHydratedProperties(instance, type, props, parentNamespace, rootContainerInstance);
15561 },
15562 hydrateTextInstance: function (textInstance, text, internalInstanceHandle) {
15563 precacheFiberNode(internalInstanceHandle, textInstance);
15564 return diffHydratedText(textInstance, text);
15565 },
15566 didNotMatchHydratedContainerTextInstance: function (parentContainer, textInstance, text) {
15567 {
15568 warnForUnmatchedText(textInstance, text);
15569 }
15570 },
15571 didNotMatchHydratedTextInstance: function (parentType, parentProps, parentInstance, textInstance, text) {
15572 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15573 warnForUnmatchedText(textInstance, text);
15574 }
15575 },
15576 didNotHydrateContainerInstance: function (parentContainer, instance) {
15577 {
15578 if (instance.nodeType === 1) {
15579 warnForDeletedHydratableElement(parentContainer, instance);
15580 } else {
15581 warnForDeletedHydratableText(parentContainer, instance);
15582 }
15583 }
15584 },
15585 didNotHydrateInstance: function (parentType, parentProps, parentInstance, instance) {
15586 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15587 if (instance.nodeType === 1) {
15588 warnForDeletedHydratableElement(parentInstance, instance);
15589 } else {
15590 warnForDeletedHydratableText(parentInstance, instance);
15591 }
15592 }
15593 },
15594 didNotFindHydratableContainerInstance: function (parentContainer, type, props) {
15595 {
15596 warnForInsertedHydratedElement(parentContainer, type, props);
15597 }
15598 },
15599 didNotFindHydratableContainerTextInstance: function (parentContainer, text) {
15600 {
15601 warnForInsertedHydratedText(parentContainer, text);
15602 }
15603 },
15604 didNotFindHydratableInstance: function (parentType, parentProps, parentInstance, type, props) {
15605 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15606 warnForInsertedHydratedElement(parentInstance, type, props);
15607 }
15608 },
15609 didNotFindHydratableTextInstance: function (parentType, parentProps, parentInstance, text) {
15610 if (true && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
15611 warnForInsertedHydratedText(parentInstance, text);
15612 }
15613 }
15614 },
15615
15616 scheduleDeferredCallback: rIC,
15617 cancelDeferredCallback: cIC
15618});
15619
15620injection$3.injectFiberBatchedUpdates(DOMRenderer.batchedUpdates);
15621
15622var warnedAboutHydrateAPI = false;
15623
15624function legacyCreateRootFromDOMContainer(container, forceHydrate) {
15625 var shouldHydrate = forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
15626 // First clear any existing content.
15627 if (!shouldHydrate) {
15628 var warned = false;
15629 var rootSibling = void 0;
15630 while (rootSibling = container.lastChild) {
15631 {
15632 if (!warned && rootSibling.nodeType === ELEMENT_NODE && rootSibling.hasAttribute(ROOT_ATTRIBUTE_NAME)) {
15633 warned = true;
15634 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.');
15635 }
15636 }
15637 container.removeChild(rootSibling);
15638 }
15639 }
15640 {
15641 if (shouldHydrate && !forceHydrate && !warnedAboutHydrateAPI) {
15642 warnedAboutHydrateAPI = true;
15643 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.');
15644 }
15645 }
15646 // Legacy roots are not async by default.
15647 var isAsync = false;
15648 return new ReactRoot(container, isAsync, shouldHydrate);
15649}
15650
15651function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {
15652 // TODO: Ensure all entry points contain this check
15653 !isValidContainer(container) ? invariant_1(false, 'Target container is not a DOM element.') : void 0;
15654
15655 {
15656 topLevelUpdateWarnings(container);
15657 }
15658
15659 // TODO: Without `any` type, Flow says "Property cannot be accessed on any
15660 // member of intersection type." Whyyyyyy.
15661 var root = container._reactRootContainer;
15662 if (!root) {
15663 // Initial mount
15664 root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate);
15665 if (typeof callback === 'function') {
15666 var originalCallback = callback;
15667 callback = function () {
15668 var instance = DOMRenderer.getPublicRootInstance(root._internalRoot);
15669 originalCallback.call(instance);
15670 };
15671 }
15672 // Initial mount should not be batched.
15673 DOMRenderer.unbatchedUpdates(function () {
15674 if (parentComponent != null) {
15675 root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
15676 } else {
15677 root.render(children, callback);
15678 }
15679 });
15680 } else {
15681 if (typeof callback === 'function') {
15682 var _originalCallback = callback;
15683 callback = function () {
15684 var instance = DOMRenderer.getPublicRootInstance(root._internalRoot);
15685 _originalCallback.call(instance);
15686 };
15687 }
15688 // Update
15689 if (parentComponent != null) {
15690 root.legacy_renderSubtreeIntoContainer(parentComponent, children, callback);
15691 } else {
15692 root.render(children, callback);
15693 }
15694 }
15695 return DOMRenderer.getPublicRootInstance(root._internalRoot);
15696}
15697
15698function createPortal(children, container) {
15699 var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
15700
15701 !isValidContainer(container) ? invariant_1(false, 'Target container is not a DOM element.') : void 0;
15702 // TODO: pass ReactDOM portal implementation as third argument
15703 return createPortal$1(children, container, null, key);
15704}
15705
15706var ReactDOM = {
15707 createPortal: createPortal,
15708
15709 findDOMNode: function (componentOrElement) {
15710 {
15711 var owner = ReactCurrentOwner.current;
15712 if (owner !== null) {
15713 var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender;
15714 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');
15715 owner.stateNode._warnedAboutRefsInRender = true;
15716 }
15717 }
15718 if (componentOrElement == null) {
15719 return null;
15720 }
15721 if (componentOrElement.nodeType === ELEMENT_NODE) {
15722 return componentOrElement;
15723 }
15724
15725 var inst = get(componentOrElement);
15726 if (inst) {
15727 return DOMRenderer.findHostInstance(inst);
15728 }
15729
15730 if (typeof componentOrElement.render === 'function') {
15731 invariant_1(false, 'Unable to find node on an unmounted component.');
15732 } else {
15733 invariant_1(false, 'Element appears to be neither ReactComponent nor DOMNode. Keys: %s', Object.keys(componentOrElement));
15734 }
15735 },
15736 hydrate: function (element, container, callback) {
15737 // TODO: throw or warn if we couldn't hydrate?
15738 return legacyRenderSubtreeIntoContainer(null, element, container, true, callback);
15739 },
15740 render: function (element, container, callback) {
15741 return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
15742 },
15743 unstable_renderSubtreeIntoContainer: function (parentComponent, element, containerNode, callback) {
15744 !(parentComponent != null && has(parentComponent)) ? invariant_1(false, 'parentComponent must be a valid React Component') : void 0;
15745 return legacyRenderSubtreeIntoContainer(parentComponent, element, containerNode, false, callback);
15746 },
15747 unmountComponentAtNode: function (container) {
15748 !isValidContainer(container) ? invariant_1(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : void 0;
15749
15750 if (container._reactRootContainer) {
15751 {
15752 var rootEl = getReactRootElementInContainer(container);
15753 var renderedByDifferentReact = rootEl && !getInstanceFromNode$1(rootEl);
15754 warning_1(!renderedByDifferentReact, "unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.');
15755 }
15756
15757 // Unmount should not be batched.
15758 DOMRenderer.unbatchedUpdates(function () {
15759 legacyRenderSubtreeIntoContainer(null, null, container, false, function () {
15760 container._reactRootContainer = null;
15761 });
15762 });
15763 // If you call unmountComponentAtNode twice in quick succession, you'll
15764 // get `true` twice. That's probably fine?
15765 return true;
15766 } else {
15767 {
15768 var _rootEl = getReactRootElementInContainer(container);
15769 var hasNonRootReactChild = !!(_rootEl && getInstanceFromNode$1(_rootEl));
15770
15771 // Check if the container itself is a React root node.
15772 var isContainerReactRoot = container.nodeType === 1 && isValidContainer(container.parentNode) && !!container.parentNode._reactRootContainer;
15773
15774 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.');
15775 }
15776
15777 return false;
15778 }
15779 },
15780
15781
15782 // Temporary alias since we already shipped React 16 RC with it.
15783 // TODO: remove in React 17.
15784 unstable_createPortal: function () {
15785 if (!didWarnAboutUnstableCreatePortal) {
15786 didWarnAboutUnstableCreatePortal = true;
15787 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.');
15788 }
15789 return createPortal.apply(undefined, arguments);
15790 },
15791
15792
15793 unstable_batchedUpdates: batchedUpdates,
15794
15795 unstable_deferredUpdates: DOMRenderer.deferredUpdates,
15796
15797 flushSync: DOMRenderer.flushSync,
15798
15799 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
15800 // For TapEventPlugin which is popular in open source
15801 EventPluginHub: EventPluginHub,
15802 // Used by test-utils
15803 EventPluginRegistry: EventPluginRegistry,
15804 EventPropagators: EventPropagators,
15805 ReactControlledComponent: ReactControlledComponent,
15806 ReactDOMComponentTree: ReactDOMComponentTree,
15807 ReactDOMEventListener: ReactDOMEventListener
15808 }
15809};
15810
15811{
15812 // Show deprecation warnings as we don't want to support injection forever.
15813 // We do it now to let the internal injection happen without warnings.
15814 // https://github.com/facebook/react/issues/11689
15815 enableWarningOnInjection();
15816}
15817
15818if (enableCreateRoot) {
15819 ReactDOM.createRoot = function createRoot(container, options) {
15820 var hydrate = options != null && options.hydrate === true;
15821 return new ReactRoot(container, true, hydrate);
15822 };
15823}
15824
15825var foundDevTools = DOMRenderer.injectIntoDevTools({
15826 findFiberByHostInstance: getClosestInstanceFromNode,
15827 bundleType: 1,
15828 version: ReactVersion,
15829 rendererPackageName: 'react-dom'
15830});
15831
15832{
15833 if (!foundDevTools && ExecutionEnvironment_1.canUseDOM && window.top === window.self) {
15834 // If we're in Chrome or Firefox, provide a download link if not installed.
15835 if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
15836 var protocol = window.location.protocol;
15837 // Don't warn in exotic cases like chrome-extension://.
15838 if (/^(https?|file):$/.test(protocol)) {
15839 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');
15840 }
15841 }
15842 }
15843}
15844
15845
15846
15847var ReactDOM$2 = Object.freeze({
15848 default: ReactDOM
15849});
15850
15851var ReactDOM$3 = ( ReactDOM$2 && ReactDOM ) || ReactDOM$2;
15852
15853// TODO: decide on the top-level export form.
15854// This is hacky but makes it work with both Rollup and Jest.
15855var reactDom = ReactDOM$3['default'] ? ReactDOM$3['default'] : ReactDOM$3;
15856
15857return reactDom;
15858
15859})));