[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 /** 2 * @license React 3 * react-dom.development.js 4 * 5 * Copyright (c) Facebook, Inc. and its affiliates. 6 * 7 * This source code is licensed under the MIT license found in the 8 * LICENSE file in the root directory of this source tree. 9 */ 10 (function (global, factory) { 11 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) : 12 typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) : 13 (global = global || self, factory(global.ReactDOM = {}, global.React)); 14 }(this, (function (exports, React) { 'use strict'; 15 16 var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; 17 18 var suppressWarning = false; 19 function setSuppressWarning(newSuppressWarning) { 20 { 21 suppressWarning = newSuppressWarning; 22 } 23 } // In DEV, calls to console.warn and console.error get replaced 24 // by calls to these methods by a Babel plugin. 25 // 26 // In PROD (or in packages without access to React internals), 27 // they are left as they are instead. 28 29 function warn(format) { 30 { 31 if (!suppressWarning) { 32 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 33 args[_key - 1] = arguments[_key]; 34 } 35 36 printWarning('warn', format, args); 37 } 38 } 39 } 40 function error(format) { 41 { 42 if (!suppressWarning) { 43 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { 44 args[_key2 - 1] = arguments[_key2]; 45 } 46 47 printWarning('error', format, args); 48 } 49 } 50 } 51 52 function printWarning(level, format, args) { 53 // When changing this logic, you might want to also 54 // update consoleWithStackDev.www.js as well. 55 { 56 var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; 57 var stack = ReactDebugCurrentFrame.getStackAddendum(); 58 59 if (stack !== '') { 60 format += '%s'; 61 args = args.concat([stack]); 62 } // eslint-disable-next-line react-internal/safe-string-coercion 63 64 65 var argsWithFormat = args.map(function (item) { 66 return String(item); 67 }); // Careful: RN currently depends on this prefix 68 69 argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it 70 // breaks IE9: https://github.com/facebook/react/issues/13610 71 // eslint-disable-next-line react-internal/no-production-logging 72 73 Function.prototype.apply.call(console[level], console, argsWithFormat); 74 } 75 } 76 77 var FunctionComponent = 0; 78 var ClassComponent = 1; 79 var IndeterminateComponent = 2; // Before we know whether it is function or class 80 81 var HostRoot = 3; // Root of a host tree. Could be nested inside another node. 82 83 var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. 84 85 var HostComponent = 5; 86 var HostText = 6; 87 var Fragment = 7; 88 var Mode = 8; 89 var ContextConsumer = 9; 90 var ContextProvider = 10; 91 var ForwardRef = 11; 92 var Profiler = 12; 93 var SuspenseComponent = 13; 94 var MemoComponent = 14; 95 var SimpleMemoComponent = 15; 96 var LazyComponent = 16; 97 var IncompleteClassComponent = 17; 98 var DehydratedFragment = 18; 99 var SuspenseListComponent = 19; 100 var ScopeComponent = 21; 101 var OffscreenComponent = 22; 102 var LegacyHiddenComponent = 23; 103 var CacheComponent = 24; 104 var TracingMarkerComponent = 25; 105 106 // ----------------------------------------------------------------------------- 107 108 var enableClientRenderFallbackOnTextMismatch = true; // TODO: Need to review this code one more time before landing 109 // the react-reconciler package. 110 111 var enableNewReconciler = false; // Support legacy Primer support on internal FB www 112 113 var enableLazyContextPropagation = false; // FB-only usage. The new API has different semantics. 114 115 var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber 116 117 var enableSuspenseAvoidThisFallback = false; // Enables unstable_avoidThisFallback feature in Fizz 118 // React DOM Chopping Block 119 // 120 // Similar to main Chopping Block but only flags related to React DOM. These are 121 // grouped because we will likely batch all of them into a single major release. 122 // ----------------------------------------------------------------------------- 123 // Disable support for comment nodes as React DOM containers. Already disabled 124 // in open source, but www codebase still relies on it. Need to remove. 125 126 var disableCommentsAsDOMContainers = true; // Disable javascript: URL strings in href for XSS protection. 127 // and client rendering, mostly to allow JSX attributes to apply to the custom 128 // element's object properties instead of only HTML attributes. 129 // https://github.com/facebook/react/issues/11347 130 131 var enableCustomElementPropertySupport = false; // Disables children for <textarea> elements 132 var warnAboutStringRefs = true; // ----------------------------------------------------------------------------- 133 // Debugging and DevTools 134 // ----------------------------------------------------------------------------- 135 // Adds user timing marks for e.g. state updates, suspense, and work loop stuff, 136 // for an experimental timeline tool. 137 138 var enableSchedulingProfiler = true; // Helps identify side effects in render-phase lifecycle hooks and setState 139 140 var enableProfilerTimer = true; // Record durations for commit and passive effects phases. 141 142 var enableProfilerCommitHooks = true; // Phase param passed to onRender callback differentiates between an "update" and a "cascading-update". 143 144 var allNativeEvents = new Set(); 145 /** 146 * Mapping from registration name to event name 147 */ 148 149 150 var registrationNameDependencies = {}; 151 /** 152 * Mapping from lowercase registration names to the properly cased version, 153 * used to warn in the case of missing event handlers. Available 154 * only in true. 155 * @type {Object} 156 */ 157 158 var possibleRegistrationNames = {} ; // Trust the developer to only use possibleRegistrationNames in true 159 160 function registerTwoPhaseEvent(registrationName, dependencies) { 161 registerDirectEvent(registrationName, dependencies); 162 registerDirectEvent(registrationName + 'Capture', dependencies); 163 } 164 function registerDirectEvent(registrationName, dependencies) { 165 { 166 if (registrationNameDependencies[registrationName]) { 167 error('EventRegistry: More than one plugin attempted to publish the same ' + 'registration name, `%s`.', registrationName); 168 } 169 } 170 171 registrationNameDependencies[registrationName] = dependencies; 172 173 { 174 var lowerCasedName = registrationName.toLowerCase(); 175 possibleRegistrationNames[lowerCasedName] = registrationName; 176 177 if (registrationName === 'onDoubleClick') { 178 possibleRegistrationNames.ondblclick = registrationName; 179 } 180 } 181 182 for (var i = 0; i < dependencies.length; i++) { 183 allNativeEvents.add(dependencies[i]); 184 } 185 } 186 187 var canUseDOM = !!(typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined'); 188 189 var hasOwnProperty = Object.prototype.hasOwnProperty; 190 191 /* 192 * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol 193 * and Temporal.* types. See https://github.com/facebook/react/pull/22064. 194 * 195 * The functions in this module will throw an easier-to-understand, 196 * easier-to-debug exception with a clear errors message message explaining the 197 * problem. (Instead of a confusing exception thrown inside the implementation 198 * of the `value` object). 199 */ 200 // $FlowFixMe only called in DEV, so void return is not possible. 201 function typeName(value) { 202 { 203 // toStringTag is needed for namespaced types like Temporal.Instant 204 var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag; 205 var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object'; 206 return type; 207 } 208 } // $FlowFixMe only called in DEV, so void return is not possible. 209 210 211 function willCoercionThrow(value) { 212 { 213 try { 214 testStringCoercion(value); 215 return false; 216 } catch (e) { 217 return true; 218 } 219 } 220 } 221 222 function testStringCoercion(value) { 223 // If you ended up here by following an exception call stack, here's what's 224 // happened: you supplied an object or symbol value to React (as a prop, key, 225 // DOM attribute, CSS property, string ref, etc.) and when React tried to 226 // coerce it to a string using `'' + value`, an exception was thrown. 227 // 228 // The most common types that will cause this exception are `Symbol` instances 229 // and Temporal objects like `Temporal.Instant`. But any object that has a 230 // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this 231 // exception. (Library authors do this to prevent users from using built-in 232 // numeric operators like `+` or comparison operators like `>=` because custom 233 // methods are needed to perform accurate arithmetic or comparison.) 234 // 235 // To fix the problem, coerce this object or symbol value to a string before 236 // passing it to React. The most reliable way is usually `String(value)`. 237 // 238 // To find which value is throwing, check the browser or debugger console. 239 // Before this exception was thrown, there should be `console.error` output 240 // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the 241 // problem and how that type was used: key, atrribute, input value prop, etc. 242 // In most cases, this console output also shows the component and its 243 // ancestor components where the exception happened. 244 // 245 // eslint-disable-next-line react-internal/safe-string-coercion 246 return '' + value; 247 } 248 249 function checkAttributeStringCoercion(value, attributeName) { 250 { 251 if (willCoercionThrow(value)) { 252 error('The provided `%s` attribute is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', attributeName, typeName(value)); 253 254 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 255 } 256 } 257 } 258 function checkKeyStringCoercion(value) { 259 { 260 if (willCoercionThrow(value)) { 261 error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 262 263 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 264 } 265 } 266 } 267 function checkPropStringCoercion(value, propName) { 268 { 269 if (willCoercionThrow(value)) { 270 error('The provided `%s` prop is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value)); 271 272 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 273 } 274 } 275 } 276 function checkCSSPropertyStringCoercion(value, propName) { 277 { 278 if (willCoercionThrow(value)) { 279 error('The provided `%s` CSS property is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value)); 280 281 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 282 } 283 } 284 } 285 function checkHtmlStringCoercion(value) { 286 { 287 if (willCoercionThrow(value)) { 288 error('The provided HTML markup uses a value of unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 289 290 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 291 } 292 } 293 } 294 function checkFormFieldValueStringCoercion(value) { 295 { 296 if (willCoercionThrow(value)) { 297 error('Form field values (value, checked, defaultValue, or defaultChecked props)' + ' must be strings, not %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 298 299 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 300 } 301 } 302 } 303 304 // A reserved attribute. 305 // It is handled by React separately and shouldn't be written to the DOM. 306 var RESERVED = 0; // A simple string attribute. 307 // Attributes that aren't in the filter are presumed to have this type. 308 309 var STRING = 1; // A string attribute that accepts booleans in React. In HTML, these are called 310 // "enumerated" attributes with "true" and "false" as possible values. 311 // When true, it should be set to a "true" string. 312 // When false, it should be set to a "false" string. 313 314 var BOOLEANISH_STRING = 2; // A real boolean attribute. 315 // When true, it should be present (set either to an empty string or its name). 316 // When false, it should be omitted. 317 318 var BOOLEAN = 3; // An attribute that can be used as a flag as well as with a value. 319 // When true, it should be present (set either to an empty string or its name). 320 // When false, it should be omitted. 321 // For any other value, should be present with that value. 322 323 var OVERLOADED_BOOLEAN = 4; // An attribute that must be numeric or parse as a numeric. 324 // When falsy, it should be removed. 325 326 var NUMERIC = 5; // An attribute that must be positive numeric or parse as a positive numeric. 327 // When falsy, it should be removed. 328 329 var POSITIVE_NUMERIC = 6; 330 331 /* eslint-disable max-len */ 332 var ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; 333 /* eslint-enable max-len */ 334 335 var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; 336 var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$'); 337 var illegalAttributeNameCache = {}; 338 var validatedAttributeNameCache = {}; 339 function isAttributeNameSafe(attributeName) { 340 if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { 341 return true; 342 } 343 344 if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { 345 return false; 346 } 347 348 if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { 349 validatedAttributeNameCache[attributeName] = true; 350 return true; 351 } 352 353 illegalAttributeNameCache[attributeName] = true; 354 355 { 356 error('Invalid attribute name: `%s`', attributeName); 357 } 358 359 return false; 360 } 361 function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) { 362 if (propertyInfo !== null) { 363 return propertyInfo.type === RESERVED; 364 } 365 366 if (isCustomComponentTag) { 367 return false; 368 } 369 370 if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) { 371 return true; 372 } 373 374 return false; 375 } 376 function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) { 377 if (propertyInfo !== null && propertyInfo.type === RESERVED) { 378 return false; 379 } 380 381 switch (typeof value) { 382 case 'function': // $FlowIssue symbol is perfectly valid here 383 384 case 'symbol': 385 // eslint-disable-line 386 return true; 387 388 case 'boolean': 389 { 390 if (isCustomComponentTag) { 391 return false; 392 } 393 394 if (propertyInfo !== null) { 395 return !propertyInfo.acceptsBooleans; 396 } else { 397 var prefix = name.toLowerCase().slice(0, 5); 398 return prefix !== 'data-' && prefix !== 'aria-'; 399 } 400 } 401 402 default: 403 return false; 404 } 405 } 406 function shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag) { 407 if (value === null || typeof value === 'undefined') { 408 return true; 409 } 410 411 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag)) { 412 return true; 413 } 414 415 if (isCustomComponentTag) { 416 417 return false; 418 } 419 420 if (propertyInfo !== null) { 421 422 switch (propertyInfo.type) { 423 case BOOLEAN: 424 return !value; 425 426 case OVERLOADED_BOOLEAN: 427 return value === false; 428 429 case NUMERIC: 430 return isNaN(value); 431 432 case POSITIVE_NUMERIC: 433 return isNaN(value) || value < 1; 434 } 435 } 436 437 return false; 438 } 439 function getPropertyInfo(name) { 440 return properties.hasOwnProperty(name) ? properties[name] : null; 441 } 442 443 function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace, sanitizeURL, removeEmptyString) { 444 this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN; 445 this.attributeName = attributeName; 446 this.attributeNamespace = attributeNamespace; 447 this.mustUseProperty = mustUseProperty; 448 this.propertyName = name; 449 this.type = type; 450 this.sanitizeURL = sanitizeURL; 451 this.removeEmptyString = removeEmptyString; 452 } // When adding attributes to this list, be sure to also add them to 453 // the `possibleStandardNames` module to ensure casing and incorrect 454 // name warnings. 455 456 457 var properties = {}; // These props are reserved by React. They shouldn't be written to the DOM. 458 459 var reservedProps = ['children', 'dangerouslySetInnerHTML', // TODO: This prevents the assignment of defaultValue to regular 460 // elements (not just inputs). Now that ReactDOMInput assigns to the 461 // defaultValue property -- do we need this? 462 'defaultValue', 'defaultChecked', 'innerHTML', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'style']; 463 464 reservedProps.forEach(function (name) { 465 properties[name] = new PropertyInfoRecord(name, RESERVED, false, // mustUseProperty 466 name, // attributeName 467 null, // attributeNamespace 468 false, // sanitizeURL 469 false); 470 }); // A few React string attributes have a different name. 471 // This is a mapping from React prop names to the attribute names. 472 473 [['acceptCharset', 'accept-charset'], ['className', 'class'], ['htmlFor', 'for'], ['httpEquiv', 'http-equiv']].forEach(function (_ref) { 474 var name = _ref[0], 475 attributeName = _ref[1]; 476 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 477 attributeName, // attributeName 478 null, // attributeNamespace 479 false, // sanitizeURL 480 false); 481 }); // These are "enumerated" HTML attributes that accept "true" and "false". 482 // In React, we let users pass `true` and `false` even though technically 483 // these aren't boolean attributes (they are coerced to strings). 484 485 ['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (name) { 486 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty 487 name.toLowerCase(), // attributeName 488 null, // attributeNamespace 489 false, // sanitizeURL 490 false); 491 }); // These are "enumerated" SVG attributes that accept "true" and "false". 492 // In React, we let users pass `true` and `false` even though technically 493 // these aren't boolean attributes (they are coerced to strings). 494 // Since these are SVG attributes, their attribute names are case-sensitive. 495 496 ['autoReverse', 'externalResourcesRequired', 'focusable', 'preserveAlpha'].forEach(function (name) { 497 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty 498 name, // attributeName 499 null, // attributeNamespace 500 false, // sanitizeURL 501 false); 502 }); // These are HTML boolean attributes. 503 504 ['allowFullScreen', 'async', // Note: there is a special case that prevents it from being written to the DOM 505 // on the client side because the browsers are inconsistent. Instead we call focus(). 506 'autoFocus', 'autoPlay', 'controls', 'default', 'defer', 'disabled', 'disablePictureInPicture', 'disableRemotePlayback', 'formNoValidate', 'hidden', 'loop', 'noModule', 'noValidate', 'open', 'playsInline', 'readOnly', 'required', 'reversed', 'scoped', 'seamless', // Microdata 507 'itemScope'].forEach(function (name) { 508 properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, // mustUseProperty 509 name.toLowerCase(), // attributeName 510 null, // attributeNamespace 511 false, // sanitizeURL 512 false); 513 }); // These are the few React props that we set as DOM properties 514 // rather than attributes. These are all booleans. 515 516 ['checked', // Note: `option.selected` is not updated if `select.multiple` is 517 // disabled with `removeAttribute`. We have special logic for handling this. 518 'multiple', 'muted', 'selected' // NOTE: if you add a camelCased prop to this list, 519 // you'll need to set attributeName to name.toLowerCase() 520 // instead in the assignment below. 521 ].forEach(function (name) { 522 properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, // mustUseProperty 523 name, // attributeName 524 null, // attributeNamespace 525 false, // sanitizeURL 526 false); 527 }); // These are HTML attributes that are "overloaded booleans": they behave like 528 // booleans, but can also accept a string value. 529 530 ['capture', 'download' // NOTE: if you add a camelCased prop to this list, 531 // you'll need to set attributeName to name.toLowerCase() 532 // instead in the assignment below. 533 ].forEach(function (name) { 534 properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, // mustUseProperty 535 name, // attributeName 536 null, // attributeNamespace 537 false, // sanitizeURL 538 false); 539 }); // These are HTML attributes that must be positive numbers. 540 541 ['cols', 'rows', 'size', 'span' // NOTE: if you add a camelCased prop to this list, 542 // you'll need to set attributeName to name.toLowerCase() 543 // instead in the assignment below. 544 ].forEach(function (name) { 545 properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, // mustUseProperty 546 name, // attributeName 547 null, // attributeNamespace 548 false, // sanitizeURL 549 false); 550 }); // These are HTML attributes that must be numbers. 551 552 ['rowSpan', 'start'].forEach(function (name) { 553 properties[name] = new PropertyInfoRecord(name, NUMERIC, false, // mustUseProperty 554 name.toLowerCase(), // attributeName 555 null, // attributeNamespace 556 false, // sanitizeURL 557 false); 558 }); 559 var CAMELIZE = /[\-\:]([a-z])/g; 560 561 var capitalize = function (token) { 562 return token[1].toUpperCase(); 563 }; // This is a list of all SVG attributes that need special casing, namespacing, 564 // or boolean value assignment. Regular attributes that just accept strings 565 // and have the same names are omitted, just like in the HTML attribute filter. 566 // Some of these attributes can be hard to find. This list was created by 567 // scraping the MDN documentation. 568 569 570 ['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' // NOTE: if you add a camelCased prop to this list, 571 // you'll need to set attributeName to name.toLowerCase() 572 // instead in the assignment below. 573 ].forEach(function (attributeName) { 574 var name = attributeName.replace(CAMELIZE, capitalize); 575 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 576 attributeName, null, // attributeNamespace 577 false, // sanitizeURL 578 false); 579 }); // String SVG attributes with the xlink namespace. 580 581 ['xlink:actuate', 'xlink:arcrole', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type' // NOTE: if you add a camelCased prop to this list, 582 // you'll need to set attributeName to name.toLowerCase() 583 // instead in the assignment below. 584 ].forEach(function (attributeName) { 585 var name = attributeName.replace(CAMELIZE, capitalize); 586 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 587 attributeName, 'http://www.w3.org/1999/xlink', false, // sanitizeURL 588 false); 589 }); // String SVG attributes with the xml namespace. 590 591 ['xml:base', 'xml:lang', 'xml:space' // NOTE: if you add a camelCased prop to this list, 592 // you'll need to set attributeName to name.toLowerCase() 593 // instead in the assignment below. 594 ].forEach(function (attributeName) { 595 var name = attributeName.replace(CAMELIZE, capitalize); 596 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 597 attributeName, 'http://www.w3.org/XML/1998/namespace', false, // sanitizeURL 598 false); 599 }); // These attribute exists both in HTML and SVG. 600 // The attribute name is case-sensitive in SVG so we can't just use 601 // the React name like we do for attributes that exist only in HTML. 602 603 ['tabIndex', 'crossOrigin'].forEach(function (attributeName) { 604 properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty 605 attributeName.toLowerCase(), // attributeName 606 null, // attributeNamespace 607 false, // sanitizeURL 608 false); 609 }); // These attributes accept URLs. These must not allow javascript: URLS. 610 // These will also need to accept Trusted Types object in the future. 611 612 var xlinkHref = 'xlinkHref'; 613 properties[xlinkHref] = new PropertyInfoRecord('xlinkHref', STRING, false, // mustUseProperty 614 'xlink:href', 'http://www.w3.org/1999/xlink', true, // sanitizeURL 615 false); 616 ['src', 'href', 'action', 'formAction'].forEach(function (attributeName) { 617 properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty 618 attributeName.toLowerCase(), // attributeName 619 null, // attributeNamespace 620 true, // sanitizeURL 621 true); 622 }); 623 624 // and any newline or tab are filtered out as if they're not part of the URL. 625 // https://url.spec.whatwg.org/#url-parsing 626 // Tab or newline are defined as \r\n\t: 627 // https://infra.spec.whatwg.org/#ascii-tab-or-newline 628 // A C0 control is a code point in the range \u0000 NULL to \u001F 629 // INFORMATION SEPARATOR ONE, inclusive: 630 // https://infra.spec.whatwg.org/#c0-control-or-space 631 632 /* eslint-disable max-len */ 633 634 var isJavaScriptProtocol = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; 635 var didWarn = false; 636 637 function sanitizeURL(url) { 638 { 639 if (!didWarn && isJavaScriptProtocol.test(url)) { 640 didWarn = true; 641 642 error('A future version of React will block javascript: URLs as a security precaution. ' + 'Use event handlers instead if you can. If you need to generate unsafe HTML try ' + 'using dangerouslySetInnerHTML instead. React was passed %s.', JSON.stringify(url)); 643 } 644 } 645 } 646 647 /** 648 * Get the value for a property on a node. Only used in DEV for SSR validation. 649 * The "expected" argument is used as a hint of what the expected value is. 650 * Some properties have multiple equivalent values. 651 */ 652 function getValueForProperty(node, name, expected, propertyInfo) { 653 { 654 if (propertyInfo.mustUseProperty) { 655 var propertyName = propertyInfo.propertyName; 656 return node[propertyName]; 657 } else { 658 // This check protects multiple uses of `expected`, which is why the 659 // react-internal/safe-string-coercion rule is disabled in several spots 660 // below. 661 { 662 checkAttributeStringCoercion(expected, name); 663 } 664 665 if ( propertyInfo.sanitizeURL) { 666 // If we haven't fully disabled javascript: URLs, and if 667 // the hydration is successful of a javascript: URL, we 668 // still want to warn on the client. 669 // eslint-disable-next-line react-internal/safe-string-coercion 670 sanitizeURL('' + expected); 671 } 672 673 var attributeName = propertyInfo.attributeName; 674 var stringValue = null; 675 676 if (propertyInfo.type === OVERLOADED_BOOLEAN) { 677 if (node.hasAttribute(attributeName)) { 678 var value = node.getAttribute(attributeName); 679 680 if (value === '') { 681 return true; 682 } 683 684 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 685 return value; 686 } // eslint-disable-next-line react-internal/safe-string-coercion 687 688 689 if (value === '' + expected) { 690 return expected; 691 } 692 693 return value; 694 } 695 } else if (node.hasAttribute(attributeName)) { 696 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 697 // We had an attribute but shouldn't have had one, so read it 698 // for the error message. 699 return node.getAttribute(attributeName); 700 } 701 702 if (propertyInfo.type === BOOLEAN) { 703 // If this was a boolean, it doesn't matter what the value is 704 // the fact that we have it is the same as the expected. 705 return expected; 706 } // Even if this property uses a namespace we use getAttribute 707 // because we assume its namespaced name is the same as our config. 708 // To use getAttributeNS we need the local name which we don't have 709 // in our config atm. 710 711 712 stringValue = node.getAttribute(attributeName); 713 } 714 715 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 716 return stringValue === null ? expected : stringValue; // eslint-disable-next-line react-internal/safe-string-coercion 717 } else if (stringValue === '' + expected) { 718 return expected; 719 } else { 720 return stringValue; 721 } 722 } 723 } 724 } 725 /** 726 * Get the value for a attribute on a node. Only used in DEV for SSR validation. 727 * The third argument is used as a hint of what the expected value is. Some 728 * attributes have multiple equivalent values. 729 */ 730 731 function getValueForAttribute(node, name, expected, isCustomComponentTag) { 732 { 733 if (!isAttributeNameSafe(name)) { 734 return; 735 } 736 737 if (!node.hasAttribute(name)) { 738 return expected === undefined ? undefined : null; 739 } 740 741 var value = node.getAttribute(name); 742 743 { 744 checkAttributeStringCoercion(expected, name); 745 } 746 747 if (value === '' + expected) { 748 return expected; 749 } 750 751 return value; 752 } 753 } 754 /** 755 * Sets the value for a property on a node. 756 * 757 * @param {DOMElement} node 758 * @param {string} name 759 * @param {*} value 760 */ 761 762 function setValueForProperty(node, name, value, isCustomComponentTag) { 763 var propertyInfo = getPropertyInfo(name); 764 765 if (shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag)) { 766 return; 767 } 768 769 if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) { 770 value = null; 771 } 772 773 774 if (isCustomComponentTag || propertyInfo === null) { 775 if (isAttributeNameSafe(name)) { 776 var _attributeName = name; 777 778 if (value === null) { 779 node.removeAttribute(_attributeName); 780 } else { 781 { 782 checkAttributeStringCoercion(value, name); 783 } 784 785 node.setAttribute(_attributeName, '' + value); 786 } 787 } 788 789 return; 790 } 791 792 var mustUseProperty = propertyInfo.mustUseProperty; 793 794 if (mustUseProperty) { 795 var propertyName = propertyInfo.propertyName; 796 797 if (value === null) { 798 var type = propertyInfo.type; 799 node[propertyName] = type === BOOLEAN ? false : ''; 800 } else { 801 // Contrary to `setAttribute`, object properties are properly 802 // `toString`ed by IE8/9. 803 node[propertyName] = value; 804 } 805 806 return; 807 } // The rest are treated as attributes with special cases. 808 809 810 var attributeName = propertyInfo.attributeName, 811 attributeNamespace = propertyInfo.attributeNamespace; 812 813 if (value === null) { 814 node.removeAttribute(attributeName); 815 } else { 816 var _type = propertyInfo.type; 817 var attributeValue; 818 819 if (_type === BOOLEAN || _type === OVERLOADED_BOOLEAN && value === true) { 820 // If attribute type is boolean, we know for sure it won't be an execution sink 821 // and we won't require Trusted Type here. 822 attributeValue = ''; 823 } else { 824 // `setAttribute` with objects becomes only `[object]` in IE8/9, 825 // ('' + value) makes it output the correct toString()-value. 826 { 827 { 828 checkAttributeStringCoercion(value, attributeName); 829 } 830 831 attributeValue = '' + value; 832 } 833 834 if (propertyInfo.sanitizeURL) { 835 sanitizeURL(attributeValue.toString()); 836 } 837 } 838 839 if (attributeNamespace) { 840 node.setAttributeNS(attributeNamespace, attributeName, attributeValue); 841 } else { 842 node.setAttribute(attributeName, attributeValue); 843 } 844 } 845 } 846 847 // ATTENTION 848 // When adding new symbols to this file, 849 // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' 850 // The Symbol used to tag the ReactElement-like types. 851 var REACT_ELEMENT_TYPE = Symbol.for('react.element'); 852 var REACT_PORTAL_TYPE = Symbol.for('react.portal'); 853 var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); 854 var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode'); 855 var REACT_PROFILER_TYPE = Symbol.for('react.profiler'); 856 var REACT_PROVIDER_TYPE = Symbol.for('react.provider'); 857 var REACT_CONTEXT_TYPE = Symbol.for('react.context'); 858 var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref'); 859 var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense'); 860 var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list'); 861 var REACT_MEMO_TYPE = Symbol.for('react.memo'); 862 var REACT_LAZY_TYPE = Symbol.for('react.lazy'); 863 var REACT_SCOPE_TYPE = Symbol.for('react.scope'); 864 var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for('react.debug_trace_mode'); 865 var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen'); 866 var REACT_LEGACY_HIDDEN_TYPE = Symbol.for('react.legacy_hidden'); 867 var REACT_CACHE_TYPE = Symbol.for('react.cache'); 868 var REACT_TRACING_MARKER_TYPE = Symbol.for('react.tracing_marker'); 869 var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; 870 var FAUX_ITERATOR_SYMBOL = '@@iterator'; 871 function getIteratorFn(maybeIterable) { 872 if (maybeIterable === null || typeof maybeIterable !== 'object') { 873 return null; 874 } 875 876 var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; 877 878 if (typeof maybeIterator === 'function') { 879 return maybeIterator; 880 } 881 882 return null; 883 } 884 885 var assign = Object.assign; 886 887 // Helpers to patch console.logs to avoid logging during side-effect free 888 // replaying on render function. This currently only patches the object 889 // lazily which won't cover if the log function was extracted eagerly. 890 // We could also eagerly patch the method. 891 var disabledDepth = 0; 892 var prevLog; 893 var prevInfo; 894 var prevWarn; 895 var prevError; 896 var prevGroup; 897 var prevGroupCollapsed; 898 var prevGroupEnd; 899 900 function disabledLog() {} 901 902 disabledLog.__reactDisabledLog = true; 903 function disableLogs() { 904 { 905 if (disabledDepth === 0) { 906 /* eslint-disable react-internal/no-production-logging */ 907 prevLog = console.log; 908 prevInfo = console.info; 909 prevWarn = console.warn; 910 prevError = console.error; 911 prevGroup = console.group; 912 prevGroupCollapsed = console.groupCollapsed; 913 prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 914 915 var props = { 916 configurable: true, 917 enumerable: true, 918 value: disabledLog, 919 writable: true 920 }; // $FlowFixMe Flow thinks console is immutable. 921 922 Object.defineProperties(console, { 923 info: props, 924 log: props, 925 warn: props, 926 error: props, 927 group: props, 928 groupCollapsed: props, 929 groupEnd: props 930 }); 931 /* eslint-enable react-internal/no-production-logging */ 932 } 933 934 disabledDepth++; 935 } 936 } 937 function reenableLogs() { 938 { 939 disabledDepth--; 940 941 if (disabledDepth === 0) { 942 /* eslint-disable react-internal/no-production-logging */ 943 var props = { 944 configurable: true, 945 enumerable: true, 946 writable: true 947 }; // $FlowFixMe Flow thinks console is immutable. 948 949 Object.defineProperties(console, { 950 log: assign({}, props, { 951 value: prevLog 952 }), 953 info: assign({}, props, { 954 value: prevInfo 955 }), 956 warn: assign({}, props, { 957 value: prevWarn 958 }), 959 error: assign({}, props, { 960 value: prevError 961 }), 962 group: assign({}, props, { 963 value: prevGroup 964 }), 965 groupCollapsed: assign({}, props, { 966 value: prevGroupCollapsed 967 }), 968 groupEnd: assign({}, props, { 969 value: prevGroupEnd 970 }) 971 }); 972 /* eslint-enable react-internal/no-production-logging */ 973 } 974 975 if (disabledDepth < 0) { 976 error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.'); 977 } 978 } 979 } 980 981 var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; 982 var prefix; 983 function describeBuiltInComponentFrame(name, source, ownerFn) { 984 { 985 if (prefix === undefined) { 986 // Extract the VM specific prefix used by each line. 987 try { 988 throw Error(); 989 } catch (x) { 990 var match = x.stack.trim().match(/\n( *(at )?)/); 991 prefix = match && match[1] || ''; 992 } 993 } // We use the prefix to ensure our stacks line up with native stack frames. 994 995 996 return '\n' + prefix + name; 997 } 998 } 999 var reentry = false; 1000 var componentFrameCache; 1001 1002 { 1003 var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; 1004 componentFrameCache = new PossiblyWeakMap(); 1005 } 1006 1007 function describeNativeComponentFrame(fn, construct) { 1008 // If something asked for a stack inside a fake render, it should get ignored. 1009 if ( !fn || reentry) { 1010 return ''; 1011 } 1012 1013 { 1014 var frame = componentFrameCache.get(fn); 1015 1016 if (frame !== undefined) { 1017 return frame; 1018 } 1019 } 1020 1021 var control; 1022 reentry = true; 1023 var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined. 1024 1025 Error.prepareStackTrace = undefined; 1026 var previousDispatcher; 1027 1028 { 1029 previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function 1030 // for warnings. 1031 1032 ReactCurrentDispatcher.current = null; 1033 disableLogs(); 1034 } 1035 1036 try { 1037 // This should throw. 1038 if (construct) { 1039 // Something should be setting the props in the constructor. 1040 var Fake = function () { 1041 throw Error(); 1042 }; // $FlowFixMe 1043 1044 1045 Object.defineProperty(Fake.prototype, 'props', { 1046 set: function () { 1047 // We use a throwing setter instead of frozen or non-writable props 1048 // because that won't throw in a non-strict mode function. 1049 throw Error(); 1050 } 1051 }); 1052 1053 if (typeof Reflect === 'object' && Reflect.construct) { 1054 // We construct a different control for this case to include any extra 1055 // frames added by the construct call. 1056 try { 1057 Reflect.construct(Fake, []); 1058 } catch (x) { 1059 control = x; 1060 } 1061 1062 Reflect.construct(fn, [], Fake); 1063 } else { 1064 try { 1065 Fake.call(); 1066 } catch (x) { 1067 control = x; 1068 } 1069 1070 fn.call(Fake.prototype); 1071 } 1072 } else { 1073 try { 1074 throw Error(); 1075 } catch (x) { 1076 control = x; 1077 } 1078 1079 fn(); 1080 } 1081 } catch (sample) { 1082 // This is inlined manually because closure doesn't do it for us. 1083 if (sample && control && typeof sample.stack === 'string') { 1084 // This extracts the first frame from the sample that isn't also in the control. 1085 // Skipping one frame that we assume is the frame that calls the two. 1086 var sampleLines = sample.stack.split('\n'); 1087 var controlLines = control.stack.split('\n'); 1088 var s = sampleLines.length - 1; 1089 var c = controlLines.length - 1; 1090 1091 while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { 1092 // We expect at least one stack frame to be shared. 1093 // Typically this will be the root most one. However, stack frames may be 1094 // cut off due to maximum stack limits. In this case, one maybe cut off 1095 // earlier than the other. We assume that the sample is longer or the same 1096 // and there for cut off earlier. So we should find the root most frame in 1097 // the sample somewhere in the control. 1098 c--; 1099 } 1100 1101 for (; s >= 1 && c >= 0; s--, c--) { 1102 // Next we find the first one that isn't the same which should be the 1103 // frame that called our sample function and the control. 1104 if (sampleLines[s] !== controlLines[c]) { 1105 // In V8, the first line is describing the message but other VMs don't. 1106 // If we're about to return the first line, and the control is also on the same 1107 // line, that's a pretty good indicator that our sample threw at same line as 1108 // the control. I.e. before we entered the sample frame. So we ignore this result. 1109 // This can happen if you passed a class to function component, or non-function. 1110 if (s !== 1 || c !== 1) { 1111 do { 1112 s--; 1113 c--; // We may still have similar intermediate frames from the construct call. 1114 // The next one that isn't the same should be our match though. 1115 1116 if (c < 0 || sampleLines[s] !== controlLines[c]) { 1117 // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. 1118 var _frame = '\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled "<anonymous>" 1119 // but we have a user-provided "displayName" 1120 // splice it in to make the stack more readable. 1121 1122 1123 if (fn.displayName && _frame.includes('<anonymous>')) { 1124 _frame = _frame.replace('<anonymous>', fn.displayName); 1125 } 1126 1127 { 1128 if (typeof fn === 'function') { 1129 componentFrameCache.set(fn, _frame); 1130 } 1131 } // Return the line we found. 1132 1133 1134 return _frame; 1135 } 1136 } while (s >= 1 && c >= 0); 1137 } 1138 1139 break; 1140 } 1141 } 1142 } 1143 } finally { 1144 reentry = false; 1145 1146 { 1147 ReactCurrentDispatcher.current = previousDispatcher; 1148 reenableLogs(); 1149 } 1150 1151 Error.prepareStackTrace = previousPrepareStackTrace; 1152 } // Fallback to just using the name if we couldn't make it throw. 1153 1154 1155 var name = fn ? fn.displayName || fn.name : ''; 1156 var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ''; 1157 1158 { 1159 if (typeof fn === 'function') { 1160 componentFrameCache.set(fn, syntheticFrame); 1161 } 1162 } 1163 1164 return syntheticFrame; 1165 } 1166 1167 function describeClassComponentFrame(ctor, source, ownerFn) { 1168 { 1169 return describeNativeComponentFrame(ctor, true); 1170 } 1171 } 1172 function describeFunctionComponentFrame(fn, source, ownerFn) { 1173 { 1174 return describeNativeComponentFrame(fn, false); 1175 } 1176 } 1177 1178 function shouldConstruct(Component) { 1179 var prototype = Component.prototype; 1180 return !!(prototype && prototype.isReactComponent); 1181 } 1182 1183 function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { 1184 1185 if (type == null) { 1186 return ''; 1187 } 1188 1189 if (typeof type === 'function') { 1190 { 1191 return describeNativeComponentFrame(type, shouldConstruct(type)); 1192 } 1193 } 1194 1195 if (typeof type === 'string') { 1196 return describeBuiltInComponentFrame(type); 1197 } 1198 1199 switch (type) { 1200 case REACT_SUSPENSE_TYPE: 1201 return describeBuiltInComponentFrame('Suspense'); 1202 1203 case REACT_SUSPENSE_LIST_TYPE: 1204 return describeBuiltInComponentFrame('SuspenseList'); 1205 } 1206 1207 if (typeof type === 'object') { 1208 switch (type.$$typeof) { 1209 case REACT_FORWARD_REF_TYPE: 1210 return describeFunctionComponentFrame(type.render); 1211 1212 case REACT_MEMO_TYPE: 1213 // Memo may contain any component type so we recursively resolve it. 1214 return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); 1215 1216 case REACT_LAZY_TYPE: 1217 { 1218 var lazyComponent = type; 1219 var payload = lazyComponent._payload; 1220 var init = lazyComponent._init; 1221 1222 try { 1223 // Lazy may contain any component type so we recursively resolve it. 1224 return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn); 1225 } catch (x) {} 1226 } 1227 } 1228 } 1229 1230 return ''; 1231 } 1232 1233 function describeFiber(fiber) { 1234 var owner = fiber._debugOwner ? fiber._debugOwner.type : null ; 1235 var source = fiber._debugSource ; 1236 1237 switch (fiber.tag) { 1238 case HostComponent: 1239 return describeBuiltInComponentFrame(fiber.type); 1240 1241 case LazyComponent: 1242 return describeBuiltInComponentFrame('Lazy'); 1243 1244 case SuspenseComponent: 1245 return describeBuiltInComponentFrame('Suspense'); 1246 1247 case SuspenseListComponent: 1248 return describeBuiltInComponentFrame('SuspenseList'); 1249 1250 case FunctionComponent: 1251 case IndeterminateComponent: 1252 case SimpleMemoComponent: 1253 return describeFunctionComponentFrame(fiber.type); 1254 1255 case ForwardRef: 1256 return describeFunctionComponentFrame(fiber.type.render); 1257 1258 case ClassComponent: 1259 return describeClassComponentFrame(fiber.type); 1260 1261 default: 1262 return ''; 1263 } 1264 } 1265 1266 function getStackByFiberInDevAndProd(workInProgress) { 1267 try { 1268 var info = ''; 1269 var node = workInProgress; 1270 1271 do { 1272 info += describeFiber(node); 1273 node = node.return; 1274 } while (node); 1275 1276 return info; 1277 } catch (x) { 1278 return '\nError generating stack: ' + x.message + '\n' + x.stack; 1279 } 1280 } 1281 1282 function getWrappedName(outerType, innerType, wrapperName) { 1283 var displayName = outerType.displayName; 1284 1285 if (displayName) { 1286 return displayName; 1287 } 1288 1289 var functionName = innerType.displayName || innerType.name || ''; 1290 return functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName; 1291 } // Keep in sync with react-reconciler/getComponentNameFromFiber 1292 1293 1294 function getContextName(type) { 1295 return type.displayName || 'Context'; 1296 } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. 1297 1298 1299 function getComponentNameFromType(type) { 1300 if (type == null) { 1301 // Host root, text node or just invalid type. 1302 return null; 1303 } 1304 1305 { 1306 if (typeof type.tag === 'number') { 1307 error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.'); 1308 } 1309 } 1310 1311 if (typeof type === 'function') { 1312 return type.displayName || type.name || null; 1313 } 1314 1315 if (typeof type === 'string') { 1316 return type; 1317 } 1318 1319 switch (type) { 1320 case REACT_FRAGMENT_TYPE: 1321 return 'Fragment'; 1322 1323 case REACT_PORTAL_TYPE: 1324 return 'Portal'; 1325 1326 case REACT_PROFILER_TYPE: 1327 return 'Profiler'; 1328 1329 case REACT_STRICT_MODE_TYPE: 1330 return 'StrictMode'; 1331 1332 case REACT_SUSPENSE_TYPE: 1333 return 'Suspense'; 1334 1335 case REACT_SUSPENSE_LIST_TYPE: 1336 return 'SuspenseList'; 1337 1338 } 1339 1340 if (typeof type === 'object') { 1341 switch (type.$$typeof) { 1342 case REACT_CONTEXT_TYPE: 1343 var context = type; 1344 return getContextName(context) + '.Consumer'; 1345 1346 case REACT_PROVIDER_TYPE: 1347 var provider = type; 1348 return getContextName(provider._context) + '.Provider'; 1349 1350 case REACT_FORWARD_REF_TYPE: 1351 return getWrappedName(type, type.render, 'ForwardRef'); 1352 1353 case REACT_MEMO_TYPE: 1354 var outerName = type.displayName || null; 1355 1356 if (outerName !== null) { 1357 return outerName; 1358 } 1359 1360 return getComponentNameFromType(type.type) || 'Memo'; 1361 1362 case REACT_LAZY_TYPE: 1363 { 1364 var lazyComponent = type; 1365 var payload = lazyComponent._payload; 1366 var init = lazyComponent._init; 1367 1368 try { 1369 return getComponentNameFromType(init(payload)); 1370 } catch (x) { 1371 return null; 1372 } 1373 } 1374 1375 // eslint-disable-next-line no-fallthrough 1376 } 1377 } 1378 1379 return null; 1380 } 1381 1382 function getWrappedName$1(outerType, innerType, wrapperName) { 1383 var functionName = innerType.displayName || innerType.name || ''; 1384 return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName); 1385 } // Keep in sync with shared/getComponentNameFromType 1386 1387 1388 function getContextName$1(type) { 1389 return type.displayName || 'Context'; 1390 } 1391 1392 function getComponentNameFromFiber(fiber) { 1393 var tag = fiber.tag, 1394 type = fiber.type; 1395 1396 switch (tag) { 1397 case CacheComponent: 1398 return 'Cache'; 1399 1400 case ContextConsumer: 1401 var context = type; 1402 return getContextName$1(context) + '.Consumer'; 1403 1404 case ContextProvider: 1405 var provider = type; 1406 return getContextName$1(provider._context) + '.Provider'; 1407 1408 case DehydratedFragment: 1409 return 'DehydratedFragment'; 1410 1411 case ForwardRef: 1412 return getWrappedName$1(type, type.render, 'ForwardRef'); 1413 1414 case Fragment: 1415 return 'Fragment'; 1416 1417 case HostComponent: 1418 // Host component type is the display name (e.g. "div", "View") 1419 return type; 1420 1421 case HostPortal: 1422 return 'Portal'; 1423 1424 case HostRoot: 1425 return 'Root'; 1426 1427 case HostText: 1428 return 'Text'; 1429 1430 case LazyComponent: 1431 // Name comes from the type in this case; we don't have a tag. 1432 return getComponentNameFromType(type); 1433 1434 case Mode: 1435 if (type === REACT_STRICT_MODE_TYPE) { 1436 // Don't be less specific than shared/getComponentNameFromType 1437 return 'StrictMode'; 1438 } 1439 1440 return 'Mode'; 1441 1442 case OffscreenComponent: 1443 return 'Offscreen'; 1444 1445 case Profiler: 1446 return 'Profiler'; 1447 1448 case ScopeComponent: 1449 return 'Scope'; 1450 1451 case SuspenseComponent: 1452 return 'Suspense'; 1453 1454 case SuspenseListComponent: 1455 return 'SuspenseList'; 1456 1457 case TracingMarkerComponent: 1458 return 'TracingMarker'; 1459 // The display name for this tags come from the user-provided type: 1460 1461 case ClassComponent: 1462 case FunctionComponent: 1463 case IncompleteClassComponent: 1464 case IndeterminateComponent: 1465 case MemoComponent: 1466 case SimpleMemoComponent: 1467 if (typeof type === 'function') { 1468 return type.displayName || type.name || null; 1469 } 1470 1471 if (typeof type === 'string') { 1472 return type; 1473 } 1474 1475 break; 1476 1477 } 1478 1479 return null; 1480 } 1481 1482 var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; 1483 var current = null; 1484 var isRendering = false; 1485 function getCurrentFiberOwnerNameInDevOrNull() { 1486 { 1487 if (current === null) { 1488 return null; 1489 } 1490 1491 var owner = current._debugOwner; 1492 1493 if (owner !== null && typeof owner !== 'undefined') { 1494 return getComponentNameFromFiber(owner); 1495 } 1496 } 1497 1498 return null; 1499 } 1500 1501 function getCurrentFiberStackInDev() { 1502 { 1503 if (current === null) { 1504 return ''; 1505 } // Safe because if current fiber exists, we are reconciling, 1506 // and it is guaranteed to be the work-in-progress version. 1507 1508 1509 return getStackByFiberInDevAndProd(current); 1510 } 1511 } 1512 1513 function resetCurrentFiber() { 1514 { 1515 ReactDebugCurrentFrame.getCurrentStack = null; 1516 current = null; 1517 isRendering = false; 1518 } 1519 } 1520 function setCurrentFiber(fiber) { 1521 { 1522 ReactDebugCurrentFrame.getCurrentStack = fiber === null ? null : getCurrentFiberStackInDev; 1523 current = fiber; 1524 isRendering = false; 1525 } 1526 } 1527 function getCurrentFiber() { 1528 { 1529 return current; 1530 } 1531 } 1532 function setIsRendering(rendering) { 1533 { 1534 isRendering = rendering; 1535 } 1536 } 1537 1538 // Flow does not allow string concatenation of most non-string types. To work 1539 // around this limitation, we use an opaque type that can only be obtained by 1540 // passing the value through getToStringValue first. 1541 function toString(value) { 1542 // The coercion safety check is performed in getToStringValue(). 1543 // eslint-disable-next-line react-internal/safe-string-coercion 1544 return '' + value; 1545 } 1546 function getToStringValue(value) { 1547 switch (typeof value) { 1548 case 'boolean': 1549 case 'number': 1550 case 'string': 1551 case 'undefined': 1552 return value; 1553 1554 case 'object': 1555 { 1556 checkFormFieldValueStringCoercion(value); 1557 } 1558 1559 return value; 1560 1561 default: 1562 // function, symbol are assigned as empty strings 1563 return ''; 1564 } 1565 } 1566 1567 var hasReadOnlyValue = { 1568 button: true, 1569 checkbox: true, 1570 image: true, 1571 hidden: true, 1572 radio: true, 1573 reset: true, 1574 submit: true 1575 }; 1576 function checkControlledValueProps(tagName, props) { 1577 { 1578 if (!(hasReadOnlyValue[props.type] || props.onChange || props.onInput || props.readOnly || props.disabled || props.value == null)) { 1579 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`.'); 1580 } 1581 1582 if (!(props.onChange || props.readOnly || props.disabled || props.checked == null)) { 1583 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`.'); 1584 } 1585 } 1586 } 1587 1588 function isCheckable(elem) { 1589 var type = elem.type; 1590 var nodeName = elem.nodeName; 1591 return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio'); 1592 } 1593 1594 function getTracker(node) { 1595 return node._valueTracker; 1596 } 1597 1598 function detachTracker(node) { 1599 node._valueTracker = null; 1600 } 1601 1602 function getValueFromNode(node) { 1603 var value = ''; 1604 1605 if (!node) { 1606 return value; 1607 } 1608 1609 if (isCheckable(node)) { 1610 value = node.checked ? 'true' : 'false'; 1611 } else { 1612 value = node.value; 1613 } 1614 1615 return value; 1616 } 1617 1618 function trackValueOnNode(node) { 1619 var valueField = isCheckable(node) ? 'checked' : 'value'; 1620 var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField); 1621 1622 { 1623 checkFormFieldValueStringCoercion(node[valueField]); 1624 } 1625 1626 var currentValue = '' + node[valueField]; // if someone has already defined a value or Safari, then bail 1627 // and don't track value will cause over reporting of changes, 1628 // but it's better then a hard failure 1629 // (needed for certain tests that spyOn input values and Safari) 1630 1631 if (node.hasOwnProperty(valueField) || typeof descriptor === 'undefined' || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') { 1632 return; 1633 } 1634 1635 var get = descriptor.get, 1636 set = descriptor.set; 1637 Object.defineProperty(node, valueField, { 1638 configurable: true, 1639 get: function () { 1640 return get.call(this); 1641 }, 1642 set: function (value) { 1643 { 1644 checkFormFieldValueStringCoercion(value); 1645 } 1646 1647 currentValue = '' + value; 1648 set.call(this, value); 1649 } 1650 }); // We could've passed this the first time 1651 // but it triggers a bug in IE11 and Edge 14/15. 1652 // Calling defineProperty() again should be equivalent. 1653 // https://github.com/facebook/react/issues/11768 1654 1655 Object.defineProperty(node, valueField, { 1656 enumerable: descriptor.enumerable 1657 }); 1658 var tracker = { 1659 getValue: function () { 1660 return currentValue; 1661 }, 1662 setValue: function (value) { 1663 { 1664 checkFormFieldValueStringCoercion(value); 1665 } 1666 1667 currentValue = '' + value; 1668 }, 1669 stopTracking: function () { 1670 detachTracker(node); 1671 delete node[valueField]; 1672 } 1673 }; 1674 return tracker; 1675 } 1676 1677 function track(node) { 1678 if (getTracker(node)) { 1679 return; 1680 } // TODO: Once it's just Fiber we can move this to node._wrapperState 1681 1682 1683 node._valueTracker = trackValueOnNode(node); 1684 } 1685 function updateValueIfChanged(node) { 1686 if (!node) { 1687 return false; 1688 } 1689 1690 var tracker = getTracker(node); // if there is no tracker at this point it's unlikely 1691 // that trying again will succeed 1692 1693 if (!tracker) { 1694 return true; 1695 } 1696 1697 var lastValue = tracker.getValue(); 1698 var nextValue = getValueFromNode(node); 1699 1700 if (nextValue !== lastValue) { 1701 tracker.setValue(nextValue); 1702 return true; 1703 } 1704 1705 return false; 1706 } 1707 1708 function getActiveElement(doc) { 1709 doc = doc || (typeof document !== 'undefined' ? document : undefined); 1710 1711 if (typeof doc === 'undefined') { 1712 return null; 1713 } 1714 1715 try { 1716 return doc.activeElement || doc.body; 1717 } catch (e) { 1718 return doc.body; 1719 } 1720 } 1721 1722 var didWarnValueDefaultValue = false; 1723 var didWarnCheckedDefaultChecked = false; 1724 var didWarnControlledToUncontrolled = false; 1725 var didWarnUncontrolledToControlled = false; 1726 1727 function isControlled(props) { 1728 var usesChecked = props.type === 'checkbox' || props.type === 'radio'; 1729 return usesChecked ? props.checked != null : props.value != null; 1730 } 1731 /** 1732 * Implements an <input> host component that allows setting these optional 1733 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. 1734 * 1735 * If `checked` or `value` are not supplied (or null/undefined), user actions 1736 * that affect the checked state or value will trigger updates to the element. 1737 * 1738 * If they are supplied (and not null/undefined), the rendered element will not 1739 * trigger updates to the element. Instead, the props must change in order for 1740 * the rendered element to be updated. 1741 * 1742 * The rendered element will be initialized as unchecked (or `defaultChecked`) 1743 * with an empty value (or `defaultValue`). 1744 * 1745 * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html 1746 */ 1747 1748 1749 function getHostProps(element, props) { 1750 var node = element; 1751 var checked = props.checked; 1752 var hostProps = assign({}, props, { 1753 defaultChecked: undefined, 1754 defaultValue: undefined, 1755 value: undefined, 1756 checked: checked != null ? checked : node._wrapperState.initialChecked 1757 }); 1758 return hostProps; 1759 } 1760 function initWrapperState(element, props) { 1761 { 1762 checkControlledValueProps('input', props); 1763 1764 if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) { 1765 error('%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://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component', props.type); 1766 1767 didWarnCheckedDefaultChecked = true; 1768 } 1769 1770 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) { 1771 error('%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://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component', props.type); 1772 1773 didWarnValueDefaultValue = true; 1774 } 1775 } 1776 1777 var node = element; 1778 var defaultValue = props.defaultValue == null ? '' : props.defaultValue; 1779 node._wrapperState = { 1780 initialChecked: props.checked != null ? props.checked : props.defaultChecked, 1781 initialValue: getToStringValue(props.value != null ? props.value : defaultValue), 1782 controlled: isControlled(props) 1783 }; 1784 } 1785 function updateChecked(element, props) { 1786 var node = element; 1787 var checked = props.checked; 1788 1789 if (checked != null) { 1790 setValueForProperty(node, 'checked', checked, false); 1791 } 1792 } 1793 function updateWrapper(element, props) { 1794 var node = element; 1795 1796 { 1797 var controlled = isControlled(props); 1798 1799 if (!node._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) { 1800 error('A component is changing an uncontrolled input to be controlled. ' + 'This is likely caused by the value changing from undefined to ' + 'a defined value, which should not happen. ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components'); 1801 1802 didWarnUncontrolledToControlled = true; 1803 } 1804 1805 if (node._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) { 1806 error('A component is changing a controlled input to be uncontrolled. ' + 'This is likely caused by the value changing from a defined to ' + 'undefined, which should not happen. ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components'); 1807 1808 didWarnControlledToUncontrolled = true; 1809 } 1810 } 1811 1812 updateChecked(element, props); 1813 var value = getToStringValue(props.value); 1814 var type = props.type; 1815 1816 if (value != null) { 1817 if (type === 'number') { 1818 if (value === 0 && node.value === '' || // We explicitly want to coerce to number here if possible. 1819 // eslint-disable-next-line 1820 node.value != value) { 1821 node.value = toString(value); 1822 } 1823 } else if (node.value !== toString(value)) { 1824 node.value = toString(value); 1825 } 1826 } else if (type === 'submit' || type === 'reset') { 1827 // Submit/reset inputs need the attribute removed completely to avoid 1828 // blank-text buttons. 1829 node.removeAttribute('value'); 1830 return; 1831 } 1832 1833 { 1834 // When syncing the value attribute, the value comes from a cascade of 1835 // properties: 1836 // 1. The value React property 1837 // 2. The defaultValue React property 1838 // 3. Otherwise there should be no change 1839 if (props.hasOwnProperty('value')) { 1840 setDefaultValue(node, props.type, value); 1841 } else if (props.hasOwnProperty('defaultValue')) { 1842 setDefaultValue(node, props.type, getToStringValue(props.defaultValue)); 1843 } 1844 } 1845 1846 { 1847 // When syncing the checked attribute, it only changes when it needs 1848 // to be removed, such as transitioning from a checkbox into a text input 1849 if (props.checked == null && props.defaultChecked != null) { 1850 node.defaultChecked = !!props.defaultChecked; 1851 } 1852 } 1853 } 1854 function postMountWrapper(element, props, isHydrating) { 1855 var node = element; // Do not assign value if it is already set. This prevents user text input 1856 // from being lost during SSR hydration. 1857 1858 if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) { 1859 var type = props.type; 1860 var isButton = type === 'submit' || type === 'reset'; // Avoid setting value attribute on submit/reset inputs as it overrides the 1861 // default value provided by the browser. See: #12872 1862 1863 if (isButton && (props.value === undefined || props.value === null)) { 1864 return; 1865 } 1866 1867 var initialValue = toString(node._wrapperState.initialValue); // Do not assign value if it is already set. This prevents user text input 1868 // from being lost during SSR hydration. 1869 1870 if (!isHydrating) { 1871 { 1872 // When syncing the value attribute, the value property should use 1873 // the wrapperState._initialValue property. This uses: 1874 // 1875 // 1. The value React property when present 1876 // 2. The defaultValue React property when present 1877 // 3. An empty string 1878 if (initialValue !== node.value) { 1879 node.value = initialValue; 1880 } 1881 } 1882 } 1883 1884 { 1885 // Otherwise, the value attribute is synchronized to the property, 1886 // so we assign defaultValue to the same thing as the value property 1887 // assignment step above. 1888 node.defaultValue = initialValue; 1889 } 1890 } // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug 1891 // this is needed to work around a chrome bug where setting defaultChecked 1892 // will sometimes influence the value of checked (even after detachment). 1893 // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416 1894 // We need to temporarily unset name to avoid disrupting radio button groups. 1895 1896 1897 var name = node.name; 1898 1899 if (name !== '') { 1900 node.name = ''; 1901 } 1902 1903 { 1904 // When syncing the checked attribute, both the checked property and 1905 // attribute are assigned at the same time using defaultChecked. This uses: 1906 // 1907 // 1. The checked React property when present 1908 // 2. The defaultChecked React property when present 1909 // 3. Otherwise, false 1910 node.defaultChecked = !node.defaultChecked; 1911 node.defaultChecked = !!node._wrapperState.initialChecked; 1912 } 1913 1914 if (name !== '') { 1915 node.name = name; 1916 } 1917 } 1918 function restoreControlledState(element, props) { 1919 var node = element; 1920 updateWrapper(node, props); 1921 updateNamedCousins(node, props); 1922 } 1923 1924 function updateNamedCousins(rootNode, props) { 1925 var name = props.name; 1926 1927 if (props.type === 'radio' && name != null) { 1928 var queryRoot = rootNode; 1929 1930 while (queryRoot.parentNode) { 1931 queryRoot = queryRoot.parentNode; 1932 } // If `rootNode.form` was non-null, then we could try `form.elements`, 1933 // but that sometimes behaves strangely in IE8. We could also try using 1934 // `form.getElementsByName`, but that will only return direct children 1935 // and won't include inputs that use the HTML5 `form=` attribute. Since 1936 // the input might not even be in a form. It might not even be in the 1937 // document. Let's just use the local `querySelectorAll` to ensure we don't 1938 // miss anything. 1939 1940 1941 { 1942 checkAttributeStringCoercion(name, 'name'); 1943 } 1944 1945 var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]'); 1946 1947 for (var i = 0; i < group.length; i++) { 1948 var otherNode = group[i]; 1949 1950 if (otherNode === rootNode || otherNode.form !== rootNode.form) { 1951 continue; 1952 } // This will throw if radio buttons rendered by different copies of React 1953 // and the same name are rendered into the same form (same as #1939). 1954 // That's probably okay; we don't support it just as we don't support 1955 // mixing React radio buttons with non-React ones. 1956 1957 1958 var otherProps = getFiberCurrentPropsFromNode(otherNode); 1959 1960 if (!otherProps) { 1961 throw new Error('ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.'); 1962 } // We need update the tracked value on the named cousin since the value 1963 // was changed but the input saw no event or value set 1964 1965 1966 updateValueIfChanged(otherNode); // If this is a controlled radio button group, forcing the input that 1967 // was previously checked to update will cause it to be come re-checked 1968 // as appropriate. 1969 1970 updateWrapper(otherNode, otherProps); 1971 } 1972 } 1973 } // In Chrome, assigning defaultValue to certain input types triggers input validation. 1974 // For number inputs, the display value loses trailing decimal points. For email inputs, 1975 // Chrome raises "The specified value <x> is not a valid email address". 1976 // 1977 // Here we check to see if the defaultValue has actually changed, avoiding these problems 1978 // when the user is inputting text 1979 // 1980 // https://github.com/facebook/react/issues/7253 1981 1982 1983 function setDefaultValue(node, type, value) { 1984 if ( // Focused number inputs synchronize on blur. See ChangeEventPlugin.js 1985 type !== 'number' || getActiveElement(node.ownerDocument) !== node) { 1986 if (value == null) { 1987 node.defaultValue = toString(node._wrapperState.initialValue); 1988 } else if (node.defaultValue !== toString(value)) { 1989 node.defaultValue = toString(value); 1990 } 1991 } 1992 } 1993 1994 var didWarnSelectedSetOnOption = false; 1995 var didWarnInvalidChild = false; 1996 var didWarnInvalidInnerHTML = false; 1997 /** 1998 * Implements an <option> host component that warns when `selected` is set. 1999 */ 2000 2001 function validateProps(element, props) { 2002 { 2003 // If a value is not provided, then the children must be simple. 2004 if (props.value == null) { 2005 if (typeof props.children === 'object' && props.children !== null) { 2006 React.Children.forEach(props.children, function (child) { 2007 if (child == null) { 2008 return; 2009 } 2010 2011 if (typeof child === 'string' || typeof child === 'number') { 2012 return; 2013 } 2014 2015 if (!didWarnInvalidChild) { 2016 didWarnInvalidChild = true; 2017 2018 error('Cannot infer the option value of complex children. ' + 'Pass a `value` prop or use a plain string as children to <option>.'); 2019 } 2020 }); 2021 } else if (props.dangerouslySetInnerHTML != null) { 2022 if (!didWarnInvalidInnerHTML) { 2023 didWarnInvalidInnerHTML = true; 2024 2025 error('Pass a `value` prop if you set dangerouslyInnerHTML so React knows ' + 'which value should be selected.'); 2026 } 2027 } 2028 } // TODO: Remove support for `selected` in <option>. 2029 2030 2031 if (props.selected != null && !didWarnSelectedSetOnOption) { 2032 error('Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.'); 2033 2034 didWarnSelectedSetOnOption = true; 2035 } 2036 } 2037 } 2038 function postMountWrapper$1(element, props) { 2039 // value="" should make a value attribute (#6219) 2040 if (props.value != null) { 2041 element.setAttribute('value', toString(getToStringValue(props.value))); 2042 } 2043 } 2044 2045 var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare 2046 2047 function isArray(a) { 2048 return isArrayImpl(a); 2049 } 2050 2051 var didWarnValueDefaultValue$1; 2052 2053 { 2054 didWarnValueDefaultValue$1 = false; 2055 } 2056 2057 function getDeclarationErrorAddendum() { 2058 var ownerName = getCurrentFiberOwnerNameInDevOrNull(); 2059 2060 if (ownerName) { 2061 return '\n\nCheck the render method of `' + ownerName + '`.'; 2062 } 2063 2064 return ''; 2065 } 2066 2067 var valuePropNames = ['value', 'defaultValue']; 2068 /** 2069 * Validation function for `value` and `defaultValue`. 2070 */ 2071 2072 function checkSelectPropTypes(props) { 2073 { 2074 checkControlledValueProps('select', props); 2075 2076 for (var i = 0; i < valuePropNames.length; i++) { 2077 var propName = valuePropNames[i]; 2078 2079 if (props[propName] == null) { 2080 continue; 2081 } 2082 2083 var propNameIsArray = isArray(props[propName]); 2084 2085 if (props.multiple && !propNameIsArray) { 2086 error('The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum()); 2087 } else if (!props.multiple && propNameIsArray) { 2088 error('The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum()); 2089 } 2090 } 2091 } 2092 } 2093 2094 function updateOptions(node, multiple, propValue, setDefaultSelected) { 2095 var options = node.options; 2096 2097 if (multiple) { 2098 var selectedValues = propValue; 2099 var selectedValue = {}; 2100 2101 for (var i = 0; i < selectedValues.length; i++) { 2102 // Prefix to avoid chaos with special keys. 2103 selectedValue['$' + selectedValues[i]] = true; 2104 } 2105 2106 for (var _i = 0; _i < options.length; _i++) { 2107 var selected = selectedValue.hasOwnProperty('$' + options[_i].value); 2108 2109 if (options[_i].selected !== selected) { 2110 options[_i].selected = selected; 2111 } 2112 2113 if (selected && setDefaultSelected) { 2114 options[_i].defaultSelected = true; 2115 } 2116 } 2117 } else { 2118 // Do not set `select.value` as exact behavior isn't consistent across all 2119 // browsers for all cases. 2120 var _selectedValue = toString(getToStringValue(propValue)); 2121 2122 var defaultSelected = null; 2123 2124 for (var _i2 = 0; _i2 < options.length; _i2++) { 2125 if (options[_i2].value === _selectedValue) { 2126 options[_i2].selected = true; 2127 2128 if (setDefaultSelected) { 2129 options[_i2].defaultSelected = true; 2130 } 2131 2132 return; 2133 } 2134 2135 if (defaultSelected === null && !options[_i2].disabled) { 2136 defaultSelected = options[_i2]; 2137 } 2138 } 2139 2140 if (defaultSelected !== null) { 2141 defaultSelected.selected = true; 2142 } 2143 } 2144 } 2145 /** 2146 * Implements a <select> host component that allows optionally setting the 2147 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a 2148 * stringable. If `multiple` is true, the prop must be an array of stringables. 2149 * 2150 * If `value` is not supplied (or null/undefined), user actions that change the 2151 * selected option will trigger updates to the rendered options. 2152 * 2153 * If it is supplied (and not null/undefined), the rendered options will not 2154 * update in response to user actions. Instead, the `value` prop must change in 2155 * order for the rendered options to update. 2156 * 2157 * If `defaultValue` is provided, any options with the supplied values will be 2158 * selected. 2159 */ 2160 2161 2162 function getHostProps$1(element, props) { 2163 return assign({}, props, { 2164 value: undefined 2165 }); 2166 } 2167 function initWrapperState$1(element, props) { 2168 var node = element; 2169 2170 { 2171 checkSelectPropTypes(props); 2172 } 2173 2174 node._wrapperState = { 2175 wasMultiple: !!props.multiple 2176 }; 2177 2178 { 2179 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) { 2180 error('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://reactjs.org/link/controlled-components'); 2181 2182 didWarnValueDefaultValue$1 = true; 2183 } 2184 } 2185 } 2186 function postMountWrapper$2(element, props) { 2187 var node = element; 2188 node.multiple = !!props.multiple; 2189 var value = props.value; 2190 2191 if (value != null) { 2192 updateOptions(node, !!props.multiple, value, false); 2193 } else if (props.defaultValue != null) { 2194 updateOptions(node, !!props.multiple, props.defaultValue, true); 2195 } 2196 } 2197 function postUpdateWrapper(element, props) { 2198 var node = element; 2199 var wasMultiple = node._wrapperState.wasMultiple; 2200 node._wrapperState.wasMultiple = !!props.multiple; 2201 var value = props.value; 2202 2203 if (value != null) { 2204 updateOptions(node, !!props.multiple, value, false); 2205 } else if (wasMultiple !== !!props.multiple) { 2206 // For simplicity, reapply `defaultValue` if `multiple` is toggled. 2207 if (props.defaultValue != null) { 2208 updateOptions(node, !!props.multiple, props.defaultValue, true); 2209 } else { 2210 // Revert the select back to its default unselected state. 2211 updateOptions(node, !!props.multiple, props.multiple ? [] : '', false); 2212 } 2213 } 2214 } 2215 function restoreControlledState$1(element, props) { 2216 var node = element; 2217 var value = props.value; 2218 2219 if (value != null) { 2220 updateOptions(node, !!props.multiple, value, false); 2221 } 2222 } 2223 2224 var didWarnValDefaultVal = false; 2225 2226 /** 2227 * Implements a <textarea> host component that allows setting `value`, and 2228 * `defaultValue`. This differs from the traditional DOM API because value is 2229 * usually set as PCDATA children. 2230 * 2231 * If `value` is not supplied (or null/undefined), user actions that affect the 2232 * value will trigger updates to the element. 2233 * 2234 * If `value` is supplied (and not null/undefined), the rendered element will 2235 * not trigger updates to the element. Instead, the `value` prop must change in 2236 * order for the rendered element to be updated. 2237 * 2238 * The rendered element will be initialized with an empty value, the prop 2239 * `defaultValue` if specified, or the children content (deprecated). 2240 */ 2241 function getHostProps$2(element, props) { 2242 var node = element; 2243 2244 if (props.dangerouslySetInnerHTML != null) { 2245 throw new Error('`dangerouslySetInnerHTML` does not make sense on <textarea>.'); 2246 } // Always set children to the same thing. In IE9, the selection range will 2247 // get reset if `textContent` is mutated. We could add a check in setTextContent 2248 // to only set the value if/when the value differs from the node value (which would 2249 // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this 2250 // solution. The value can be a boolean or object so that's why it's forced 2251 // to be a string. 2252 2253 2254 var hostProps = assign({}, props, { 2255 value: undefined, 2256 defaultValue: undefined, 2257 children: toString(node._wrapperState.initialValue) 2258 }); 2259 2260 return hostProps; 2261 } 2262 function initWrapperState$2(element, props) { 2263 var node = element; 2264 2265 { 2266 checkControlledValueProps('textarea', props); 2267 2268 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) { 2269 error('%s contains a textarea with both value and defaultValue props. ' + '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://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component'); 2270 2271 didWarnValDefaultVal = true; 2272 } 2273 } 2274 2275 var initialValue = props.value; // Only bother fetching default value if we're going to use it 2276 2277 if (initialValue == null) { 2278 var children = props.children, 2279 defaultValue = props.defaultValue; 2280 2281 if (children != null) { 2282 { 2283 error('Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.'); 2284 } 2285 2286 { 2287 if (defaultValue != null) { 2288 throw new Error('If you supply `defaultValue` on a <textarea>, do not pass children.'); 2289 } 2290 2291 if (isArray(children)) { 2292 if (children.length > 1) { 2293 throw new Error('<textarea> can only have at most one child.'); 2294 } 2295 2296 children = children[0]; 2297 } 2298 2299 defaultValue = children; 2300 } 2301 } 2302 2303 if (defaultValue == null) { 2304 defaultValue = ''; 2305 } 2306 2307 initialValue = defaultValue; 2308 } 2309 2310 node._wrapperState = { 2311 initialValue: getToStringValue(initialValue) 2312 }; 2313 } 2314 function updateWrapper$1(element, props) { 2315 var node = element; 2316 var value = getToStringValue(props.value); 2317 var defaultValue = getToStringValue(props.defaultValue); 2318 2319 if (value != null) { 2320 // Cast `value` to a string to ensure the value is set correctly. While 2321 // browsers typically do this as necessary, jsdom doesn't. 2322 var newValue = toString(value); // To avoid side effects (such as losing text selection), only set value if changed 2323 2324 if (newValue !== node.value) { 2325 node.value = newValue; 2326 } 2327 2328 if (props.defaultValue == null && node.defaultValue !== newValue) { 2329 node.defaultValue = newValue; 2330 } 2331 } 2332 2333 if (defaultValue != null) { 2334 node.defaultValue = toString(defaultValue); 2335 } 2336 } 2337 function postMountWrapper$3(element, props) { 2338 var node = element; // This is in postMount because we need access to the DOM node, which is not 2339 // available until after the component has mounted. 2340 2341 var textContent = node.textContent; // Only set node.value if textContent is equal to the expected 2342 // initial value. In IE10/IE11 there is a bug where the placeholder attribute 2343 // will populate textContent as well. 2344 // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/ 2345 2346 if (textContent === node._wrapperState.initialValue) { 2347 if (textContent !== '' && textContent !== null) { 2348 node.value = textContent; 2349 } 2350 } 2351 } 2352 function restoreControlledState$2(element, props) { 2353 // DOM component is still mounted; update 2354 updateWrapper$1(element, props); 2355 } 2356 2357 var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; 2358 var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML'; 2359 var SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; // Assumes there is no parent namespace. 2360 2361 function getIntrinsicNamespace(type) { 2362 switch (type) { 2363 case 'svg': 2364 return SVG_NAMESPACE; 2365 2366 case 'math': 2367 return MATH_NAMESPACE; 2368 2369 default: 2370 return HTML_NAMESPACE; 2371 } 2372 } 2373 function getChildNamespace(parentNamespace, type) { 2374 if (parentNamespace == null || parentNamespace === HTML_NAMESPACE) { 2375 // No (or default) parent namespace: potential entry point. 2376 return getIntrinsicNamespace(type); 2377 } 2378 2379 if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') { 2380 // We're leaving SVG. 2381 return HTML_NAMESPACE; 2382 } // By default, pass namespace below. 2383 2384 2385 return parentNamespace; 2386 } 2387 2388 /* globals MSApp */ 2389 2390 /** 2391 * Create a function which has 'unsafe' privileges (required by windows8 apps) 2392 */ 2393 var createMicrosoftUnsafeLocalFunction = function (func) { 2394 if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) { 2395 return function (arg0, arg1, arg2, arg3) { 2396 MSApp.execUnsafeLocalFunction(function () { 2397 return func(arg0, arg1, arg2, arg3); 2398 }); 2399 }; 2400 } else { 2401 return func; 2402 } 2403 }; 2404 2405 var reusableSVGContainer; 2406 /** 2407 * Set the innerHTML property of a node 2408 * 2409 * @param {DOMElement} node 2410 * @param {string} html 2411 * @internal 2412 */ 2413 2414 var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) { 2415 if (node.namespaceURI === SVG_NAMESPACE) { 2416 2417 if (!('innerHTML' in node)) { 2418 // IE does not have innerHTML for SVG nodes, so instead we inject the 2419 // new markup in a temp node and then move the child nodes across into 2420 // the target node 2421 reusableSVGContainer = reusableSVGContainer || document.createElement('div'); 2422 reusableSVGContainer.innerHTML = '<svg>' + html.valueOf().toString() + '</svg>'; 2423 var svgNode = reusableSVGContainer.firstChild; 2424 2425 while (node.firstChild) { 2426 node.removeChild(node.firstChild); 2427 } 2428 2429 while (svgNode.firstChild) { 2430 node.appendChild(svgNode.firstChild); 2431 } 2432 2433 return; 2434 } 2435 } 2436 2437 node.innerHTML = html; 2438 }); 2439 2440 /** 2441 * HTML nodeType values that represent the type of the node 2442 */ 2443 var ELEMENT_NODE = 1; 2444 var TEXT_NODE = 3; 2445 var COMMENT_NODE = 8; 2446 var DOCUMENT_NODE = 9; 2447 var DOCUMENT_FRAGMENT_NODE = 11; 2448 2449 /** 2450 * Set the textContent property of a node. For text updates, it's faster 2451 * to set the `nodeValue` of the Text node directly instead of using 2452 * `.textContent` which will remove the existing node and create a new one. 2453 * 2454 * @param {DOMElement} node 2455 * @param {string} text 2456 * @internal 2457 */ 2458 2459 var setTextContent = function (node, text) { 2460 if (text) { 2461 var firstChild = node.firstChild; 2462 2463 if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) { 2464 firstChild.nodeValue = text; 2465 return; 2466 } 2467 } 2468 2469 node.textContent = text; 2470 }; 2471 2472 // List derived from Gecko source code: 2473 // https://github.com/mozilla/gecko-dev/blob/4e638efc71/layout/style/test/property_database.js 2474 var shorthandToLonghand = { 2475 animation: ['animationDelay', 'animationDirection', 'animationDuration', 'animationFillMode', 'animationIterationCount', 'animationName', 'animationPlayState', 'animationTimingFunction'], 2476 background: ['backgroundAttachment', 'backgroundClip', 'backgroundColor', 'backgroundImage', 'backgroundOrigin', 'backgroundPositionX', 'backgroundPositionY', 'backgroundRepeat', 'backgroundSize'], 2477 backgroundPosition: ['backgroundPositionX', 'backgroundPositionY'], 2478 border: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth', 'borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth', 'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderTopColor', 'borderTopStyle', 'borderTopWidth'], 2479 borderBlockEnd: ['borderBlockEndColor', 'borderBlockEndStyle', 'borderBlockEndWidth'], 2480 borderBlockStart: ['borderBlockStartColor', 'borderBlockStartStyle', 'borderBlockStartWidth'], 2481 borderBottom: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth'], 2482 borderColor: ['borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor'], 2483 borderImage: ['borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth'], 2484 borderInlineEnd: ['borderInlineEndColor', 'borderInlineEndStyle', 'borderInlineEndWidth'], 2485 borderInlineStart: ['borderInlineStartColor', 'borderInlineStartStyle', 'borderInlineStartWidth'], 2486 borderLeft: ['borderLeftColor', 'borderLeftStyle', 'borderLeftWidth'], 2487 borderRadius: ['borderBottomLeftRadius', 'borderBottomRightRadius', 'borderTopLeftRadius', 'borderTopRightRadius'], 2488 borderRight: ['borderRightColor', 'borderRightStyle', 'borderRightWidth'], 2489 borderStyle: ['borderBottomStyle', 'borderLeftStyle', 'borderRightStyle', 'borderTopStyle'], 2490 borderTop: ['borderTopColor', 'borderTopStyle', 'borderTopWidth'], 2491 borderWidth: ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth'], 2492 columnRule: ['columnRuleColor', 'columnRuleStyle', 'columnRuleWidth'], 2493 columns: ['columnCount', 'columnWidth'], 2494 flex: ['flexBasis', 'flexGrow', 'flexShrink'], 2495 flexFlow: ['flexDirection', 'flexWrap'], 2496 font: ['fontFamily', 'fontFeatureSettings', 'fontKerning', 'fontLanguageOverride', 'fontSize', 'fontSizeAdjust', 'fontStretch', 'fontStyle', 'fontVariant', 'fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition', 'fontWeight', 'lineHeight'], 2497 fontVariant: ['fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition'], 2498 gap: ['columnGap', 'rowGap'], 2499 grid: ['gridAutoColumns', 'gridAutoFlow', 'gridAutoRows', 'gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'], 2500 gridArea: ['gridColumnEnd', 'gridColumnStart', 'gridRowEnd', 'gridRowStart'], 2501 gridColumn: ['gridColumnEnd', 'gridColumnStart'], 2502 gridColumnGap: ['columnGap'], 2503 gridGap: ['columnGap', 'rowGap'], 2504 gridRow: ['gridRowEnd', 'gridRowStart'], 2505 gridRowGap: ['rowGap'], 2506 gridTemplate: ['gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'], 2507 listStyle: ['listStyleImage', 'listStylePosition', 'listStyleType'], 2508 margin: ['marginBottom', 'marginLeft', 'marginRight', 'marginTop'], 2509 marker: ['markerEnd', 'markerMid', 'markerStart'], 2510 mask: ['maskClip', 'maskComposite', 'maskImage', 'maskMode', 'maskOrigin', 'maskPositionX', 'maskPositionY', 'maskRepeat', 'maskSize'], 2511 maskPosition: ['maskPositionX', 'maskPositionY'], 2512 outline: ['outlineColor', 'outlineStyle', 'outlineWidth'], 2513 overflow: ['overflowX', 'overflowY'], 2514 padding: ['paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop'], 2515 placeContent: ['alignContent', 'justifyContent'], 2516 placeItems: ['alignItems', 'justifyItems'], 2517 placeSelf: ['alignSelf', 'justifySelf'], 2518 textDecoration: ['textDecorationColor', 'textDecorationLine', 'textDecorationStyle'], 2519 textEmphasis: ['textEmphasisColor', 'textEmphasisStyle'], 2520 transition: ['transitionDelay', 'transitionDuration', 'transitionProperty', 'transitionTimingFunction'], 2521 wordWrap: ['overflowWrap'] 2522 }; 2523 2524 /** 2525 * CSS properties which accept numbers but are not in units of "px". 2526 */ 2527 var isUnitlessNumber = { 2528 animationIterationCount: true, 2529 aspectRatio: true, 2530 borderImageOutset: true, 2531 borderImageSlice: true, 2532 borderImageWidth: true, 2533 boxFlex: true, 2534 boxFlexGroup: true, 2535 boxOrdinalGroup: true, 2536 columnCount: true, 2537 columns: true, 2538 flex: true, 2539 flexGrow: true, 2540 flexPositive: true, 2541 flexShrink: true, 2542 flexNegative: true, 2543 flexOrder: true, 2544 gridArea: true, 2545 gridRow: true, 2546 gridRowEnd: true, 2547 gridRowSpan: true, 2548 gridRowStart: true, 2549 gridColumn: true, 2550 gridColumnEnd: true, 2551 gridColumnSpan: true, 2552 gridColumnStart: true, 2553 fontWeight: true, 2554 lineClamp: true, 2555 lineHeight: true, 2556 opacity: true, 2557 order: true, 2558 orphans: true, 2559 tabSize: true, 2560 widows: true, 2561 zIndex: true, 2562 zoom: true, 2563 // SVG-related properties 2564 fillOpacity: true, 2565 floodOpacity: true, 2566 stopOpacity: true, 2567 strokeDasharray: true, 2568 strokeDashoffset: true, 2569 strokeMiterlimit: true, 2570 strokeOpacity: true, 2571 strokeWidth: true 2572 }; 2573 /** 2574 * @param {string} prefix vendor-specific prefix, eg: Webkit 2575 * @param {string} key style name, eg: transitionDuration 2576 * @return {string} style name prefixed with `prefix`, properly camelCased, eg: 2577 * WebkitTransitionDuration 2578 */ 2579 2580 function prefixKey(prefix, key) { 2581 return prefix + key.charAt(0).toUpperCase() + key.substring(1); 2582 } 2583 /** 2584 * Support style names that may come passed in prefixed by adding permutations 2585 * of vendor prefixes. 2586 */ 2587 2588 2589 var prefixes = ['Webkit', 'ms', 'Moz', 'O']; // Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an 2590 // infinite loop, because it iterates over the newly added props too. 2591 2592 Object.keys(isUnitlessNumber).forEach(function (prop) { 2593 prefixes.forEach(function (prefix) { 2594 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; 2595 }); 2596 }); 2597 2598 /** 2599 * Convert a value into the proper css writable value. The style name `name` 2600 * should be logical (no hyphens), as specified 2601 * in `CSSProperty.isUnitlessNumber`. 2602 * 2603 * @param {string} name CSS property name such as `topMargin`. 2604 * @param {*} value CSS property value such as `10px`. 2605 * @return {string} Normalized style value with dimensions applied. 2606 */ 2607 2608 function dangerousStyleValue(name, value, isCustomProperty) { 2609 // Note that we've removed escapeTextForBrowser() calls here since the 2610 // whole string will be escaped when the attribute is injected into 2611 // the markup. If you provide unsafe user data here they can inject 2612 // arbitrary CSS which may be problematic (I couldn't repro this): 2613 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet 2614 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/ 2615 // This is not an XSS hole but instead a potential CSS injection issue 2616 // which has lead to a greater discussion about how we're going to 2617 // trust URLs moving forward. See #2115901 2618 var isEmpty = value == null || typeof value === 'boolean' || value === ''; 2619 2620 if (isEmpty) { 2621 return ''; 2622 } 2623 2624 if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) { 2625 return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers 2626 } 2627 2628 { 2629 checkCSSPropertyStringCoercion(value, name); 2630 } 2631 2632 return ('' + value).trim(); 2633 } 2634 2635 var uppercasePattern = /([A-Z])/g; 2636 var msPattern = /^ms-/; 2637 /** 2638 * Hyphenates a camelcased CSS property name, for example: 2639 * 2640 * > hyphenateStyleName('backgroundColor') 2641 * < "background-color" 2642 * > hyphenateStyleName('MozTransition') 2643 * < "-moz-transition" 2644 * > hyphenateStyleName('msTransition') 2645 * < "-ms-transition" 2646 * 2647 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix 2648 * is converted to `-ms-`. 2649 */ 2650 2651 function hyphenateStyleName(name) { 2652 return name.replace(uppercasePattern, '-$1').toLowerCase().replace(msPattern, '-ms-'); 2653 } 2654 2655 var warnValidStyle = function () {}; 2656 2657 { 2658 // 'msTransform' is correct, but the other prefixes should be capitalized 2659 var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/; 2660 var msPattern$1 = /^-ms-/; 2661 var hyphenPattern = /-(.)/g; // style values shouldn't contain a semicolon 2662 2663 var badStyleValueWithSemicolonPattern = /;\s*$/; 2664 var warnedStyleNames = {}; 2665 var warnedStyleValues = {}; 2666 var warnedForNaNValue = false; 2667 var warnedForInfinityValue = false; 2668 2669 var camelize = function (string) { 2670 return string.replace(hyphenPattern, function (_, character) { 2671 return character.toUpperCase(); 2672 }); 2673 }; 2674 2675 var warnHyphenatedStyleName = function (name) { 2676 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { 2677 return; 2678 } 2679 2680 warnedStyleNames[name] = true; 2681 2682 error('Unsupported style property %s. Did you mean %s?', name, // As Andi Smith suggests 2683 // (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix 2684 // is converted to lowercase `ms`. 2685 camelize(name.replace(msPattern$1, 'ms-'))); 2686 }; 2687 2688 var warnBadVendoredStyleName = function (name) { 2689 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { 2690 return; 2691 } 2692 2693 warnedStyleNames[name] = true; 2694 2695 error('Unsupported vendor-prefixed style property %s. Did you mean %s?', name, name.charAt(0).toUpperCase() + name.slice(1)); 2696 }; 2697 2698 var warnStyleValueWithSemicolon = function (name, value) { 2699 if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) { 2700 return; 2701 } 2702 2703 warnedStyleValues[value] = true; 2704 2705 error("Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.', name, value.replace(badStyleValueWithSemicolonPattern, '')); 2706 }; 2707 2708 var warnStyleValueIsNaN = function (name, value) { 2709 if (warnedForNaNValue) { 2710 return; 2711 } 2712 2713 warnedForNaNValue = true; 2714 2715 error('`NaN` is an invalid value for the `%s` css style property.', name); 2716 }; 2717 2718 var warnStyleValueIsInfinity = function (name, value) { 2719 if (warnedForInfinityValue) { 2720 return; 2721 } 2722 2723 warnedForInfinityValue = true; 2724 2725 error('`Infinity` is an invalid value for the `%s` css style property.', name); 2726 }; 2727 2728 warnValidStyle = function (name, value) { 2729 if (name.indexOf('-') > -1) { 2730 warnHyphenatedStyleName(name); 2731 } else if (badVendoredStyleNamePattern.test(name)) { 2732 warnBadVendoredStyleName(name); 2733 } else if (badStyleValueWithSemicolonPattern.test(value)) { 2734 warnStyleValueWithSemicolon(name, value); 2735 } 2736 2737 if (typeof value === 'number') { 2738 if (isNaN(value)) { 2739 warnStyleValueIsNaN(name, value); 2740 } else if (!isFinite(value)) { 2741 warnStyleValueIsInfinity(name, value); 2742 } 2743 } 2744 }; 2745 } 2746 2747 var warnValidStyle$1 = warnValidStyle; 2748 2749 /** 2750 * Operations for dealing with CSS properties. 2751 */ 2752 2753 /** 2754 * This creates a string that is expected to be equivalent to the style 2755 * attribute generated by server-side rendering. It by-passes warnings and 2756 * security checks so it's not safe to use this value for anything other than 2757 * comparison. It is only used in DEV for SSR validation. 2758 */ 2759 2760 function createDangerousStringForStyles(styles) { 2761 { 2762 var serialized = ''; 2763 var delimiter = ''; 2764 2765 for (var styleName in styles) { 2766 if (!styles.hasOwnProperty(styleName)) { 2767 continue; 2768 } 2769 2770 var styleValue = styles[styleName]; 2771 2772 if (styleValue != null) { 2773 var isCustomProperty = styleName.indexOf('--') === 0; 2774 serialized += delimiter + (isCustomProperty ? styleName : hyphenateStyleName(styleName)) + ':'; 2775 serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty); 2776 delimiter = ';'; 2777 } 2778 } 2779 2780 return serialized || null; 2781 } 2782 } 2783 /** 2784 * Sets the value for multiple styles on a node. If a value is specified as 2785 * '' (empty string), the corresponding style property will be unset. 2786 * 2787 * @param {DOMElement} node 2788 * @param {object} styles 2789 */ 2790 2791 function setValueForStyles(node, styles) { 2792 var style = node.style; 2793 2794 for (var styleName in styles) { 2795 if (!styles.hasOwnProperty(styleName)) { 2796 continue; 2797 } 2798 2799 var isCustomProperty = styleName.indexOf('--') === 0; 2800 2801 { 2802 if (!isCustomProperty) { 2803 warnValidStyle$1(styleName, styles[styleName]); 2804 } 2805 } 2806 2807 var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty); 2808 2809 if (styleName === 'float') { 2810 styleName = 'cssFloat'; 2811 } 2812 2813 if (isCustomProperty) { 2814 style.setProperty(styleName, styleValue); 2815 } else { 2816 style[styleName] = styleValue; 2817 } 2818 } 2819 } 2820 2821 function isValueEmpty(value) { 2822 return value == null || typeof value === 'boolean' || value === ''; 2823 } 2824 /** 2825 * Given {color: 'red', overflow: 'hidden'} returns { 2826 * color: 'color', 2827 * overflowX: 'overflow', 2828 * overflowY: 'overflow', 2829 * }. This can be read as "the overflowY property was set by the overflow 2830 * shorthand". That is, the values are the property that each was derived from. 2831 */ 2832 2833 2834 function expandShorthandMap(styles) { 2835 var expanded = {}; 2836 2837 for (var key in styles) { 2838 var longhands = shorthandToLonghand[key] || [key]; 2839 2840 for (var i = 0; i < longhands.length; i++) { 2841 expanded[longhands[i]] = key; 2842 } 2843 } 2844 2845 return expanded; 2846 } 2847 /** 2848 * When mixing shorthand and longhand property names, we warn during updates if 2849 * we expect an incorrect result to occur. In particular, we warn for: 2850 * 2851 * Updating a shorthand property (longhand gets overwritten): 2852 * {font: 'foo', fontVariant: 'bar'} -> {font: 'baz', fontVariant: 'bar'} 2853 * becomes .style.font = 'baz' 2854 * Removing a shorthand property (longhand gets lost too): 2855 * {font: 'foo', fontVariant: 'bar'} -> {fontVariant: 'bar'} 2856 * becomes .style.font = '' 2857 * Removing a longhand property (should revert to shorthand; doesn't): 2858 * {font: 'foo', fontVariant: 'bar'} -> {font: 'foo'} 2859 * becomes .style.fontVariant = '' 2860 */ 2861 2862 2863 function validateShorthandPropertyCollisionInDev(styleUpdates, nextStyles) { 2864 { 2865 if (!nextStyles) { 2866 return; 2867 } 2868 2869 var expandedUpdates = expandShorthandMap(styleUpdates); 2870 var expandedStyles = expandShorthandMap(nextStyles); 2871 var warnedAbout = {}; 2872 2873 for (var key in expandedUpdates) { 2874 var originalKey = expandedUpdates[key]; 2875 var correctOriginalKey = expandedStyles[key]; 2876 2877 if (correctOriginalKey && originalKey !== correctOriginalKey) { 2878 var warningKey = originalKey + ',' + correctOriginalKey; 2879 2880 if (warnedAbout[warningKey]) { 2881 continue; 2882 } 2883 2884 warnedAbout[warningKey] = true; 2885 2886 error('%s a style property during rerender (%s) when a ' + 'conflicting property is set (%s) can lead to styling bugs. To ' + "avoid this, don't mix shorthand and non-shorthand properties " + 'for the same value; instead, replace the shorthand with ' + 'separate values.', isValueEmpty(styleUpdates[originalKey]) ? 'Removing' : 'Updating', originalKey, correctOriginalKey); 2887 } 2888 } 2889 } 2890 } 2891 2892 // For HTML, certain tags should omit their close tag. We keep a list for 2893 // those special-case tags. 2894 var omittedCloseTags = { 2895 area: true, 2896 base: true, 2897 br: true, 2898 col: true, 2899 embed: true, 2900 hr: true, 2901 img: true, 2902 input: true, 2903 keygen: true, 2904 link: true, 2905 meta: true, 2906 param: true, 2907 source: true, 2908 track: true, 2909 wbr: true // NOTE: menuitem's close tag should be omitted, but that causes problems. 2910 2911 }; 2912 2913 // `omittedCloseTags` except that `menuitem` should still have its closing tag. 2914 2915 var voidElementTags = assign({ 2916 menuitem: true 2917 }, omittedCloseTags); 2918 2919 var HTML = '__html'; 2920 2921 function assertValidProps(tag, props) { 2922 if (!props) { 2923 return; 2924 } // Note the use of `==` which checks for null or undefined. 2925 2926 2927 if (voidElementTags[tag]) { 2928 if (props.children != null || props.dangerouslySetInnerHTML != null) { 2929 throw new Error(tag + " is a void element tag and must neither have `children` nor " + 'use `dangerouslySetInnerHTML`.'); 2930 } 2931 } 2932 2933 if (props.dangerouslySetInnerHTML != null) { 2934 if (props.children != null) { 2935 throw new Error('Can only set one of `children` or `props.dangerouslySetInnerHTML`.'); 2936 } 2937 2938 if (typeof props.dangerouslySetInnerHTML !== 'object' || !(HTML in props.dangerouslySetInnerHTML)) { 2939 throw new Error('`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://reactjs.org/link/dangerously-set-inner-html ' + 'for more information.'); 2940 } 2941 } 2942 2943 { 2944 if (!props.suppressContentEditableWarning && props.contentEditable && props.children != null) { 2945 error('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.'); 2946 } 2947 } 2948 2949 if (props.style != null && typeof props.style !== 'object') { 2950 throw new Error('The `style` prop expects a mapping from style properties to values, ' + "not a string. For example, style={{marginRight: spacing + 'em'}} when " + 'using JSX.'); 2951 } 2952 } 2953 2954 function isCustomComponent(tagName, props) { 2955 if (tagName.indexOf('-') === -1) { 2956 return typeof props.is === 'string'; 2957 } 2958 2959 switch (tagName) { 2960 // These are reserved SVG and MathML elements. 2961 // We don't mind this list too much because we expect it to never grow. 2962 // The alternative is to track the namespace in a few places which is convoluted. 2963 // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts 2964 case 'annotation-xml': 2965 case 'color-profile': 2966 case 'font-face': 2967 case 'font-face-src': 2968 case 'font-face-uri': 2969 case 'font-face-format': 2970 case 'font-face-name': 2971 case 'missing-glyph': 2972 return false; 2973 2974 default: 2975 return true; 2976 } 2977 } 2978 2979 // When adding attributes to the HTML or SVG allowed attribute list, be sure to 2980 // also add them to this module to ensure casing and incorrect name 2981 // warnings. 2982 var possibleStandardNames = { 2983 // HTML 2984 accept: 'accept', 2985 acceptcharset: 'acceptCharset', 2986 'accept-charset': 'acceptCharset', 2987 accesskey: 'accessKey', 2988 action: 'action', 2989 allowfullscreen: 'allowFullScreen', 2990 alt: 'alt', 2991 as: 'as', 2992 async: 'async', 2993 autocapitalize: 'autoCapitalize', 2994 autocomplete: 'autoComplete', 2995 autocorrect: 'autoCorrect', 2996 autofocus: 'autoFocus', 2997 autoplay: 'autoPlay', 2998 autosave: 'autoSave', 2999 capture: 'capture', 3000 cellpadding: 'cellPadding', 3001 cellspacing: 'cellSpacing', 3002 challenge: 'challenge', 3003 charset: 'charSet', 3004 checked: 'checked', 3005 children: 'children', 3006 cite: 'cite', 3007 class: 'className', 3008 classid: 'classID', 3009 classname: 'className', 3010 cols: 'cols', 3011 colspan: 'colSpan', 3012 content: 'content', 3013 contenteditable: 'contentEditable', 3014 contextmenu: 'contextMenu', 3015 controls: 'controls', 3016 controlslist: 'controlsList', 3017 coords: 'coords', 3018 crossorigin: 'crossOrigin', 3019 dangerouslysetinnerhtml: 'dangerouslySetInnerHTML', 3020 data: 'data', 3021 datetime: 'dateTime', 3022 default: 'default', 3023 defaultchecked: 'defaultChecked', 3024 defaultvalue: 'defaultValue', 3025 defer: 'defer', 3026 dir: 'dir', 3027 disabled: 'disabled', 3028 disablepictureinpicture: 'disablePictureInPicture', 3029 disableremoteplayback: 'disableRemotePlayback', 3030 download: 'download', 3031 draggable: 'draggable', 3032 enctype: 'encType', 3033 enterkeyhint: 'enterKeyHint', 3034 for: 'htmlFor', 3035 form: 'form', 3036 formmethod: 'formMethod', 3037 formaction: 'formAction', 3038 formenctype: 'formEncType', 3039 formnovalidate: 'formNoValidate', 3040 formtarget: 'formTarget', 3041 frameborder: 'frameBorder', 3042 headers: 'headers', 3043 height: 'height', 3044 hidden: 'hidden', 3045 high: 'high', 3046 href: 'href', 3047 hreflang: 'hrefLang', 3048 htmlfor: 'htmlFor', 3049 httpequiv: 'httpEquiv', 3050 'http-equiv': 'httpEquiv', 3051 icon: 'icon', 3052 id: 'id', 3053 imagesizes: 'imageSizes', 3054 imagesrcset: 'imageSrcSet', 3055 innerhtml: 'innerHTML', 3056 inputmode: 'inputMode', 3057 integrity: 'integrity', 3058 is: 'is', 3059 itemid: 'itemID', 3060 itemprop: 'itemProp', 3061 itemref: 'itemRef', 3062 itemscope: 'itemScope', 3063 itemtype: 'itemType', 3064 keyparams: 'keyParams', 3065 keytype: 'keyType', 3066 kind: 'kind', 3067 label: 'label', 3068 lang: 'lang', 3069 list: 'list', 3070 loop: 'loop', 3071 low: 'low', 3072 manifest: 'manifest', 3073 marginwidth: 'marginWidth', 3074 marginheight: 'marginHeight', 3075 max: 'max', 3076 maxlength: 'maxLength', 3077 media: 'media', 3078 mediagroup: 'mediaGroup', 3079 method: 'method', 3080 min: 'min', 3081 minlength: 'minLength', 3082 multiple: 'multiple', 3083 muted: 'muted', 3084 name: 'name', 3085 nomodule: 'noModule', 3086 nonce: 'nonce', 3087 novalidate: 'noValidate', 3088 open: 'open', 3089 optimum: 'optimum', 3090 pattern: 'pattern', 3091 placeholder: 'placeholder', 3092 playsinline: 'playsInline', 3093 poster: 'poster', 3094 preload: 'preload', 3095 profile: 'profile', 3096 radiogroup: 'radioGroup', 3097 readonly: 'readOnly', 3098 referrerpolicy: 'referrerPolicy', 3099 rel: 'rel', 3100 required: 'required', 3101 reversed: 'reversed', 3102 role: 'role', 3103 rows: 'rows', 3104 rowspan: 'rowSpan', 3105 sandbox: 'sandbox', 3106 scope: 'scope', 3107 scoped: 'scoped', 3108 scrolling: 'scrolling', 3109 seamless: 'seamless', 3110 selected: 'selected', 3111 shape: 'shape', 3112 size: 'size', 3113 sizes: 'sizes', 3114 span: 'span', 3115 spellcheck: 'spellCheck', 3116 src: 'src', 3117 srcdoc: 'srcDoc', 3118 srclang: 'srcLang', 3119 srcset: 'srcSet', 3120 start: 'start', 3121 step: 'step', 3122 style: 'style', 3123 summary: 'summary', 3124 tabindex: 'tabIndex', 3125 target: 'target', 3126 title: 'title', 3127 type: 'type', 3128 usemap: 'useMap', 3129 value: 'value', 3130 width: 'width', 3131 wmode: 'wmode', 3132 wrap: 'wrap', 3133 // SVG 3134 about: 'about', 3135 accentheight: 'accentHeight', 3136 'accent-height': 'accentHeight', 3137 accumulate: 'accumulate', 3138 additive: 'additive', 3139 alignmentbaseline: 'alignmentBaseline', 3140 'alignment-baseline': 'alignmentBaseline', 3141 allowreorder: 'allowReorder', 3142 alphabetic: 'alphabetic', 3143 amplitude: 'amplitude', 3144 arabicform: 'arabicForm', 3145 'arabic-form': 'arabicForm', 3146 ascent: 'ascent', 3147 attributename: 'attributeName', 3148 attributetype: 'attributeType', 3149 autoreverse: 'autoReverse', 3150 azimuth: 'azimuth', 3151 basefrequency: 'baseFrequency', 3152 baselineshift: 'baselineShift', 3153 'baseline-shift': 'baselineShift', 3154 baseprofile: 'baseProfile', 3155 bbox: 'bbox', 3156 begin: 'begin', 3157 bias: 'bias', 3158 by: 'by', 3159 calcmode: 'calcMode', 3160 capheight: 'capHeight', 3161 'cap-height': 'capHeight', 3162 clip: 'clip', 3163 clippath: 'clipPath', 3164 'clip-path': 'clipPath', 3165 clippathunits: 'clipPathUnits', 3166 cliprule: 'clipRule', 3167 'clip-rule': 'clipRule', 3168 color: 'color', 3169 colorinterpolation: 'colorInterpolation', 3170 'color-interpolation': 'colorInterpolation', 3171 colorinterpolationfilters: 'colorInterpolationFilters', 3172 'color-interpolation-filters': 'colorInterpolationFilters', 3173 colorprofile: 'colorProfile', 3174 'color-profile': 'colorProfile', 3175 colorrendering: 'colorRendering', 3176 'color-rendering': 'colorRendering', 3177 contentscripttype: 'contentScriptType', 3178 contentstyletype: 'contentStyleType', 3179 cursor: 'cursor', 3180 cx: 'cx', 3181 cy: 'cy', 3182 d: 'd', 3183 datatype: 'datatype', 3184 decelerate: 'decelerate', 3185 descent: 'descent', 3186 diffuseconstant: 'diffuseConstant', 3187 direction: 'direction', 3188 display: 'display', 3189 divisor: 'divisor', 3190 dominantbaseline: 'dominantBaseline', 3191 'dominant-baseline': 'dominantBaseline', 3192 dur: 'dur', 3193 dx: 'dx', 3194 dy: 'dy', 3195 edgemode: 'edgeMode', 3196 elevation: 'elevation', 3197 enablebackground: 'enableBackground', 3198 'enable-background': 'enableBackground', 3199 end: 'end', 3200 exponent: 'exponent', 3201 externalresourcesrequired: 'externalResourcesRequired', 3202 fill: 'fill', 3203 fillopacity: 'fillOpacity', 3204 'fill-opacity': 'fillOpacity', 3205 fillrule: 'fillRule', 3206 'fill-rule': 'fillRule', 3207 filter: 'filter', 3208 filterres: 'filterRes', 3209 filterunits: 'filterUnits', 3210 floodopacity: 'floodOpacity', 3211 'flood-opacity': 'floodOpacity', 3212 floodcolor: 'floodColor', 3213 'flood-color': 'floodColor', 3214 focusable: 'focusable', 3215 fontfamily: 'fontFamily', 3216 'font-family': 'fontFamily', 3217 fontsize: 'fontSize', 3218 'font-size': 'fontSize', 3219 fontsizeadjust: 'fontSizeAdjust', 3220 'font-size-adjust': 'fontSizeAdjust', 3221 fontstretch: 'fontStretch', 3222 'font-stretch': 'fontStretch', 3223 fontstyle: 'fontStyle', 3224 'font-style': 'fontStyle', 3225 fontvariant: 'fontVariant', 3226 'font-variant': 'fontVariant', 3227 fontweight: 'fontWeight', 3228 'font-weight': 'fontWeight', 3229 format: 'format', 3230 from: 'from', 3231 fx: 'fx', 3232 fy: 'fy', 3233 g1: 'g1', 3234 g2: 'g2', 3235 glyphname: 'glyphName', 3236 'glyph-name': 'glyphName', 3237 glyphorientationhorizontal: 'glyphOrientationHorizontal', 3238 'glyph-orientation-horizontal': 'glyphOrientationHorizontal', 3239 glyphorientationvertical: 'glyphOrientationVertical', 3240 'glyph-orientation-vertical': 'glyphOrientationVertical', 3241 glyphref: 'glyphRef', 3242 gradienttransform: 'gradientTransform', 3243 gradientunits: 'gradientUnits', 3244 hanging: 'hanging', 3245 horizadvx: 'horizAdvX', 3246 'horiz-adv-x': 'horizAdvX', 3247 horizoriginx: 'horizOriginX', 3248 'horiz-origin-x': 'horizOriginX', 3249 ideographic: 'ideographic', 3250 imagerendering: 'imageRendering', 3251 'image-rendering': 'imageRendering', 3252 in2: 'in2', 3253 in: 'in', 3254 inlist: 'inlist', 3255 intercept: 'intercept', 3256 k1: 'k1', 3257 k2: 'k2', 3258 k3: 'k3', 3259 k4: 'k4', 3260 k: 'k', 3261 kernelmatrix: 'kernelMatrix', 3262 kernelunitlength: 'kernelUnitLength', 3263 kerning: 'kerning', 3264 keypoints: 'keyPoints', 3265 keysplines: 'keySplines', 3266 keytimes: 'keyTimes', 3267 lengthadjust: 'lengthAdjust', 3268 letterspacing: 'letterSpacing', 3269 'letter-spacing': 'letterSpacing', 3270 lightingcolor: 'lightingColor', 3271 'lighting-color': 'lightingColor', 3272 limitingconeangle: 'limitingConeAngle', 3273 local: 'local', 3274 markerend: 'markerEnd', 3275 'marker-end': 'markerEnd', 3276 markerheight: 'markerHeight', 3277 markermid: 'markerMid', 3278 'marker-mid': 'markerMid', 3279 markerstart: 'markerStart', 3280 'marker-start': 'markerStart', 3281 markerunits: 'markerUnits', 3282 markerwidth: 'markerWidth', 3283 mask: 'mask', 3284 maskcontentunits: 'maskContentUnits', 3285 maskunits: 'maskUnits', 3286 mathematical: 'mathematical', 3287 mode: 'mode', 3288 numoctaves: 'numOctaves', 3289 offset: 'offset', 3290 opacity: 'opacity', 3291 operator: 'operator', 3292 order: 'order', 3293 orient: 'orient', 3294 orientation: 'orientation', 3295 origin: 'origin', 3296 overflow: 'overflow', 3297 overlineposition: 'overlinePosition', 3298 'overline-position': 'overlinePosition', 3299 overlinethickness: 'overlineThickness', 3300 'overline-thickness': 'overlineThickness', 3301 paintorder: 'paintOrder', 3302 'paint-order': 'paintOrder', 3303 panose1: 'panose1', 3304 'panose-1': 'panose1', 3305 pathlength: 'pathLength', 3306 patterncontentunits: 'patternContentUnits', 3307 patterntransform: 'patternTransform', 3308 patternunits: 'patternUnits', 3309 pointerevents: 'pointerEvents', 3310 'pointer-events': 'pointerEvents', 3311 points: 'points', 3312 pointsatx: 'pointsAtX', 3313 pointsaty: 'pointsAtY', 3314 pointsatz: 'pointsAtZ', 3315 prefix: 'prefix', 3316 preservealpha: 'preserveAlpha', 3317 preserveaspectratio: 'preserveAspectRatio', 3318 primitiveunits: 'primitiveUnits', 3319 property: 'property', 3320 r: 'r', 3321 radius: 'radius', 3322 refx: 'refX', 3323 refy: 'refY', 3324 renderingintent: 'renderingIntent', 3325 'rendering-intent': 'renderingIntent', 3326 repeatcount: 'repeatCount', 3327 repeatdur: 'repeatDur', 3328 requiredextensions: 'requiredExtensions', 3329 requiredfeatures: 'requiredFeatures', 3330 resource: 'resource', 3331 restart: 'restart', 3332 result: 'result', 3333 results: 'results', 3334 rotate: 'rotate', 3335 rx: 'rx', 3336 ry: 'ry', 3337 scale: 'scale', 3338 security: 'security', 3339 seed: 'seed', 3340 shaperendering: 'shapeRendering', 3341 'shape-rendering': 'shapeRendering', 3342 slope: 'slope', 3343 spacing: 'spacing', 3344 specularconstant: 'specularConstant', 3345 specularexponent: 'specularExponent', 3346 speed: 'speed', 3347 spreadmethod: 'spreadMethod', 3348 startoffset: 'startOffset', 3349 stddeviation: 'stdDeviation', 3350 stemh: 'stemh', 3351 stemv: 'stemv', 3352 stitchtiles: 'stitchTiles', 3353 stopcolor: 'stopColor', 3354 'stop-color': 'stopColor', 3355 stopopacity: 'stopOpacity', 3356 'stop-opacity': 'stopOpacity', 3357 strikethroughposition: 'strikethroughPosition', 3358 'strikethrough-position': 'strikethroughPosition', 3359 strikethroughthickness: 'strikethroughThickness', 3360 'strikethrough-thickness': 'strikethroughThickness', 3361 string: 'string', 3362 stroke: 'stroke', 3363 strokedasharray: 'strokeDasharray', 3364 'stroke-dasharray': 'strokeDasharray', 3365 strokedashoffset: 'strokeDashoffset', 3366 'stroke-dashoffset': 'strokeDashoffset', 3367 strokelinecap: 'strokeLinecap', 3368 'stroke-linecap': 'strokeLinecap', 3369 strokelinejoin: 'strokeLinejoin', 3370 'stroke-linejoin': 'strokeLinejoin', 3371 strokemiterlimit: 'strokeMiterlimit', 3372 'stroke-miterlimit': 'strokeMiterlimit', 3373 strokewidth: 'strokeWidth', 3374 'stroke-width': 'strokeWidth', 3375 strokeopacity: 'strokeOpacity', 3376 'stroke-opacity': 'strokeOpacity', 3377 suppresscontenteditablewarning: 'suppressContentEditableWarning', 3378 suppresshydrationwarning: 'suppressHydrationWarning', 3379 surfacescale: 'surfaceScale', 3380 systemlanguage: 'systemLanguage', 3381 tablevalues: 'tableValues', 3382 targetx: 'targetX', 3383 targety: 'targetY', 3384 textanchor: 'textAnchor', 3385 'text-anchor': 'textAnchor', 3386 textdecoration: 'textDecoration', 3387 'text-decoration': 'textDecoration', 3388 textlength: 'textLength', 3389 textrendering: 'textRendering', 3390 'text-rendering': 'textRendering', 3391 to: 'to', 3392 transform: 'transform', 3393 typeof: 'typeof', 3394 u1: 'u1', 3395 u2: 'u2', 3396 underlineposition: 'underlinePosition', 3397 'underline-position': 'underlinePosition', 3398 underlinethickness: 'underlineThickness', 3399 'underline-thickness': 'underlineThickness', 3400 unicode: 'unicode', 3401 unicodebidi: 'unicodeBidi', 3402 'unicode-bidi': 'unicodeBidi', 3403 unicoderange: 'unicodeRange', 3404 'unicode-range': 'unicodeRange', 3405 unitsperem: 'unitsPerEm', 3406 'units-per-em': 'unitsPerEm', 3407 unselectable: 'unselectable', 3408 valphabetic: 'vAlphabetic', 3409 'v-alphabetic': 'vAlphabetic', 3410 values: 'values', 3411 vectoreffect: 'vectorEffect', 3412 'vector-effect': 'vectorEffect', 3413 version: 'version', 3414 vertadvy: 'vertAdvY', 3415 'vert-adv-y': 'vertAdvY', 3416 vertoriginx: 'vertOriginX', 3417 'vert-origin-x': 'vertOriginX', 3418 vertoriginy: 'vertOriginY', 3419 'vert-origin-y': 'vertOriginY', 3420 vhanging: 'vHanging', 3421 'v-hanging': 'vHanging', 3422 videographic: 'vIdeographic', 3423 'v-ideographic': 'vIdeographic', 3424 viewbox: 'viewBox', 3425 viewtarget: 'viewTarget', 3426 visibility: 'visibility', 3427 vmathematical: 'vMathematical', 3428 'v-mathematical': 'vMathematical', 3429 vocab: 'vocab', 3430 widths: 'widths', 3431 wordspacing: 'wordSpacing', 3432 'word-spacing': 'wordSpacing', 3433 writingmode: 'writingMode', 3434 'writing-mode': 'writingMode', 3435 x1: 'x1', 3436 x2: 'x2', 3437 x: 'x', 3438 xchannelselector: 'xChannelSelector', 3439 xheight: 'xHeight', 3440 'x-height': 'xHeight', 3441 xlinkactuate: 'xlinkActuate', 3442 'xlink:actuate': 'xlinkActuate', 3443 xlinkarcrole: 'xlinkArcrole', 3444 'xlink:arcrole': 'xlinkArcrole', 3445 xlinkhref: 'xlinkHref', 3446 'xlink:href': 'xlinkHref', 3447 xlinkrole: 'xlinkRole', 3448 'xlink:role': 'xlinkRole', 3449 xlinkshow: 'xlinkShow', 3450 'xlink:show': 'xlinkShow', 3451 xlinktitle: 'xlinkTitle', 3452 'xlink:title': 'xlinkTitle', 3453 xlinktype: 'xlinkType', 3454 'xlink:type': 'xlinkType', 3455 xmlbase: 'xmlBase', 3456 'xml:base': 'xmlBase', 3457 xmllang: 'xmlLang', 3458 'xml:lang': 'xmlLang', 3459 xmlns: 'xmlns', 3460 'xml:space': 'xmlSpace', 3461 xmlnsxlink: 'xmlnsXlink', 3462 'xmlns:xlink': 'xmlnsXlink', 3463 xmlspace: 'xmlSpace', 3464 y1: 'y1', 3465 y2: 'y2', 3466 y: 'y', 3467 ychannelselector: 'yChannelSelector', 3468 z: 'z', 3469 zoomandpan: 'zoomAndPan' 3470 }; 3471 3472 var ariaProperties = { 3473 'aria-current': 0, 3474 // state 3475 'aria-description': 0, 3476 'aria-details': 0, 3477 'aria-disabled': 0, 3478 // state 3479 'aria-hidden': 0, 3480 // state 3481 'aria-invalid': 0, 3482 // state 3483 'aria-keyshortcuts': 0, 3484 'aria-label': 0, 3485 'aria-roledescription': 0, 3486 // Widget Attributes 3487 'aria-autocomplete': 0, 3488 'aria-checked': 0, 3489 'aria-expanded': 0, 3490 'aria-haspopup': 0, 3491 'aria-level': 0, 3492 'aria-modal': 0, 3493 'aria-multiline': 0, 3494 'aria-multiselectable': 0, 3495 'aria-orientation': 0, 3496 'aria-placeholder': 0, 3497 'aria-pressed': 0, 3498 'aria-readonly': 0, 3499 'aria-required': 0, 3500 'aria-selected': 0, 3501 'aria-sort': 0, 3502 'aria-valuemax': 0, 3503 'aria-valuemin': 0, 3504 'aria-valuenow': 0, 3505 'aria-valuetext': 0, 3506 // Live Region Attributes 3507 'aria-atomic': 0, 3508 'aria-busy': 0, 3509 'aria-live': 0, 3510 'aria-relevant': 0, 3511 // Drag-and-Drop Attributes 3512 'aria-dropeffect': 0, 3513 'aria-grabbed': 0, 3514 // Relationship Attributes 3515 'aria-activedescendant': 0, 3516 'aria-colcount': 0, 3517 'aria-colindex': 0, 3518 'aria-colspan': 0, 3519 'aria-controls': 0, 3520 'aria-describedby': 0, 3521 'aria-errormessage': 0, 3522 'aria-flowto': 0, 3523 'aria-labelledby': 0, 3524 'aria-owns': 0, 3525 'aria-posinset': 0, 3526 'aria-rowcount': 0, 3527 'aria-rowindex': 0, 3528 'aria-rowspan': 0, 3529 'aria-setsize': 0 3530 }; 3531 3532 var warnedProperties = {}; 3533 var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); 3534 var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); 3535 3536 function validateProperty(tagName, name) { 3537 { 3538 if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) { 3539 return true; 3540 } 3541 3542 if (rARIACamel.test(name)) { 3543 var ariaName = 'aria-' + name.slice(4).toLowerCase(); 3544 var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null; // If this is an aria-* attribute, but is not listed in the known DOM 3545 // DOM properties, then it is an invalid aria-* attribute. 3546 3547 if (correctName == null) { 3548 error('Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.', name); 3549 3550 warnedProperties[name] = true; 3551 return true; 3552 } // aria-* attributes should be lowercase; suggest the lowercase version. 3553 3554 3555 if (name !== correctName) { 3556 error('Invalid ARIA attribute `%s`. Did you mean `%s`?', name, correctName); 3557 3558 warnedProperties[name] = true; 3559 return true; 3560 } 3561 } 3562 3563 if (rARIA.test(name)) { 3564 var lowerCasedName = name.toLowerCase(); 3565 var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null; // If this is an aria-* attribute, but is not listed in the known DOM 3566 // DOM properties, then it is an invalid aria-* attribute. 3567 3568 if (standardName == null) { 3569 warnedProperties[name] = true; 3570 return false; 3571 } // aria-* attributes should be lowercase; suggest the lowercase version. 3572 3573 3574 if (name !== standardName) { 3575 error('Unknown ARIA attribute `%s`. Did you mean `%s`?', name, standardName); 3576 3577 warnedProperties[name] = true; 3578 return true; 3579 } 3580 } 3581 } 3582 3583 return true; 3584 } 3585 3586 function warnInvalidARIAProps(type, props) { 3587 { 3588 var invalidProps = []; 3589 3590 for (var key in props) { 3591 var isValid = validateProperty(type, key); 3592 3593 if (!isValid) { 3594 invalidProps.push(key); 3595 } 3596 } 3597 3598 var unknownPropString = invalidProps.map(function (prop) { 3599 return '`' + prop + '`'; 3600 }).join(', '); 3601 3602 if (invalidProps.length === 1) { 3603 error('Invalid aria prop %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type); 3604 } else if (invalidProps.length > 1) { 3605 error('Invalid aria props %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type); 3606 } 3607 } 3608 } 3609 3610 function validateProperties(type, props) { 3611 if (isCustomComponent(type, props)) { 3612 return; 3613 } 3614 3615 warnInvalidARIAProps(type, props); 3616 } 3617 3618 var didWarnValueNull = false; 3619 function validateProperties$1(type, props) { 3620 { 3621 if (type !== 'input' && type !== 'textarea' && type !== 'select') { 3622 return; 3623 } 3624 3625 if (props != null && props.value === null && !didWarnValueNull) { 3626 didWarnValueNull = true; 3627 3628 if (type === 'select' && props.multiple) { 3629 error('`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.', type); 3630 } else { 3631 error('`value` prop on `%s` should not be null. ' + 'Consider using an empty string to clear the component or `undefined` ' + 'for uncontrolled components.', type); 3632 } 3633 } 3634 } 3635 } 3636 3637 var validateProperty$1 = function () {}; 3638 3639 { 3640 var warnedProperties$1 = {}; 3641 var EVENT_NAME_REGEX = /^on./; 3642 var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/; 3643 var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); 3644 var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); 3645 3646 validateProperty$1 = function (tagName, name, value, eventRegistry) { 3647 if (hasOwnProperty.call(warnedProperties$1, name) && warnedProperties$1[name]) { 3648 return true; 3649 } 3650 3651 var lowerCasedName = name.toLowerCase(); 3652 3653 if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') { 3654 error('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.'); 3655 3656 warnedProperties$1[name] = true; 3657 return true; 3658 } // We can't rely on the event system being injected on the server. 3659 3660 3661 if (eventRegistry != null) { 3662 var registrationNameDependencies = eventRegistry.registrationNameDependencies, 3663 possibleRegistrationNames = eventRegistry.possibleRegistrationNames; 3664 3665 if (registrationNameDependencies.hasOwnProperty(name)) { 3666 return true; 3667 } 3668 3669 var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null; 3670 3671 if (registrationName != null) { 3672 error('Invalid event handler property `%s`. Did you mean `%s`?', name, registrationName); 3673 3674 warnedProperties$1[name] = true; 3675 return true; 3676 } 3677 3678 if (EVENT_NAME_REGEX.test(name)) { 3679 error('Unknown event handler property `%s`. It will be ignored.', name); 3680 3681 warnedProperties$1[name] = true; 3682 return true; 3683 } 3684 } else if (EVENT_NAME_REGEX.test(name)) { 3685 // If no event plugins have been injected, we are in a server environment. 3686 // So we can't tell if the event name is correct for sure, but we can filter 3687 // out known bad ones like `onclick`. We can't suggest a specific replacement though. 3688 if (INVALID_EVENT_NAME_REGEX.test(name)) { 3689 error('Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.', name); 3690 } 3691 3692 warnedProperties$1[name] = true; 3693 return true; 3694 } // Let the ARIA attribute hook validate ARIA attributes 3695 3696 3697 if (rARIA$1.test(name) || rARIACamel$1.test(name)) { 3698 return true; 3699 } 3700 3701 if (lowerCasedName === 'innerhtml') { 3702 error('Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.'); 3703 3704 warnedProperties$1[name] = true; 3705 return true; 3706 } 3707 3708 if (lowerCasedName === 'aria') { 3709 error('The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.'); 3710 3711 warnedProperties$1[name] = true; 3712 return true; 3713 } 3714 3715 if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') { 3716 error('Received a `%s` for a string attribute `is`. If this is expected, cast ' + 'the value to a string.', typeof value); 3717 3718 warnedProperties$1[name] = true; 3719 return true; 3720 } 3721 3722 if (typeof value === 'number' && isNaN(value)) { 3723 error('Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.', name); 3724 3725 warnedProperties$1[name] = true; 3726 return true; 3727 } 3728 3729 var propertyInfo = getPropertyInfo(name); 3730 var isReserved = propertyInfo !== null && propertyInfo.type === RESERVED; // Known attributes should match the casing specified in the property config. 3731 3732 if (possibleStandardNames.hasOwnProperty(lowerCasedName)) { 3733 var standardName = possibleStandardNames[lowerCasedName]; 3734 3735 if (standardName !== name) { 3736 error('Invalid DOM property `%s`. Did you mean `%s`?', name, standardName); 3737 3738 warnedProperties$1[name] = true; 3739 return true; 3740 } 3741 } else if (!isReserved && name !== lowerCasedName) { 3742 // Unknown attributes should have lowercase casing since that's how they 3743 // will be cased anyway with server rendering. 3744 error('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.', name, lowerCasedName); 3745 3746 warnedProperties$1[name] = true; 3747 return true; 3748 } 3749 3750 if (typeof value === 'boolean' && shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) { 3751 if (value) { 3752 error('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()}.', value, name, name, value, name); 3753 } else { 3754 error('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.', value, name, name, value, name, name, name); 3755 } 3756 3757 warnedProperties$1[name] = true; 3758 return true; 3759 } // Now that we've validated casing, do not validate 3760 // data types for reserved props 3761 3762 3763 if (isReserved) { 3764 return true; 3765 } // Warn when a known attribute is a bad type 3766 3767 3768 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) { 3769 warnedProperties$1[name] = true; 3770 return false; 3771 } // Warn when passing the strings 'false' or 'true' into a boolean prop 3772 3773 3774 if ((value === 'false' || value === 'true') && propertyInfo !== null && propertyInfo.type === BOOLEAN) { 3775 error('Received the string `%s` for the boolean attribute `%s`. ' + '%s ' + 'Did you mean %s={%s}?', value, name, value === 'false' ? 'The browser will interpret it as a truthy value.' : 'Although this works, it will not work as expected if you pass the string "false".', name, value); 3776 3777 warnedProperties$1[name] = true; 3778 return true; 3779 } 3780 3781 return true; 3782 }; 3783 } 3784 3785 var warnUnknownProperties = function (type, props, eventRegistry) { 3786 { 3787 var unknownProps = []; 3788 3789 for (var key in props) { 3790 var isValid = validateProperty$1(type, key, props[key], eventRegistry); 3791 3792 if (!isValid) { 3793 unknownProps.push(key); 3794 } 3795 } 3796 3797 var unknownPropString = unknownProps.map(function (prop) { 3798 return '`' + prop + '`'; 3799 }).join(', '); 3800 3801 if (unknownProps.length === 1) { 3802 error('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://reactjs.org/link/attribute-behavior ', unknownPropString, type); 3803 } else if (unknownProps.length > 1) { 3804 error('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://reactjs.org/link/attribute-behavior ', unknownPropString, type); 3805 } 3806 } 3807 }; 3808 3809 function validateProperties$2(type, props, eventRegistry) { 3810 if (isCustomComponent(type, props)) { 3811 return; 3812 } 3813 3814 warnUnknownProperties(type, props, eventRegistry); 3815 } 3816 3817 var IS_EVENT_HANDLE_NON_MANAGED_NODE = 1; 3818 var IS_NON_DELEGATED = 1 << 1; 3819 var IS_CAPTURE_PHASE = 1 << 2; 3820 // set to LEGACY_FB_SUPPORT. LEGACY_FB_SUPPORT only gets set when 3821 // we call willDeferLaterForLegacyFBSupport, thus not bailing out 3822 // will result in endless cycles like an infinite loop. 3823 // We also don't want to defer during event replaying. 3824 3825 var SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS = IS_EVENT_HANDLE_NON_MANAGED_NODE | IS_NON_DELEGATED | IS_CAPTURE_PHASE; 3826 3827 // This exists to avoid circular dependency between ReactDOMEventReplaying 3828 // and DOMPluginEventSystem. 3829 var currentReplayingEvent = null; 3830 function setReplayingEvent(event) { 3831 { 3832 if (currentReplayingEvent !== null) { 3833 error('Expected currently replaying event to be null. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 3834 } 3835 } 3836 3837 currentReplayingEvent = event; 3838 } 3839 function resetReplayingEvent() { 3840 { 3841 if (currentReplayingEvent === null) { 3842 error('Expected currently replaying event to not be null. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 3843 } 3844 } 3845 3846 currentReplayingEvent = null; 3847 } 3848 function isReplayingEvent(event) { 3849 return event === currentReplayingEvent; 3850 } 3851 3852 /** 3853 * Gets the target node from a native browser event by accounting for 3854 * inconsistencies in browser DOM APIs. 3855 * 3856 * @param {object} nativeEvent Native browser event. 3857 * @return {DOMEventTarget} Target node. 3858 */ 3859 3860 function getEventTarget(nativeEvent) { 3861 // Fallback to nativeEvent.srcElement for IE9 3862 // https://github.com/facebook/react/issues/12506 3863 var target = nativeEvent.target || nativeEvent.srcElement || window; // Normalize SVG <use> element events #4963 3864 3865 if (target.correspondingUseElement) { 3866 target = target.correspondingUseElement; 3867 } // Safari may fire events on text nodes (Node.TEXT_NODE is 3). 3868 // @see http://www.quirksmode.org/js/events_properties.html 3869 3870 3871 return target.nodeType === TEXT_NODE ? target.parentNode : target; 3872 } 3873 3874 var restoreImpl = null; 3875 var restoreTarget = null; 3876 var restoreQueue = null; 3877 3878 function restoreStateOfTarget(target) { 3879 // We perform this translation at the end of the event loop so that we 3880 // always receive the correct fiber here 3881 var internalInstance = getInstanceFromNode(target); 3882 3883 if (!internalInstance) { 3884 // Unmounted 3885 return; 3886 } 3887 3888 if (typeof restoreImpl !== 'function') { 3889 throw new Error('setRestoreImplementation() needs to be called to handle a target for controlled ' + 'events. This error is likely caused by a bug in React. Please file an issue.'); 3890 } 3891 3892 var stateNode = internalInstance.stateNode; // Guard against Fiber being unmounted. 3893 3894 if (stateNode) { 3895 var _props = getFiberCurrentPropsFromNode(stateNode); 3896 3897 restoreImpl(internalInstance.stateNode, internalInstance.type, _props); 3898 } 3899 } 3900 3901 function setRestoreImplementation(impl) { 3902 restoreImpl = impl; 3903 } 3904 function enqueueStateRestore(target) { 3905 if (restoreTarget) { 3906 if (restoreQueue) { 3907 restoreQueue.push(target); 3908 } else { 3909 restoreQueue = [target]; 3910 } 3911 } else { 3912 restoreTarget = target; 3913 } 3914 } 3915 function needsStateRestore() { 3916 return restoreTarget !== null || restoreQueue !== null; 3917 } 3918 function restoreStateIfNeeded() { 3919 if (!restoreTarget) { 3920 return; 3921 } 3922 3923 var target = restoreTarget; 3924 var queuedTargets = restoreQueue; 3925 restoreTarget = null; 3926 restoreQueue = null; 3927 restoreStateOfTarget(target); 3928 3929 if (queuedTargets) { 3930 for (var i = 0; i < queuedTargets.length; i++) { 3931 restoreStateOfTarget(queuedTargets[i]); 3932 } 3933 } 3934 } 3935 3936 // the renderer. Such as when we're dispatching events or if third party 3937 // libraries need to call batchedUpdates. Eventually, this API will go away when 3938 // everything is batched by default. We'll then have a similar API to opt-out of 3939 // scheduled work and instead do synchronous work. 3940 // Defaults 3941 3942 var batchedUpdatesImpl = function (fn, bookkeeping) { 3943 return fn(bookkeeping); 3944 }; 3945 3946 var flushSyncImpl = function () {}; 3947 3948 var isInsideEventHandler = false; 3949 3950 function finishEventHandler() { 3951 // Here we wait until all updates have propagated, which is important 3952 // when using controlled components within layers: 3953 // https://github.com/facebook/react/issues/1698 3954 // Then we restore state of any controlled component. 3955 var controlledComponentsHavePendingUpdates = needsStateRestore(); 3956 3957 if (controlledComponentsHavePendingUpdates) { 3958 // If a controlled event was fired, we may need to restore the state of 3959 // the DOM node back to the controlled value. This is necessary when React 3960 // bails out of the update without touching the DOM. 3961 // TODO: Restore state in the microtask, after the discrete updates flush, 3962 // instead of early flushing them here. 3963 flushSyncImpl(); 3964 restoreStateIfNeeded(); 3965 } 3966 } 3967 3968 function batchedUpdates(fn, a, b) { 3969 if (isInsideEventHandler) { 3970 // If we are currently inside another batch, we need to wait until it 3971 // fully completes before restoring state. 3972 return fn(a, b); 3973 } 3974 3975 isInsideEventHandler = true; 3976 3977 try { 3978 return batchedUpdatesImpl(fn, a, b); 3979 } finally { 3980 isInsideEventHandler = false; 3981 finishEventHandler(); 3982 } 3983 } // TODO: Replace with flushSync 3984 function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl, _flushSyncImpl) { 3985 batchedUpdatesImpl = _batchedUpdatesImpl; 3986 flushSyncImpl = _flushSyncImpl; 3987 } 3988 3989 function isInteractive(tag) { 3990 return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea'; 3991 } 3992 3993 function shouldPreventMouseEvent(name, type, props) { 3994 switch (name) { 3995 case 'onClick': 3996 case 'onClickCapture': 3997 case 'onDoubleClick': 3998 case 'onDoubleClickCapture': 3999 case 'onMouseDown': 4000 case 'onMouseDownCapture': 4001 case 'onMouseMove': 4002 case 'onMouseMoveCapture': 4003 case 'onMouseUp': 4004 case 'onMouseUpCapture': 4005 case 'onMouseEnter': 4006 return !!(props.disabled && isInteractive(type)); 4007 4008 default: 4009 return false; 4010 } 4011 } 4012 /** 4013 * @param {object} inst The instance, which is the source of events. 4014 * @param {string} registrationName Name of listener (e.g. `onClick`). 4015 * @return {?function} The stored callback. 4016 */ 4017 4018 4019 function getListener(inst, registrationName) { 4020 var stateNode = inst.stateNode; 4021 4022 if (stateNode === null) { 4023 // Work in progress (ex: onload events in incremental mode). 4024 return null; 4025 } 4026 4027 var props = getFiberCurrentPropsFromNode(stateNode); 4028 4029 if (props === null) { 4030 // Work in progress. 4031 return null; 4032 } 4033 4034 var listener = props[registrationName]; 4035 4036 if (shouldPreventMouseEvent(registrationName, inst.type, props)) { 4037 return null; 4038 } 4039 4040 if (listener && typeof listener !== 'function') { 4041 throw new Error("Expected `" + registrationName + "` listener to be a function, instead got a value of `" + typeof listener + "` type."); 4042 } 4043 4044 return listener; 4045 } 4046 4047 var passiveBrowserEventsSupported = false; // Check if browser support events with passive listeners 4048 // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support 4049 4050 if (canUseDOM) { 4051 try { 4052 var options = {}; // $FlowFixMe: Ignore Flow complaining about needing a value 4053 4054 Object.defineProperty(options, 'passive', { 4055 get: function () { 4056 passiveBrowserEventsSupported = true; 4057 } 4058 }); 4059 window.addEventListener('test', options, options); 4060 window.removeEventListener('test', options, options); 4061 } catch (e) { 4062 passiveBrowserEventsSupported = false; 4063 } 4064 } 4065 4066 function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { 4067 var funcArgs = Array.prototype.slice.call(arguments, 3); 4068 4069 try { 4070 func.apply(context, funcArgs); 4071 } catch (error) { 4072 this.onError(error); 4073 } 4074 } 4075 4076 var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; 4077 4078 { 4079 // In DEV mode, we swap out invokeGuardedCallback for a special version 4080 // that plays more nicely with the browser's DevTools. The idea is to preserve 4081 // "Pause on exceptions" behavior. Because React wraps all user-provided 4082 // functions in invokeGuardedCallback, and the production version of 4083 // invokeGuardedCallback uses a try-catch, all user exceptions are treated 4084 // like caught exceptions, and the DevTools won't pause unless the developer 4085 // takes the extra step of enabling pause on caught exceptions. This is 4086 // unintuitive, though, because even though React has caught the error, from 4087 // the developer's perspective, the error is uncaught. 4088 // 4089 // To preserve the expected "Pause on exceptions" behavior, we don't use a 4090 // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake 4091 // DOM node, and call the user-provided callback from inside an event handler 4092 // for that fake event. If the callback throws, the error is "captured" using 4093 // a global event handler. But because the error happens in a different 4094 // event loop context, it does not interrupt the normal program flow. 4095 // Effectively, this gives us try-catch behavior without actually using 4096 // try-catch. Neat! 4097 // Check that the browser supports the APIs we need to implement our special 4098 // DEV version of invokeGuardedCallback 4099 if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') { 4100 var fakeNode = document.createElement('react'); 4101 4102 invokeGuardedCallbackImpl = function invokeGuardedCallbackDev(name, func, context, a, b, c, d, e, f) { 4103 // If document doesn't exist we know for sure we will crash in this method 4104 // when we call document.createEvent(). However this can cause confusing 4105 // errors: https://github.com/facebook/create-react-app/issues/3482 4106 // So we preemptively throw with a better message instead. 4107 if (typeof document === 'undefined' || document === null) { 4108 throw new Error('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.'); 4109 } 4110 4111 var evt = document.createEvent('Event'); 4112 var didCall = false; // Keeps track of whether the user-provided callback threw an error. We 4113 // set this to true at the beginning, then set it to false right after 4114 // calling the function. If the function errors, `didError` will never be 4115 // set to false. This strategy works even if the browser is flaky and 4116 // fails to call our global error handler, because it doesn't rely on 4117 // the error event at all. 4118 4119 var didError = true; // Keeps track of the value of window.event so that we can reset it 4120 // during the callback to let user code access window.event in the 4121 // browsers that support it. 4122 4123 var windowEvent = window.event; // Keeps track of the descriptor of window.event to restore it after event 4124 // dispatching: https://github.com/facebook/react/issues/13688 4125 4126 var windowEventDescriptor = Object.getOwnPropertyDescriptor(window, 'event'); 4127 4128 function restoreAfterDispatch() { 4129 // We immediately remove the callback from event listeners so that 4130 // nested `invokeGuardedCallback` calls do not clash. Otherwise, a 4131 // nested call would trigger the fake event handlers of any call higher 4132 // in the stack. 4133 fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the 4134 // window.event assignment in both IE <= 10 as they throw an error 4135 // "Member not found" in strict mode, and in Firefox which does not 4136 // support window.event. 4137 4138 if (typeof window.event !== 'undefined' && window.hasOwnProperty('event')) { 4139 window.event = windowEvent; 4140 } 4141 } // Create an event handler for our fake event. We will synchronously 4142 // dispatch our fake event using `dispatchEvent`. Inside the handler, we 4143 // call the user-provided callback. 4144 4145 4146 var funcArgs = Array.prototype.slice.call(arguments, 3); 4147 4148 function callCallback() { 4149 didCall = true; 4150 restoreAfterDispatch(); 4151 func.apply(context, funcArgs); 4152 didError = false; 4153 } // Create a global error event handler. We use this to capture the value 4154 // that was thrown. It's possible that this error handler will fire more 4155 // than once; for example, if non-React code also calls `dispatchEvent` 4156 // and a handler for that event throws. We should be resilient to most of 4157 // those cases. Even if our error event handler fires more than once, the 4158 // last error event is always used. If the callback actually does error, 4159 // we know that the last error event is the correct one, because it's not 4160 // possible for anything else to have happened in between our callback 4161 // erroring and the code that follows the `dispatchEvent` call below. If 4162 // the callback doesn't error, but the error event was fired, we know to 4163 // ignore it because `didError` will be false, as described above. 4164 4165 4166 var error; // Use this to track whether the error event is ever called. 4167 4168 var didSetError = false; 4169 var isCrossOriginError = false; 4170 4171 function handleWindowError(event) { 4172 error = event.error; 4173 didSetError = true; 4174 4175 if (error === null && event.colno === 0 && event.lineno === 0) { 4176 isCrossOriginError = true; 4177 } 4178 4179 if (event.defaultPrevented) { 4180 // Some other error handler has prevented default. 4181 // Browsers silence the error report if this happens. 4182 // We'll remember this to later decide whether to log it or not. 4183 if (error != null && typeof error === 'object') { 4184 try { 4185 error._suppressLogging = true; 4186 } catch (inner) {// Ignore. 4187 } 4188 } 4189 } 4190 } // Create a fake event type. 4191 4192 4193 var evtType = "react-" + (name ? name : 'invokeguardedcallback'); // Attach our event handlers 4194 4195 window.addEventListener('error', handleWindowError); 4196 fakeNode.addEventListener(evtType, callCallback, false); // Synchronously dispatch our fake event. If the user-provided function 4197 // errors, it will trigger our global error handler. 4198 4199 evt.initEvent(evtType, false, false); 4200 fakeNode.dispatchEvent(evt); 4201 4202 if (windowEventDescriptor) { 4203 Object.defineProperty(window, 'event', windowEventDescriptor); 4204 } 4205 4206 if (didCall && didError) { 4207 if (!didSetError) { 4208 // The callback errored, but the error event never fired. 4209 // eslint-disable-next-line react-internal/prod-error-codes 4210 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.'); 4211 } else if (isCrossOriginError) { 4212 // eslint-disable-next-line react-internal/prod-error-codes 4213 error = new Error("A cross-origin error was thrown. React doesn't have access to " + 'the actual error object in development. ' + 'See https://reactjs.org/link/crossorigin-error for more information.'); 4214 } 4215 4216 this.onError(error); 4217 } // Remove our event listeners 4218 4219 4220 window.removeEventListener('error', handleWindowError); 4221 4222 if (!didCall) { 4223 // Something went really wrong, and our event was not dispatched. 4224 // https://github.com/facebook/react/issues/16734 4225 // https://github.com/facebook/react/issues/16585 4226 // Fall back to the production implementation. 4227 restoreAfterDispatch(); 4228 return invokeGuardedCallbackProd.apply(this, arguments); 4229 } 4230 }; 4231 } 4232 } 4233 4234 var invokeGuardedCallbackImpl$1 = invokeGuardedCallbackImpl; 4235 4236 var hasError = false; 4237 var caughtError = null; // Used by event system to capture/rethrow the first error. 4238 4239 var hasRethrowError = false; 4240 var rethrowError = null; 4241 var reporter = { 4242 onError: function (error) { 4243 hasError = true; 4244 caughtError = error; 4245 } 4246 }; 4247 /** 4248 * Call a function while guarding against errors that happens within it. 4249 * Returns an error if it throws, otherwise null. 4250 * 4251 * In production, this is implemented using a try-catch. The reason we don't 4252 * use a try-catch directly is so that we can swap out a different 4253 * implementation in DEV mode. 4254 * 4255 * @param {String} name of the guard to use for logging or debugging 4256 * @param {Function} func The function to invoke 4257 * @param {*} context The context to use when calling the function 4258 * @param {...*} args Arguments for function 4259 */ 4260 4261 function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { 4262 hasError = false; 4263 caughtError = null; 4264 invokeGuardedCallbackImpl$1.apply(reporter, arguments); 4265 } 4266 /** 4267 * Same as invokeGuardedCallback, but instead of returning an error, it stores 4268 * it in a global so it can be rethrown by `rethrowCaughtError` later. 4269 * TODO: See if caughtError and rethrowError can be unified. 4270 * 4271 * @param {String} name of the guard to use for logging or debugging 4272 * @param {Function} func The function to invoke 4273 * @param {*} context The context to use when calling the function 4274 * @param {...*} args Arguments for function 4275 */ 4276 4277 function invokeGuardedCallbackAndCatchFirstError(name, func, context, a, b, c, d, e, f) { 4278 invokeGuardedCallback.apply(this, arguments); 4279 4280 if (hasError) { 4281 var error = clearCaughtError(); 4282 4283 if (!hasRethrowError) { 4284 hasRethrowError = true; 4285 rethrowError = error; 4286 } 4287 } 4288 } 4289 /** 4290 * During execution of guarded functions we will capture the first error which 4291 * we will rethrow to be handled by the top level error handler. 4292 */ 4293 4294 function rethrowCaughtError() { 4295 if (hasRethrowError) { 4296 var error = rethrowError; 4297 hasRethrowError = false; 4298 rethrowError = null; 4299 throw error; 4300 } 4301 } 4302 function hasCaughtError() { 4303 return hasError; 4304 } 4305 function clearCaughtError() { 4306 if (hasError) { 4307 var error = caughtError; 4308 hasError = false; 4309 caughtError = null; 4310 return error; 4311 } else { 4312 throw new Error('clearCaughtError was called but no error was captured. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 4313 } 4314 } 4315 4316 var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; 4317 var _ReactInternals$Sched = ReactInternals.Scheduler, 4318 unstable_cancelCallback = _ReactInternals$Sched.unstable_cancelCallback, 4319 unstable_now = _ReactInternals$Sched.unstable_now, 4320 unstable_scheduleCallback = _ReactInternals$Sched.unstable_scheduleCallback, 4321 unstable_shouldYield = _ReactInternals$Sched.unstable_shouldYield, 4322 unstable_requestPaint = _ReactInternals$Sched.unstable_requestPaint, 4323 unstable_getFirstCallbackNode = _ReactInternals$Sched.unstable_getFirstCallbackNode, 4324 unstable_runWithPriority = _ReactInternals$Sched.unstable_runWithPriority, 4325 unstable_next = _ReactInternals$Sched.unstable_next, 4326 unstable_continueExecution = _ReactInternals$Sched.unstable_continueExecution, 4327 unstable_pauseExecution = _ReactInternals$Sched.unstable_pauseExecution, 4328 unstable_getCurrentPriorityLevel = _ReactInternals$Sched.unstable_getCurrentPriorityLevel, 4329 unstable_ImmediatePriority = _ReactInternals$Sched.unstable_ImmediatePriority, 4330 unstable_UserBlockingPriority = _ReactInternals$Sched.unstable_UserBlockingPriority, 4331 unstable_NormalPriority = _ReactInternals$Sched.unstable_NormalPriority, 4332 unstable_LowPriority = _ReactInternals$Sched.unstable_LowPriority, 4333 unstable_IdlePriority = _ReactInternals$Sched.unstable_IdlePriority, 4334 unstable_forceFrameRate = _ReactInternals$Sched.unstable_forceFrameRate, 4335 unstable_flushAllWithoutAsserting = _ReactInternals$Sched.unstable_flushAllWithoutAsserting, 4336 unstable_yieldValue = _ReactInternals$Sched.unstable_yieldValue, 4337 unstable_setDisableYieldValue = _ReactInternals$Sched.unstable_setDisableYieldValue; 4338 4339 /** 4340 * `ReactInstanceMap` maintains a mapping from a public facing stateful 4341 * instance (key) and the internal representation (value). This allows public 4342 * methods to accept the user facing instance as an argument and map them back 4343 * to internal methods. 4344 * 4345 * Note that this module is currently shared and assumed to be stateless. 4346 * If this becomes an actual Map, that will break. 4347 */ 4348 function get(key) { 4349 return key._reactInternals; 4350 } 4351 function has(key) { 4352 return key._reactInternals !== undefined; 4353 } 4354 function set(key, value) { 4355 key._reactInternals = value; 4356 } 4357 4358 // Don't change these two values. They're used by React Dev Tools. 4359 var NoFlags = 4360 /* */ 4361 0; 4362 var PerformedWork = 4363 /* */ 4364 1; // You can change the rest (and add more). 4365 4366 var Placement = 4367 /* */ 4368 2; 4369 var Update = 4370 /* */ 4371 4; 4372 var ChildDeletion = 4373 /* */ 4374 16; 4375 var ContentReset = 4376 /* */ 4377 32; 4378 var Callback = 4379 /* */ 4380 64; 4381 var DidCapture = 4382 /* */ 4383 128; 4384 var ForceClientRender = 4385 /* */ 4386 256; 4387 var Ref = 4388 /* */ 4389 512; 4390 var Snapshot = 4391 /* */ 4392 1024; 4393 var Passive = 4394 /* */ 4395 2048; 4396 var Hydrating = 4397 /* */ 4398 4096; 4399 var Visibility = 4400 /* */ 4401 8192; 4402 var StoreConsistency = 4403 /* */ 4404 16384; 4405 var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) 4406 4407 var HostEffectMask = 4408 /* */ 4409 32767; // These are not really side effects, but we still reuse this field. 4410 4411 var Incomplete = 4412 /* */ 4413 32768; 4414 var ShouldCapture = 4415 /* */ 4416 65536; 4417 var ForceUpdateForLegacySuspense = 4418 /* */ 4419 131072; 4420 var Forked = 4421 /* */ 4422 1048576; // Static tags describe aspects of a fiber that are not specific to a render, 4423 // e.g. a fiber uses a passive effect (even if there are no updates on this particular render). 4424 // This enables us to defer more work in the unmount case, 4425 // since we can defer traversing the tree during layout to look for Passive effects, 4426 // and instead rely on the static flag as a signal that there may be cleanup work. 4427 4428 var RefStatic = 4429 /* */ 4430 2097152; 4431 var LayoutStatic = 4432 /* */ 4433 4194304; 4434 var PassiveStatic = 4435 /* */ 4436 8388608; // These flags allow us to traverse to fibers that have effects on mount 4437 // without traversing the entire tree after every commit for 4438 // double invoking 4439 4440 var MountLayoutDev = 4441 /* */ 4442 16777216; 4443 var MountPassiveDev = 4444 /* */ 4445 33554432; // Groups of flags that are used in the commit phase to skip over trees that 4446 // don't contain effects, by checking subtreeFlags. 4447 4448 var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility 4449 // flag logic (see #20043) 4450 Update | Snapshot | ( 0); 4451 var MutationMask = Placement | Update | ChildDeletion | ContentReset | Ref | Hydrating | Visibility; 4452 var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask 4453 4454 var PassiveMask = Passive | ChildDeletion; // Union of tags that don't get reset on clones. 4455 // This allows certain concepts to persist without recalculating them, 4456 // e.g. whether a subtree contains passive effects or portals. 4457 4458 var StaticMask = LayoutStatic | PassiveStatic | RefStatic; 4459 4460 var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; 4461 function getNearestMountedFiber(fiber) { 4462 var node = fiber; 4463 var nearestMounted = fiber; 4464 4465 if (!fiber.alternate) { 4466 // If there is no alternate, this might be a new tree that isn't inserted 4467 // yet. If it is, then it will have a pending insertion effect on it. 4468 var nextNode = node; 4469 4470 do { 4471 node = nextNode; 4472 4473 if ((node.flags & (Placement | Hydrating)) !== NoFlags) { 4474 // This is an insertion or in-progress hydration. The nearest possible 4475 // mounted fiber is the parent but we need to continue to figure out 4476 // if that one is still mounted. 4477 nearestMounted = node.return; 4478 } 4479 4480 nextNode = node.return; 4481 } while (nextNode); 4482 } else { 4483 while (node.return) { 4484 node = node.return; 4485 } 4486 } 4487 4488 if (node.tag === HostRoot) { 4489 // TODO: Check if this was a nested HostRoot when used with 4490 // renderContainerIntoSubtree. 4491 return nearestMounted; 4492 } // If we didn't hit the root, that means that we're in an disconnected tree 4493 // that has been unmounted. 4494 4495 4496 return null; 4497 } 4498 function getSuspenseInstanceFromFiber(fiber) { 4499 if (fiber.tag === SuspenseComponent) { 4500 var suspenseState = fiber.memoizedState; 4501 4502 if (suspenseState === null) { 4503 var current = fiber.alternate; 4504 4505 if (current !== null) { 4506 suspenseState = current.memoizedState; 4507 } 4508 } 4509 4510 if (suspenseState !== null) { 4511 return suspenseState.dehydrated; 4512 } 4513 } 4514 4515 return null; 4516 } 4517 function getContainerFromFiber(fiber) { 4518 return fiber.tag === HostRoot ? fiber.stateNode.containerInfo : null; 4519 } 4520 function isFiberMounted(fiber) { 4521 return getNearestMountedFiber(fiber) === fiber; 4522 } 4523 function isMounted(component) { 4524 { 4525 var owner = ReactCurrentOwner.current; 4526 4527 if (owner !== null && owner.tag === ClassComponent) { 4528 var ownerFiber = owner; 4529 var instance = ownerFiber.stateNode; 4530 4531 if (!instance._warnedAboutRefsInRender) { 4532 error('%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.', getComponentNameFromFiber(ownerFiber) || 'A component'); 4533 } 4534 4535 instance._warnedAboutRefsInRender = true; 4536 } 4537 } 4538 4539 var fiber = get(component); 4540 4541 if (!fiber) { 4542 return false; 4543 } 4544 4545 return getNearestMountedFiber(fiber) === fiber; 4546 } 4547 4548 function assertIsMounted(fiber) { 4549 if (getNearestMountedFiber(fiber) !== fiber) { 4550 throw new Error('Unable to find node on an unmounted component.'); 4551 } 4552 } 4553 4554 function findCurrentFiberUsingSlowPath(fiber) { 4555 var alternate = fiber.alternate; 4556 4557 if (!alternate) { 4558 // If there is no alternate, then we only need to check if it is mounted. 4559 var nearestMounted = getNearestMountedFiber(fiber); 4560 4561 if (nearestMounted === null) { 4562 throw new Error('Unable to find node on an unmounted component.'); 4563 } 4564 4565 if (nearestMounted !== fiber) { 4566 return null; 4567 } 4568 4569 return fiber; 4570 } // If we have two possible branches, we'll walk backwards up to the root 4571 // to see what path the root points to. On the way we may hit one of the 4572 // special cases and we'll deal with them. 4573 4574 4575 var a = fiber; 4576 var b = alternate; 4577 4578 while (true) { 4579 var parentA = a.return; 4580 4581 if (parentA === null) { 4582 // We're at the root. 4583 break; 4584 } 4585 4586 var parentB = parentA.alternate; 4587 4588 if (parentB === null) { 4589 // There is no alternate. This is an unusual case. Currently, it only 4590 // happens when a Suspense component is hidden. An extra fragment fiber 4591 // is inserted in between the Suspense fiber and its children. Skip 4592 // over this extra fragment fiber and proceed to the next parent. 4593 var nextParent = parentA.return; 4594 4595 if (nextParent !== null) { 4596 a = b = nextParent; 4597 continue; 4598 } // If there's no parent, we're at the root. 4599 4600 4601 break; 4602 } // If both copies of the parent fiber point to the same child, we can 4603 // assume that the child is current. This happens when we bailout on low 4604 // priority: the bailed out fiber's child reuses the current child. 4605 4606 4607 if (parentA.child === parentB.child) { 4608 var child = parentA.child; 4609 4610 while (child) { 4611 if (child === a) { 4612 // We've determined that A is the current branch. 4613 assertIsMounted(parentA); 4614 return fiber; 4615 } 4616 4617 if (child === b) { 4618 // We've determined that B is the current branch. 4619 assertIsMounted(parentA); 4620 return alternate; 4621 } 4622 4623 child = child.sibling; 4624 } // We should never have an alternate for any mounting node. So the only 4625 // way this could possibly happen is if this was unmounted, if at all. 4626 4627 4628 throw new Error('Unable to find node on an unmounted component.'); 4629 } 4630 4631 if (a.return !== b.return) { 4632 // The return pointer of A and the return pointer of B point to different 4633 // fibers. We assume that return pointers never criss-cross, so A must 4634 // belong to the child set of A.return, and B must belong to the child 4635 // set of B.return. 4636 a = parentA; 4637 b = parentB; 4638 } else { 4639 // The return pointers point to the same fiber. We'll have to use the 4640 // default, slow path: scan the child sets of each parent alternate to see 4641 // which child belongs to which set. 4642 // 4643 // Search parent A's child set 4644 var didFindChild = false; 4645 var _child = parentA.child; 4646 4647 while (_child) { 4648 if (_child === a) { 4649 didFindChild = true; 4650 a = parentA; 4651 b = parentB; 4652 break; 4653 } 4654 4655 if (_child === b) { 4656 didFindChild = true; 4657 b = parentA; 4658 a = parentB; 4659 break; 4660 } 4661 4662 _child = _child.sibling; 4663 } 4664 4665 if (!didFindChild) { 4666 // Search parent B's child set 4667 _child = parentB.child; 4668 4669 while (_child) { 4670 if (_child === a) { 4671 didFindChild = true; 4672 a = parentB; 4673 b = parentA; 4674 break; 4675 } 4676 4677 if (_child === b) { 4678 didFindChild = true; 4679 b = parentB; 4680 a = parentA; 4681 break; 4682 } 4683 4684 _child = _child.sibling; 4685 } 4686 4687 if (!didFindChild) { 4688 throw new Error('Child was not found in either parent set. This indicates a bug ' + 'in React related to the return pointer. Please file an issue.'); 4689 } 4690 } 4691 } 4692 4693 if (a.alternate !== b) { 4694 throw new Error("Return fibers should always be each others' alternates. " + 'This error is likely caused by a bug in React. Please file an issue.'); 4695 } 4696 } // If the root is not a host container, we're in a disconnected tree. I.e. 4697 // unmounted. 4698 4699 4700 if (a.tag !== HostRoot) { 4701 throw new Error('Unable to find node on an unmounted component.'); 4702 } 4703 4704 if (a.stateNode.current === a) { 4705 // We've determined that A is the current branch. 4706 return fiber; 4707 } // Otherwise B has to be current branch. 4708 4709 4710 return alternate; 4711 } 4712 function findCurrentHostFiber(parent) { 4713 var currentParent = findCurrentFiberUsingSlowPath(parent); 4714 return currentParent !== null ? findCurrentHostFiberImpl(currentParent) : null; 4715 } 4716 4717 function findCurrentHostFiberImpl(node) { 4718 // Next we'll drill down this component to find the first HostComponent/Text. 4719 if (node.tag === HostComponent || node.tag === HostText) { 4720 return node; 4721 } 4722 4723 var child = node.child; 4724 4725 while (child !== null) { 4726 var match = findCurrentHostFiberImpl(child); 4727 4728 if (match !== null) { 4729 return match; 4730 } 4731 4732 child = child.sibling; 4733 } 4734 4735 return null; 4736 } 4737 4738 function findCurrentHostFiberWithNoPortals(parent) { 4739 var currentParent = findCurrentFiberUsingSlowPath(parent); 4740 return currentParent !== null ? findCurrentHostFiberWithNoPortalsImpl(currentParent) : null; 4741 } 4742 4743 function findCurrentHostFiberWithNoPortalsImpl(node) { 4744 // Next we'll drill down this component to find the first HostComponent/Text. 4745 if (node.tag === HostComponent || node.tag === HostText) { 4746 return node; 4747 } 4748 4749 var child = node.child; 4750 4751 while (child !== null) { 4752 if (child.tag !== HostPortal) { 4753 var match = findCurrentHostFiberWithNoPortalsImpl(child); 4754 4755 if (match !== null) { 4756 return match; 4757 } 4758 } 4759 4760 child = child.sibling; 4761 } 4762 4763 return null; 4764 } 4765 4766 // This module only exists as an ESM wrapper around the external CommonJS 4767 var scheduleCallback = unstable_scheduleCallback; 4768 var cancelCallback = unstable_cancelCallback; 4769 var shouldYield = unstable_shouldYield; 4770 var requestPaint = unstable_requestPaint; 4771 var now = unstable_now; 4772 var getCurrentPriorityLevel = unstable_getCurrentPriorityLevel; 4773 var ImmediatePriority = unstable_ImmediatePriority; 4774 var UserBlockingPriority = unstable_UserBlockingPriority; 4775 var NormalPriority = unstable_NormalPriority; 4776 var LowPriority = unstable_LowPriority; 4777 var IdlePriority = unstable_IdlePriority; 4778 // this doesn't actually exist on the scheduler, but it *does* 4779 // on scheduler/unstable_mock, which we'll need for internal testing 4780 var unstable_yieldValue$1 = unstable_yieldValue; 4781 var unstable_setDisableYieldValue$1 = unstable_setDisableYieldValue; 4782 4783 var rendererID = null; 4784 var injectedHook = null; 4785 var injectedProfilingHooks = null; 4786 var hasLoggedError = false; 4787 var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined'; 4788 function injectInternals(internals) { 4789 if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { 4790 // No DevTools 4791 return false; 4792 } 4793 4794 var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; 4795 4796 if (hook.isDisabled) { 4797 // This isn't a real property on the hook, but it can be set to opt out 4798 // of DevTools integration and associated warnings and logs. 4799 // https://github.com/facebook/react/issues/3877 4800 return true; 4801 } 4802 4803 if (!hook.supportsFiber) { 4804 { 4805 error('The installed version of React DevTools is too old and will not work ' + 'with the current version of React. Please update React DevTools. ' + 'https://reactjs.org/link/react-devtools'); 4806 } // DevTools exists, even though it doesn't support Fiber. 4807 4808 4809 return true; 4810 } 4811 4812 try { 4813 if (enableSchedulingProfiler) { 4814 // Conditionally inject these hooks only if Timeline profiler is supported by this build. 4815 // This gives DevTools a way to feature detect that isn't tied to version number 4816 // (since profiling and timeline are controlled by different feature flags). 4817 internals = assign({}, internals, { 4818 getLaneLabelMap: getLaneLabelMap, 4819 injectProfilingHooks: injectProfilingHooks 4820 }); 4821 } 4822 4823 rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. 4824 4825 injectedHook = hook; 4826 } catch (err) { 4827 // Catch all errors because it is unsafe to throw during initialization. 4828 { 4829 error('React instrumentation encountered an error: %s.', err); 4830 } 4831 } 4832 4833 if (hook.checkDCE) { 4834 // This is the real DevTools. 4835 return true; 4836 } else { 4837 // This is likely a hook installed by Fast Refresh runtime. 4838 return false; 4839 } 4840 } 4841 function onScheduleRoot(root, children) { 4842 { 4843 if (injectedHook && typeof injectedHook.onScheduleFiberRoot === 'function') { 4844 try { 4845 injectedHook.onScheduleFiberRoot(rendererID, root, children); 4846 } catch (err) { 4847 if ( !hasLoggedError) { 4848 hasLoggedError = true; 4849 4850 error('React instrumentation encountered an error: %s', err); 4851 } 4852 } 4853 } 4854 } 4855 } 4856 function onCommitRoot(root, eventPriority) { 4857 if (injectedHook && typeof injectedHook.onCommitFiberRoot === 'function') { 4858 try { 4859 var didError = (root.current.flags & DidCapture) === DidCapture; 4860 4861 if (enableProfilerTimer) { 4862 var schedulerPriority; 4863 4864 switch (eventPriority) { 4865 case DiscreteEventPriority: 4866 schedulerPriority = ImmediatePriority; 4867 break; 4868 4869 case ContinuousEventPriority: 4870 schedulerPriority = UserBlockingPriority; 4871 break; 4872 4873 case DefaultEventPriority: 4874 schedulerPriority = NormalPriority; 4875 break; 4876 4877 case IdleEventPriority: 4878 schedulerPriority = IdlePriority; 4879 break; 4880 4881 default: 4882 schedulerPriority = NormalPriority; 4883 break; 4884 } 4885 4886 injectedHook.onCommitFiberRoot(rendererID, root, schedulerPriority, didError); 4887 } else { 4888 injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); 4889 } 4890 } catch (err) { 4891 { 4892 if (!hasLoggedError) { 4893 hasLoggedError = true; 4894 4895 error('React instrumentation encountered an error: %s', err); 4896 } 4897 } 4898 } 4899 } 4900 } 4901 function onPostCommitRoot(root) { 4902 if (injectedHook && typeof injectedHook.onPostCommitFiberRoot === 'function') { 4903 try { 4904 injectedHook.onPostCommitFiberRoot(rendererID, root); 4905 } catch (err) { 4906 { 4907 if (!hasLoggedError) { 4908 hasLoggedError = true; 4909 4910 error('React instrumentation encountered an error: %s', err); 4911 } 4912 } 4913 } 4914 } 4915 } 4916 function onCommitUnmount(fiber) { 4917 if (injectedHook && typeof injectedHook.onCommitFiberUnmount === 'function') { 4918 try { 4919 injectedHook.onCommitFiberUnmount(rendererID, fiber); 4920 } catch (err) { 4921 { 4922 if (!hasLoggedError) { 4923 hasLoggedError = true; 4924 4925 error('React instrumentation encountered an error: %s', err); 4926 } 4927 } 4928 } 4929 } 4930 } 4931 function setIsStrictModeForDevtools(newIsStrictMode) { 4932 { 4933 if (typeof unstable_yieldValue$1 === 'function') { 4934 // We're in a test because Scheduler.unstable_yieldValue only exists 4935 // in SchedulerMock. To reduce the noise in strict mode tests, 4936 // suppress warnings and disable scheduler yielding during the double render 4937 unstable_setDisableYieldValue$1(newIsStrictMode); 4938 setSuppressWarning(newIsStrictMode); 4939 } 4940 4941 if (injectedHook && typeof injectedHook.setStrictMode === 'function') { 4942 try { 4943 injectedHook.setStrictMode(rendererID, newIsStrictMode); 4944 } catch (err) { 4945 { 4946 if (!hasLoggedError) { 4947 hasLoggedError = true; 4948 4949 error('React instrumentation encountered an error: %s', err); 4950 } 4951 } 4952 } 4953 } 4954 } 4955 } // Profiler API hooks 4956 4957 function injectProfilingHooks(profilingHooks) { 4958 injectedProfilingHooks = profilingHooks; 4959 } 4960 4961 function getLaneLabelMap() { 4962 { 4963 var map = new Map(); 4964 var lane = 1; 4965 4966 for (var index = 0; index < TotalLanes; index++) { 4967 var label = getLabelForLane(lane); 4968 map.set(lane, label); 4969 lane *= 2; 4970 } 4971 4972 return map; 4973 } 4974 } 4975 4976 function markCommitStarted(lanes) { 4977 { 4978 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStarted === 'function') { 4979 injectedProfilingHooks.markCommitStarted(lanes); 4980 } 4981 } 4982 } 4983 function markCommitStopped() { 4984 { 4985 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStopped === 'function') { 4986 injectedProfilingHooks.markCommitStopped(); 4987 } 4988 } 4989 } 4990 function markComponentRenderStarted(fiber) { 4991 { 4992 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStarted === 'function') { 4993 injectedProfilingHooks.markComponentRenderStarted(fiber); 4994 } 4995 } 4996 } 4997 function markComponentRenderStopped() { 4998 { 4999 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStopped === 'function') { 5000 injectedProfilingHooks.markComponentRenderStopped(); 5001 } 5002 } 5003 } 5004 function markComponentPassiveEffectMountStarted(fiber) { 5005 { 5006 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === 'function') { 5007 injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); 5008 } 5009 } 5010 } 5011 function markComponentPassiveEffectMountStopped() { 5012 { 5013 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === 'function') { 5014 injectedProfilingHooks.markComponentPassiveEffectMountStopped(); 5015 } 5016 } 5017 } 5018 function markComponentPassiveEffectUnmountStarted(fiber) { 5019 { 5020 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === 'function') { 5021 injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber); 5022 } 5023 } 5024 } 5025 function markComponentPassiveEffectUnmountStopped() { 5026 { 5027 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === 'function') { 5028 injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); 5029 } 5030 } 5031 } 5032 function markComponentLayoutEffectMountStarted(fiber) { 5033 { 5034 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === 'function') { 5035 injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); 5036 } 5037 } 5038 } 5039 function markComponentLayoutEffectMountStopped() { 5040 { 5041 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === 'function') { 5042 injectedProfilingHooks.markComponentLayoutEffectMountStopped(); 5043 } 5044 } 5045 } 5046 function markComponentLayoutEffectUnmountStarted(fiber) { 5047 { 5048 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === 'function') { 5049 injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); 5050 } 5051 } 5052 } 5053 function markComponentLayoutEffectUnmountStopped() { 5054 { 5055 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === 'function') { 5056 injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); 5057 } 5058 } 5059 } 5060 function markComponentErrored(fiber, thrownValue, lanes) { 5061 { 5062 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentErrored === 'function') { 5063 injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes); 5064 } 5065 } 5066 } 5067 function markComponentSuspended(fiber, wakeable, lanes) { 5068 { 5069 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentSuspended === 'function') { 5070 injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); 5071 } 5072 } 5073 } 5074 function markLayoutEffectsStarted(lanes) { 5075 { 5076 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStarted === 'function') { 5077 injectedProfilingHooks.markLayoutEffectsStarted(lanes); 5078 } 5079 } 5080 } 5081 function markLayoutEffectsStopped() { 5082 { 5083 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStopped === 'function') { 5084 injectedProfilingHooks.markLayoutEffectsStopped(); 5085 } 5086 } 5087 } 5088 function markPassiveEffectsStarted(lanes) { 5089 { 5090 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStarted === 'function') { 5091 injectedProfilingHooks.markPassiveEffectsStarted(lanes); 5092 } 5093 } 5094 } 5095 function markPassiveEffectsStopped() { 5096 { 5097 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStopped === 'function') { 5098 injectedProfilingHooks.markPassiveEffectsStopped(); 5099 } 5100 } 5101 } 5102 function markRenderStarted(lanes) { 5103 { 5104 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStarted === 'function') { 5105 injectedProfilingHooks.markRenderStarted(lanes); 5106 } 5107 } 5108 } 5109 function markRenderYielded() { 5110 { 5111 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderYielded === 'function') { 5112 injectedProfilingHooks.markRenderYielded(); 5113 } 5114 } 5115 } 5116 function markRenderStopped() { 5117 { 5118 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStopped === 'function') { 5119 injectedProfilingHooks.markRenderStopped(); 5120 } 5121 } 5122 } 5123 function markRenderScheduled(lane) { 5124 { 5125 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderScheduled === 'function') { 5126 injectedProfilingHooks.markRenderScheduled(lane); 5127 } 5128 } 5129 } 5130 function markForceUpdateScheduled(fiber, lane) { 5131 { 5132 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markForceUpdateScheduled === 'function') { 5133 injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); 5134 } 5135 } 5136 } 5137 function markStateUpdateScheduled(fiber, lane) { 5138 { 5139 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markStateUpdateScheduled === 'function') { 5140 injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); 5141 } 5142 } 5143 } 5144 5145 var NoMode = 5146 /* */ 5147 0; // TODO: Remove ConcurrentMode by reading from the root tag instead 5148 5149 var ConcurrentMode = 5150 /* */ 5151 1; 5152 var ProfileMode = 5153 /* */ 5154 2; 5155 var StrictLegacyMode = 5156 /* */ 5157 8; 5158 var StrictEffectsMode = 5159 /* */ 5160 16; 5161 5162 // TODO: This is pretty well supported by browsers. Maybe we can drop it. 5163 var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. 5164 // Based on: 5165 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 5166 5167 var log = Math.log; 5168 var LN2 = Math.LN2; 5169 5170 function clz32Fallback(x) { 5171 var asUint = x >>> 0; 5172 5173 if (asUint === 0) { 5174 return 32; 5175 } 5176 5177 return 31 - (log(asUint) / LN2 | 0) | 0; 5178 } 5179 5180 // If those values are changed that package should be rebuilt and redeployed. 5181 5182 var TotalLanes = 31; 5183 var NoLanes = 5184 /* */ 5185 0; 5186 var NoLane = 5187 /* */ 5188 0; 5189 var SyncLane = 5190 /* */ 5191 1; 5192 var InputContinuousHydrationLane = 5193 /* */ 5194 2; 5195 var InputContinuousLane = 5196 /* */ 5197 4; 5198 var DefaultHydrationLane = 5199 /* */ 5200 8; 5201 var DefaultLane = 5202 /* */ 5203 16; 5204 var TransitionHydrationLane = 5205 /* */ 5206 32; 5207 var TransitionLanes = 5208 /* */ 5209 4194240; 5210 var TransitionLane1 = 5211 /* */ 5212 64; 5213 var TransitionLane2 = 5214 /* */ 5215 128; 5216 var TransitionLane3 = 5217 /* */ 5218 256; 5219 var TransitionLane4 = 5220 /* */ 5221 512; 5222 var TransitionLane5 = 5223 /* */ 5224 1024; 5225 var TransitionLane6 = 5226 /* */ 5227 2048; 5228 var TransitionLane7 = 5229 /* */ 5230 4096; 5231 var TransitionLane8 = 5232 /* */ 5233 8192; 5234 var TransitionLane9 = 5235 /* */ 5236 16384; 5237 var TransitionLane10 = 5238 /* */ 5239 32768; 5240 var TransitionLane11 = 5241 /* */ 5242 65536; 5243 var TransitionLane12 = 5244 /* */ 5245 131072; 5246 var TransitionLane13 = 5247 /* */ 5248 262144; 5249 var TransitionLane14 = 5250 /* */ 5251 524288; 5252 var TransitionLane15 = 5253 /* */ 5254 1048576; 5255 var TransitionLane16 = 5256 /* */ 5257 2097152; 5258 var RetryLanes = 5259 /* */ 5260 130023424; 5261 var RetryLane1 = 5262 /* */ 5263 4194304; 5264 var RetryLane2 = 5265 /* */ 5266 8388608; 5267 var RetryLane3 = 5268 /* */ 5269 16777216; 5270 var RetryLane4 = 5271 /* */ 5272 33554432; 5273 var RetryLane5 = 5274 /* */ 5275 67108864; 5276 var SomeRetryLane = RetryLane1; 5277 var SelectiveHydrationLane = 5278 /* */ 5279 134217728; 5280 var NonIdleLanes = 5281 /* */ 5282 268435455; 5283 var IdleHydrationLane = 5284 /* */ 5285 268435456; 5286 var IdleLane = 5287 /* */ 5288 536870912; 5289 var OffscreenLane = 5290 /* */ 5291 1073741824; // This function is used for the experimental timeline (react-devtools-timeline) 5292 // It should be kept in sync with the Lanes values above. 5293 5294 function getLabelForLane(lane) { 5295 { 5296 if (lane & SyncLane) { 5297 return 'Sync'; 5298 } 5299 5300 if (lane & InputContinuousHydrationLane) { 5301 return 'InputContinuousHydration'; 5302 } 5303 5304 if (lane & InputContinuousLane) { 5305 return 'InputContinuous'; 5306 } 5307 5308 if (lane & DefaultHydrationLane) { 5309 return 'DefaultHydration'; 5310 } 5311 5312 if (lane & DefaultLane) { 5313 return 'Default'; 5314 } 5315 5316 if (lane & TransitionHydrationLane) { 5317 return 'TransitionHydration'; 5318 } 5319 5320 if (lane & TransitionLanes) { 5321 return 'Transition'; 5322 } 5323 5324 if (lane & RetryLanes) { 5325 return 'Retry'; 5326 } 5327 5328 if (lane & SelectiveHydrationLane) { 5329 return 'SelectiveHydration'; 5330 } 5331 5332 if (lane & IdleHydrationLane) { 5333 return 'IdleHydration'; 5334 } 5335 5336 if (lane & IdleLane) { 5337 return 'Idle'; 5338 } 5339 5340 if (lane & OffscreenLane) { 5341 return 'Offscreen'; 5342 } 5343 } 5344 } 5345 var NoTimestamp = -1; 5346 var nextTransitionLane = TransitionLane1; 5347 var nextRetryLane = RetryLane1; 5348 5349 function getHighestPriorityLanes(lanes) { 5350 switch (getHighestPriorityLane(lanes)) { 5351 case SyncLane: 5352 return SyncLane; 5353 5354 case InputContinuousHydrationLane: 5355 return InputContinuousHydrationLane; 5356 5357 case InputContinuousLane: 5358 return InputContinuousLane; 5359 5360 case DefaultHydrationLane: 5361 return DefaultHydrationLane; 5362 5363 case DefaultLane: 5364 return DefaultLane; 5365 5366 case TransitionHydrationLane: 5367 return TransitionHydrationLane; 5368 5369 case TransitionLane1: 5370 case TransitionLane2: 5371 case TransitionLane3: 5372 case TransitionLane4: 5373 case TransitionLane5: 5374 case TransitionLane6: 5375 case TransitionLane7: 5376 case TransitionLane8: 5377 case TransitionLane9: 5378 case TransitionLane10: 5379 case TransitionLane11: 5380 case TransitionLane12: 5381 case TransitionLane13: 5382 case TransitionLane14: 5383 case TransitionLane15: 5384 case TransitionLane16: 5385 return lanes & TransitionLanes; 5386 5387 case RetryLane1: 5388 case RetryLane2: 5389 case RetryLane3: 5390 case RetryLane4: 5391 case RetryLane5: 5392 return lanes & RetryLanes; 5393 5394 case SelectiveHydrationLane: 5395 return SelectiveHydrationLane; 5396 5397 case IdleHydrationLane: 5398 return IdleHydrationLane; 5399 5400 case IdleLane: 5401 return IdleLane; 5402 5403 case OffscreenLane: 5404 return OffscreenLane; 5405 5406 default: 5407 { 5408 error('Should have found matching lanes. This is a bug in React.'); 5409 } // This shouldn't be reachable, but as a fallback, return the entire bitmask. 5410 5411 5412 return lanes; 5413 } 5414 } 5415 5416 function getNextLanes(root, wipLanes) { 5417 // Early bailout if there's no pending work left. 5418 var pendingLanes = root.pendingLanes; 5419 5420 if (pendingLanes === NoLanes) { 5421 return NoLanes; 5422 } 5423 5424 var nextLanes = NoLanes; 5425 var suspendedLanes = root.suspendedLanes; 5426 var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, 5427 // even if the work is suspended. 5428 5429 var nonIdlePendingLanes = pendingLanes & NonIdleLanes; 5430 5431 if (nonIdlePendingLanes !== NoLanes) { 5432 var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; 5433 5434 if (nonIdleUnblockedLanes !== NoLanes) { 5435 nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); 5436 } else { 5437 var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; 5438 5439 if (nonIdlePingedLanes !== NoLanes) { 5440 nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); 5441 } 5442 } 5443 } else { 5444 // The only remaining work is Idle. 5445 var unblockedLanes = pendingLanes & ~suspendedLanes; 5446 5447 if (unblockedLanes !== NoLanes) { 5448 nextLanes = getHighestPriorityLanes(unblockedLanes); 5449 } else { 5450 if (pingedLanes !== NoLanes) { 5451 nextLanes = getHighestPriorityLanes(pingedLanes); 5452 } 5453 } 5454 } 5455 5456 if (nextLanes === NoLanes) { 5457 // This should only be reachable if we're suspended 5458 // TODO: Consider warning in this path if a fallback timer is not scheduled. 5459 return NoLanes; 5460 } // If we're already in the middle of a render, switching lanes will interrupt 5461 // it and we'll lose our progress. We should only do this if the new lanes are 5462 // higher priority. 5463 5464 5465 if (wipLanes !== NoLanes && wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't 5466 // bother waiting until the root is complete. 5467 (wipLanes & suspendedLanes) === NoLanes) { 5468 var nextLane = getHighestPriorityLane(nextLanes); 5469 var wipLane = getHighestPriorityLane(wipLanes); 5470 5471 if ( // Tests whether the next lane is equal or lower priority than the wip 5472 // one. This works because the bits decrease in priority as you go left. 5473 nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The 5474 // only difference between default updates and transition updates is that 5475 // default updates do not support refresh transitions. 5476 nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) { 5477 // Keep working on the existing in-progress tree. Do not interrupt. 5478 return wipLanes; 5479 } 5480 } 5481 5482 if ((nextLanes & InputContinuousLane) !== NoLanes) { 5483 // When updates are sync by default, we entangle continuous priority updates 5484 // and default updates, so they render in the same batch. The only reason 5485 // they use separate lanes is because continuous updates should interrupt 5486 // transitions, but default updates should not. 5487 nextLanes |= pendingLanes & DefaultLane; 5488 } // Check for entangled lanes and add them to the batch. 5489 // 5490 // A lane is said to be entangled with another when it's not allowed to render 5491 // in a batch that does not also include the other lane. Typically we do this 5492 // when multiple updates have the same source, and we only want to respond to 5493 // the most recent event from that source. 5494 // 5495 // Note that we apply entanglements *after* checking for partial work above. 5496 // This means that if a lane is entangled during an interleaved event while 5497 // it's already rendering, we won't interrupt it. This is intentional, since 5498 // entanglement is usually "best effort": we'll try our best to render the 5499 // lanes in the same batch, but it's not worth throwing out partially 5500 // completed work in order to do it. 5501 // TODO: Reconsider this. The counter-argument is that the partial work 5502 // represents an intermediate state, which we don't want to show to the user. 5503 // And by spending extra time finishing it, we're increasing the amount of 5504 // time it takes to show the final state, which is what they are actually 5505 // waiting for. 5506 // 5507 // For those exceptions where entanglement is semantically important, like 5508 // useMutableSource, we should ensure that there is no partial work at the 5509 // time we apply the entanglement. 5510 5511 5512 var entangledLanes = root.entangledLanes; 5513 5514 if (entangledLanes !== NoLanes) { 5515 var entanglements = root.entanglements; 5516 var lanes = nextLanes & entangledLanes; 5517 5518 while (lanes > 0) { 5519 var index = pickArbitraryLaneIndex(lanes); 5520 var lane = 1 << index; 5521 nextLanes |= entanglements[index]; 5522 lanes &= ~lane; 5523 } 5524 } 5525 5526 return nextLanes; 5527 } 5528 function getMostRecentEventTime(root, lanes) { 5529 var eventTimes = root.eventTimes; 5530 var mostRecentEventTime = NoTimestamp; 5531 5532 while (lanes > 0) { 5533 var index = pickArbitraryLaneIndex(lanes); 5534 var lane = 1 << index; 5535 var eventTime = eventTimes[index]; 5536 5537 if (eventTime > mostRecentEventTime) { 5538 mostRecentEventTime = eventTime; 5539 } 5540 5541 lanes &= ~lane; 5542 } 5543 5544 return mostRecentEventTime; 5545 } 5546 5547 function computeExpirationTime(lane, currentTime) { 5548 switch (lane) { 5549 case SyncLane: 5550 case InputContinuousHydrationLane: 5551 case InputContinuousLane: 5552 // User interactions should expire slightly more quickly. 5553 // 5554 // NOTE: This is set to the corresponding constant as in Scheduler.js. 5555 // When we made it larger, a product metric in www regressed, suggesting 5556 // there's a user interaction that's being starved by a series of 5557 // synchronous updates. If that theory is correct, the proper solution is 5558 // to fix the starvation. However, this scenario supports the idea that 5559 // expiration times are an important safeguard when starvation 5560 // does happen. 5561 return currentTime + 250; 5562 5563 case DefaultHydrationLane: 5564 case DefaultLane: 5565 case TransitionHydrationLane: 5566 case TransitionLane1: 5567 case TransitionLane2: 5568 case TransitionLane3: 5569 case TransitionLane4: 5570 case TransitionLane5: 5571 case TransitionLane6: 5572 case TransitionLane7: 5573 case TransitionLane8: 5574 case TransitionLane9: 5575 case TransitionLane10: 5576 case TransitionLane11: 5577 case TransitionLane12: 5578 case TransitionLane13: 5579 case TransitionLane14: 5580 case TransitionLane15: 5581 case TransitionLane16: 5582 return currentTime + 5000; 5583 5584 case RetryLane1: 5585 case RetryLane2: 5586 case RetryLane3: 5587 case RetryLane4: 5588 case RetryLane5: 5589 // TODO: Retries should be allowed to expire if they are CPU bound for 5590 // too long, but when I made this change it caused a spike in browser 5591 // crashes. There must be some other underlying bug; not super urgent but 5592 // ideally should figure out why and fix it. Unfortunately we don't have 5593 // a repro for the crashes, only detected via production metrics. 5594 return NoTimestamp; 5595 5596 case SelectiveHydrationLane: 5597 case IdleHydrationLane: 5598 case IdleLane: 5599 case OffscreenLane: 5600 // Anything idle priority or lower should never expire. 5601 return NoTimestamp; 5602 5603 default: 5604 { 5605 error('Should have found matching lanes. This is a bug in React.'); 5606 } 5607 5608 return NoTimestamp; 5609 } 5610 } 5611 5612 function markStarvedLanesAsExpired(root, currentTime) { 5613 // TODO: This gets called every time we yield. We can optimize by storing 5614 // the earliest expiration time on the root. Then use that to quickly bail out 5615 // of this function. 5616 var pendingLanes = root.pendingLanes; 5617 var suspendedLanes = root.suspendedLanes; 5618 var pingedLanes = root.pingedLanes; 5619 var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their 5620 // expiration time. If so, we'll assume the update is being starved and mark 5621 // it as expired to force it to finish. 5622 5623 var lanes = pendingLanes; 5624 5625 while (lanes > 0) { 5626 var index = pickArbitraryLaneIndex(lanes); 5627 var lane = 1 << index; 5628 var expirationTime = expirationTimes[index]; 5629 5630 if (expirationTime === NoTimestamp) { 5631 // Found a pending lane with no expiration time. If it's not suspended, or 5632 // if it's pinged, assume it's CPU-bound. Compute a new expiration time 5633 // using the current time. 5634 if ((lane & suspendedLanes) === NoLanes || (lane & pingedLanes) !== NoLanes) { 5635 // Assumes timestamps are monotonically increasing. 5636 expirationTimes[index] = computeExpirationTime(lane, currentTime); 5637 } 5638 } else if (expirationTime <= currentTime) { 5639 // This lane expired 5640 root.expiredLanes |= lane; 5641 } 5642 5643 lanes &= ~lane; 5644 } 5645 } // This returns the highest priority pending lanes regardless of whether they 5646 // are suspended. 5647 5648 function getHighestPriorityPendingLanes(root) { 5649 return getHighestPriorityLanes(root.pendingLanes); 5650 } 5651 function getLanesToRetrySynchronouslyOnError(root) { 5652 var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; 5653 5654 if (everythingButOffscreen !== NoLanes) { 5655 return everythingButOffscreen; 5656 } 5657 5658 if (everythingButOffscreen & OffscreenLane) { 5659 return OffscreenLane; 5660 } 5661 5662 return NoLanes; 5663 } 5664 function includesSyncLane(lanes) { 5665 return (lanes & SyncLane) !== NoLanes; 5666 } 5667 function includesNonIdleWork(lanes) { 5668 return (lanes & NonIdleLanes) !== NoLanes; 5669 } 5670 function includesOnlyRetries(lanes) { 5671 return (lanes & RetryLanes) === lanes; 5672 } 5673 function includesOnlyNonUrgentLanes(lanes) { 5674 var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; 5675 return (lanes & UrgentLanes) === NoLanes; 5676 } 5677 function includesOnlyTransitions(lanes) { 5678 return (lanes & TransitionLanes) === lanes; 5679 } 5680 function includesBlockingLane(root, lanes) { 5681 5682 var SyncDefaultLanes = InputContinuousHydrationLane | InputContinuousLane | DefaultHydrationLane | DefaultLane; 5683 return (lanes & SyncDefaultLanes) !== NoLanes; 5684 } 5685 function includesExpiredLane(root, lanes) { 5686 // This is a separate check from includesBlockingLane because a lane can 5687 // expire after a render has already started. 5688 return (lanes & root.expiredLanes) !== NoLanes; 5689 } 5690 function isTransitionLane(lane) { 5691 return (lane & TransitionLanes) !== NoLanes; 5692 } 5693 function claimNextTransitionLane() { 5694 // Cycle through the lanes, assigning each new transition to the next lane. 5695 // In most cases, this means every transition gets its own lane, until we 5696 // run out of lanes and cycle back to the beginning. 5697 var lane = nextTransitionLane; 5698 nextTransitionLane <<= 1; 5699 5700 if ((nextTransitionLane & TransitionLanes) === NoLanes) { 5701 nextTransitionLane = TransitionLane1; 5702 } 5703 5704 return lane; 5705 } 5706 function claimNextRetryLane() { 5707 var lane = nextRetryLane; 5708 nextRetryLane <<= 1; 5709 5710 if ((nextRetryLane & RetryLanes) === NoLanes) { 5711 nextRetryLane = RetryLane1; 5712 } 5713 5714 return lane; 5715 } 5716 function getHighestPriorityLane(lanes) { 5717 return lanes & -lanes; 5718 } 5719 function pickArbitraryLane(lanes) { 5720 // This wrapper function gets inlined. Only exists so to communicate that it 5721 // doesn't matter which bit is selected; you can pick any bit without 5722 // affecting the algorithms where its used. Here I'm using 5723 // getHighestPriorityLane because it requires the fewest operations. 5724 return getHighestPriorityLane(lanes); 5725 } 5726 5727 function pickArbitraryLaneIndex(lanes) { 5728 return 31 - clz32(lanes); 5729 } 5730 5731 function laneToIndex(lane) { 5732 return pickArbitraryLaneIndex(lane); 5733 } 5734 5735 function includesSomeLane(a, b) { 5736 return (a & b) !== NoLanes; 5737 } 5738 function isSubsetOfLanes(set, subset) { 5739 return (set & subset) === subset; 5740 } 5741 function mergeLanes(a, b) { 5742 return a | b; 5743 } 5744 function removeLanes(set, subset) { 5745 return set & ~subset; 5746 } 5747 function intersectLanes(a, b) { 5748 return a & b; 5749 } // Seems redundant, but it changes the type from a single lane (used for 5750 // updates) to a group of lanes (used for flushing work). 5751 5752 function laneToLanes(lane) { 5753 return lane; 5754 } 5755 function higherPriorityLane(a, b) { 5756 // This works because the bit ranges decrease in priority as you go left. 5757 return a !== NoLane && a < b ? a : b; 5758 } 5759 function createLaneMap(initial) { 5760 // Intentionally pushing one by one. 5761 // https://v8.dev/blog/elements-kinds#avoid-creating-holes 5762 var laneMap = []; 5763 5764 for (var i = 0; i < TotalLanes; i++) { 5765 laneMap.push(initial); 5766 } 5767 5768 return laneMap; 5769 } 5770 function markRootUpdated(root, updateLane, eventTime) { 5771 root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update 5772 // could unblock them. Clear the suspended lanes so that we can try rendering 5773 // them again. 5774 // 5775 // TODO: We really only need to unsuspend only lanes that are in the 5776 // `subtreeLanes` of the updated fiber, or the update lanes of the return 5777 // path. This would exclude suspended updates in an unrelated sibling tree, 5778 // since there's no way for this update to unblock it. 5779 // 5780 // We don't do this if the incoming update is idle, because we never process 5781 // idle updates until after all the regular updates have finished; there's no 5782 // way it could unblock a transition. 5783 5784 if (updateLane !== IdleLane) { 5785 root.suspendedLanes = NoLanes; 5786 root.pingedLanes = NoLanes; 5787 } 5788 5789 var eventTimes = root.eventTimes; 5790 var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most 5791 // recent event, and we assume time is monotonically increasing. 5792 5793 eventTimes[index] = eventTime; 5794 } 5795 function markRootSuspended(root, suspendedLanes) { 5796 root.suspendedLanes |= suspendedLanes; 5797 root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. 5798 5799 var expirationTimes = root.expirationTimes; 5800 var lanes = suspendedLanes; 5801 5802 while (lanes > 0) { 5803 var index = pickArbitraryLaneIndex(lanes); 5804 var lane = 1 << index; 5805 expirationTimes[index] = NoTimestamp; 5806 lanes &= ~lane; 5807 } 5808 } 5809 function markRootPinged(root, pingedLanes, eventTime) { 5810 root.pingedLanes |= root.suspendedLanes & pingedLanes; 5811 } 5812 function markRootFinished(root, remainingLanes) { 5813 var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; 5814 root.pendingLanes = remainingLanes; // Let's try everything again 5815 5816 root.suspendedLanes = NoLanes; 5817 root.pingedLanes = NoLanes; 5818 root.expiredLanes &= remainingLanes; 5819 root.mutableReadLanes &= remainingLanes; 5820 root.entangledLanes &= remainingLanes; 5821 var entanglements = root.entanglements; 5822 var eventTimes = root.eventTimes; 5823 var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work 5824 5825 var lanes = noLongerPendingLanes; 5826 5827 while (lanes > 0) { 5828 var index = pickArbitraryLaneIndex(lanes); 5829 var lane = 1 << index; 5830 entanglements[index] = NoLanes; 5831 eventTimes[index] = NoTimestamp; 5832 expirationTimes[index] = NoTimestamp; 5833 lanes &= ~lane; 5834 } 5835 } 5836 function markRootEntangled(root, entangledLanes) { 5837 // In addition to entangling each of the given lanes with each other, we also 5838 // have to consider _transitive_ entanglements. For each lane that is already 5839 // entangled with *any* of the given lanes, that lane is now transitively 5840 // entangled with *all* the given lanes. 5841 // 5842 // Translated: If C is entangled with A, then entangling A with B also 5843 // entangles C with B. 5844 // 5845 // If this is hard to grasp, it might help to intentionally break this 5846 // function and look at the tests that fail in ReactTransition-test.js. Try 5847 // commenting out one of the conditions below. 5848 var rootEntangledLanes = root.entangledLanes |= entangledLanes; 5849 var entanglements = root.entanglements; 5850 var lanes = rootEntangledLanes; 5851 5852 while (lanes) { 5853 var index = pickArbitraryLaneIndex(lanes); 5854 var lane = 1 << index; 5855 5856 if ( // Is this one of the newly entangled lanes? 5857 lane & entangledLanes | // Is this lane transitively entangled with the newly entangled lanes? 5858 entanglements[index] & entangledLanes) { 5859 entanglements[index] |= entangledLanes; 5860 } 5861 5862 lanes &= ~lane; 5863 } 5864 } 5865 function getBumpedLaneForHydration(root, renderLanes) { 5866 var renderLane = getHighestPriorityLane(renderLanes); 5867 var lane; 5868 5869 switch (renderLane) { 5870 case InputContinuousLane: 5871 lane = InputContinuousHydrationLane; 5872 break; 5873 5874 case DefaultLane: 5875 lane = DefaultHydrationLane; 5876 break; 5877 5878 case TransitionLane1: 5879 case TransitionLane2: 5880 case TransitionLane3: 5881 case TransitionLane4: 5882 case TransitionLane5: 5883 case TransitionLane6: 5884 case TransitionLane7: 5885 case TransitionLane8: 5886 case TransitionLane9: 5887 case TransitionLane10: 5888 case TransitionLane11: 5889 case TransitionLane12: 5890 case TransitionLane13: 5891 case TransitionLane14: 5892 case TransitionLane15: 5893 case TransitionLane16: 5894 case RetryLane1: 5895 case RetryLane2: 5896 case RetryLane3: 5897 case RetryLane4: 5898 case RetryLane5: 5899 lane = TransitionHydrationLane; 5900 break; 5901 5902 case IdleLane: 5903 lane = IdleHydrationLane; 5904 break; 5905 5906 default: 5907 // Everything else is already either a hydration lane, or shouldn't 5908 // be retried at a hydration lane. 5909 lane = NoLane; 5910 break; 5911 } // Check if the lane we chose is suspended. If so, that indicates that we 5912 // already attempted and failed to hydrate at that level. Also check if we're 5913 // already rendering that lane, which is rare but could happen. 5914 5915 5916 if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { 5917 // Give up trying to hydrate and fall back to client render. 5918 return NoLane; 5919 } 5920 5921 return lane; 5922 } 5923 function addFiberToLanesMap(root, fiber, lanes) { 5924 5925 if (!isDevToolsPresent) { 5926 return; 5927 } 5928 5929 var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; 5930 5931 while (lanes > 0) { 5932 var index = laneToIndex(lanes); 5933 var lane = 1 << index; 5934 var updaters = pendingUpdatersLaneMap[index]; 5935 updaters.add(fiber); 5936 lanes &= ~lane; 5937 } 5938 } 5939 function movePendingFibersToMemoized(root, lanes) { 5940 5941 if (!isDevToolsPresent) { 5942 return; 5943 } 5944 5945 var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; 5946 var memoizedUpdaters = root.memoizedUpdaters; 5947 5948 while (lanes > 0) { 5949 var index = laneToIndex(lanes); 5950 var lane = 1 << index; 5951 var updaters = pendingUpdatersLaneMap[index]; 5952 5953 if (updaters.size > 0) { 5954 updaters.forEach(function (fiber) { 5955 var alternate = fiber.alternate; 5956 5957 if (alternate === null || !memoizedUpdaters.has(alternate)) { 5958 memoizedUpdaters.add(fiber); 5959 } 5960 }); 5961 updaters.clear(); 5962 } 5963 5964 lanes &= ~lane; 5965 } 5966 } 5967 function getTransitionsForLanes(root, lanes) { 5968 { 5969 return null; 5970 } 5971 } 5972 5973 var DiscreteEventPriority = SyncLane; 5974 var ContinuousEventPriority = InputContinuousLane; 5975 var DefaultEventPriority = DefaultLane; 5976 var IdleEventPriority = IdleLane; 5977 var currentUpdatePriority = NoLane; 5978 function getCurrentUpdatePriority() { 5979 return currentUpdatePriority; 5980 } 5981 function setCurrentUpdatePriority(newPriority) { 5982 currentUpdatePriority = newPriority; 5983 } 5984 function runWithPriority(priority, fn) { 5985 var previousPriority = currentUpdatePriority; 5986 5987 try { 5988 currentUpdatePriority = priority; 5989 return fn(); 5990 } finally { 5991 currentUpdatePriority = previousPriority; 5992 } 5993 } 5994 function higherEventPriority(a, b) { 5995 return a !== 0 && a < b ? a : b; 5996 } 5997 function lowerEventPriority(a, b) { 5998 return a === 0 || a > b ? a : b; 5999 } 6000 function isHigherEventPriority(a, b) { 6001 return a !== 0 && a < b; 6002 } 6003 function lanesToEventPriority(lanes) { 6004 var lane = getHighestPriorityLane(lanes); 6005 6006 if (!isHigherEventPriority(DiscreteEventPriority, lane)) { 6007 return DiscreteEventPriority; 6008 } 6009 6010 if (!isHigherEventPriority(ContinuousEventPriority, lane)) { 6011 return ContinuousEventPriority; 6012 } 6013 6014 if (includesNonIdleWork(lane)) { 6015 return DefaultEventPriority; 6016 } 6017 6018 return IdleEventPriority; 6019 } 6020 6021 // This is imported by the event replaying implementation in React DOM. It's 6022 // in a separate file to break a circular dependency between the renderer and 6023 // the reconciler. 6024 function isRootDehydrated(root) { 6025 var currentState = root.current.memoizedState; 6026 return currentState.isDehydrated; 6027 } 6028 6029 var _attemptSynchronousHydration; 6030 6031 function setAttemptSynchronousHydration(fn) { 6032 _attemptSynchronousHydration = fn; 6033 } 6034 function attemptSynchronousHydration(fiber) { 6035 _attemptSynchronousHydration(fiber); 6036 } 6037 var attemptContinuousHydration; 6038 function setAttemptContinuousHydration(fn) { 6039 attemptContinuousHydration = fn; 6040 } 6041 var attemptHydrationAtCurrentPriority; 6042 function setAttemptHydrationAtCurrentPriority(fn) { 6043 attemptHydrationAtCurrentPriority = fn; 6044 } 6045 var getCurrentUpdatePriority$1; 6046 function setGetCurrentUpdatePriority(fn) { 6047 getCurrentUpdatePriority$1 = fn; 6048 } 6049 var attemptHydrationAtPriority; 6050 function setAttemptHydrationAtPriority(fn) { 6051 attemptHydrationAtPriority = fn; 6052 } // TODO: Upgrade this definition once we're on a newer version of Flow that 6053 // has this definition built-in. 6054 6055 var hasScheduledReplayAttempt = false; // The queue of discrete events to be replayed. 6056 6057 var queuedDiscreteEvents = []; // Indicates if any continuous event targets are non-null for early bailout. 6058 // if the last target was dehydrated. 6059 6060 var queuedFocus = null; 6061 var queuedDrag = null; 6062 var queuedMouse = null; // For pointer events there can be one latest event per pointerId. 6063 6064 var queuedPointers = new Map(); 6065 var queuedPointerCaptures = new Map(); // We could consider replaying selectionchange and touchmoves too. 6066 6067 var queuedExplicitHydrationTargets = []; 6068 var discreteReplayableEvents = ['mousedown', 'mouseup', 'touchcancel', 'touchend', 'touchstart', 'auxclick', 'dblclick', 'pointercancel', 'pointerdown', 'pointerup', 'dragend', 'dragstart', 'drop', 'compositionend', 'compositionstart', 'keydown', 'keypress', 'keyup', 'input', 'textInput', // Intentionally camelCase 6069 'copy', 'cut', 'paste', 'click', 'change', 'contextmenu', 'reset', 'submit']; 6070 function isDiscreteEventThatRequiresHydration(eventType) { 6071 return discreteReplayableEvents.indexOf(eventType) > -1; 6072 } 6073 6074 function createQueuedReplayableEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6075 return { 6076 blockedOn: blockedOn, 6077 domEventName: domEventName, 6078 eventSystemFlags: eventSystemFlags, 6079 nativeEvent: nativeEvent, 6080 targetContainers: [targetContainer] 6081 }; 6082 } 6083 6084 function clearIfContinuousEvent(domEventName, nativeEvent) { 6085 switch (domEventName) { 6086 case 'focusin': 6087 case 'focusout': 6088 queuedFocus = null; 6089 break; 6090 6091 case 'dragenter': 6092 case 'dragleave': 6093 queuedDrag = null; 6094 break; 6095 6096 case 'mouseover': 6097 case 'mouseout': 6098 queuedMouse = null; 6099 break; 6100 6101 case 'pointerover': 6102 case 'pointerout': 6103 { 6104 var pointerId = nativeEvent.pointerId; 6105 queuedPointers.delete(pointerId); 6106 break; 6107 } 6108 6109 case 'gotpointercapture': 6110 case 'lostpointercapture': 6111 { 6112 var _pointerId = nativeEvent.pointerId; 6113 queuedPointerCaptures.delete(_pointerId); 6114 break; 6115 } 6116 } 6117 } 6118 6119 function accumulateOrCreateContinuousQueuedReplayableEvent(existingQueuedEvent, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6120 if (existingQueuedEvent === null || existingQueuedEvent.nativeEvent !== nativeEvent) { 6121 var queuedEvent = createQueuedReplayableEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent); 6122 6123 if (blockedOn !== null) { 6124 var _fiber2 = getInstanceFromNode(blockedOn); 6125 6126 if (_fiber2 !== null) { 6127 // Attempt to increase the priority of this target. 6128 attemptContinuousHydration(_fiber2); 6129 } 6130 } 6131 6132 return queuedEvent; 6133 } // If we have already queued this exact event, then it's because 6134 // the different event systems have different DOM event listeners. 6135 // We can accumulate the flags, and the targetContainers, and 6136 // store a single event to be replayed. 6137 6138 6139 existingQueuedEvent.eventSystemFlags |= eventSystemFlags; 6140 var targetContainers = existingQueuedEvent.targetContainers; 6141 6142 if (targetContainer !== null && targetContainers.indexOf(targetContainer) === -1) { 6143 targetContainers.push(targetContainer); 6144 } 6145 6146 return existingQueuedEvent; 6147 } 6148 6149 function queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6150 // These set relatedTarget to null because the replayed event will be treated as if we 6151 // moved from outside the window (no target) onto the target once it hydrates. 6152 // Instead of mutating we could clone the event. 6153 switch (domEventName) { 6154 case 'focusin': 6155 { 6156 var focusEvent = nativeEvent; 6157 queuedFocus = accumulateOrCreateContinuousQueuedReplayableEvent(queuedFocus, blockedOn, domEventName, eventSystemFlags, targetContainer, focusEvent); 6158 return true; 6159 } 6160 6161 case 'dragenter': 6162 { 6163 var dragEvent = nativeEvent; 6164 queuedDrag = accumulateOrCreateContinuousQueuedReplayableEvent(queuedDrag, blockedOn, domEventName, eventSystemFlags, targetContainer, dragEvent); 6165 return true; 6166 } 6167 6168 case 'mouseover': 6169 { 6170 var mouseEvent = nativeEvent; 6171 queuedMouse = accumulateOrCreateContinuousQueuedReplayableEvent(queuedMouse, blockedOn, domEventName, eventSystemFlags, targetContainer, mouseEvent); 6172 return true; 6173 } 6174 6175 case 'pointerover': 6176 { 6177 var pointerEvent = nativeEvent; 6178 var pointerId = pointerEvent.pointerId; 6179 queuedPointers.set(pointerId, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointers.get(pointerId) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, pointerEvent)); 6180 return true; 6181 } 6182 6183 case 'gotpointercapture': 6184 { 6185 var _pointerEvent = nativeEvent; 6186 var _pointerId2 = _pointerEvent.pointerId; 6187 queuedPointerCaptures.set(_pointerId2, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointerCaptures.get(_pointerId2) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, _pointerEvent)); 6188 return true; 6189 } 6190 } 6191 6192 return false; 6193 } // Check if this target is unblocked. Returns true if it's unblocked. 6194 6195 function attemptExplicitHydrationTarget(queuedTarget) { 6196 // TODO: This function shares a lot of logic with findInstanceBlockingEvent. 6197 // Try to unify them. It's a bit tricky since it would require two return 6198 // values. 6199 var targetInst = getClosestInstanceFromNode(queuedTarget.target); 6200 6201 if (targetInst !== null) { 6202 var nearestMounted = getNearestMountedFiber(targetInst); 6203 6204 if (nearestMounted !== null) { 6205 var tag = nearestMounted.tag; 6206 6207 if (tag === SuspenseComponent) { 6208 var instance = getSuspenseInstanceFromFiber(nearestMounted); 6209 6210 if (instance !== null) { 6211 // We're blocked on hydrating this boundary. 6212 // Increase its priority. 6213 queuedTarget.blockedOn = instance; 6214 attemptHydrationAtPriority(queuedTarget.priority, function () { 6215 attemptHydrationAtCurrentPriority(nearestMounted); 6216 }); 6217 return; 6218 } 6219 } else if (tag === HostRoot) { 6220 var root = nearestMounted.stateNode; 6221 6222 if (isRootDehydrated(root)) { 6223 queuedTarget.blockedOn = getContainerFromFiber(nearestMounted); // We don't currently have a way to increase the priority of 6224 // a root other than sync. 6225 6226 return; 6227 } 6228 } 6229 } 6230 } 6231 6232 queuedTarget.blockedOn = null; 6233 } 6234 6235 function queueExplicitHydrationTarget(target) { 6236 // TODO: This will read the priority if it's dispatched by the React 6237 // event system but not native events. Should read window.event.type, like 6238 // we do for updates (getCurrentEventPriority). 6239 var updatePriority = getCurrentUpdatePriority$1(); 6240 var queuedTarget = { 6241 blockedOn: null, 6242 target: target, 6243 priority: updatePriority 6244 }; 6245 var i = 0; 6246 6247 for (; i < queuedExplicitHydrationTargets.length; i++) { 6248 // Stop once we hit the first target with lower priority than 6249 if (!isHigherEventPriority(updatePriority, queuedExplicitHydrationTargets[i].priority)) { 6250 break; 6251 } 6252 } 6253 6254 queuedExplicitHydrationTargets.splice(i, 0, queuedTarget); 6255 6256 if (i === 0) { 6257 attemptExplicitHydrationTarget(queuedTarget); 6258 } 6259 } 6260 6261 function attemptReplayContinuousQueuedEvent(queuedEvent) { 6262 if (queuedEvent.blockedOn !== null) { 6263 return false; 6264 } 6265 6266 var targetContainers = queuedEvent.targetContainers; 6267 6268 while (targetContainers.length > 0) { 6269 var targetContainer = targetContainers[0]; 6270 var nextBlockedOn = findInstanceBlockingEvent(queuedEvent.domEventName, queuedEvent.eventSystemFlags, targetContainer, queuedEvent.nativeEvent); 6271 6272 if (nextBlockedOn === null) { 6273 { 6274 var nativeEvent = queuedEvent.nativeEvent; 6275 var nativeEventClone = new nativeEvent.constructor(nativeEvent.type, nativeEvent); 6276 setReplayingEvent(nativeEventClone); 6277 nativeEvent.target.dispatchEvent(nativeEventClone); 6278 resetReplayingEvent(); 6279 } 6280 } else { 6281 // We're still blocked. Try again later. 6282 var _fiber3 = getInstanceFromNode(nextBlockedOn); 6283 6284 if (_fiber3 !== null) { 6285 attemptContinuousHydration(_fiber3); 6286 } 6287 6288 queuedEvent.blockedOn = nextBlockedOn; 6289 return false; 6290 } // This target container was successfully dispatched. Try the next. 6291 6292 6293 targetContainers.shift(); 6294 } 6295 6296 return true; 6297 } 6298 6299 function attemptReplayContinuousQueuedEventInMap(queuedEvent, key, map) { 6300 if (attemptReplayContinuousQueuedEvent(queuedEvent)) { 6301 map.delete(key); 6302 } 6303 } 6304 6305 function replayUnblockedEvents() { 6306 hasScheduledReplayAttempt = false; 6307 6308 6309 if (queuedFocus !== null && attemptReplayContinuousQueuedEvent(queuedFocus)) { 6310 queuedFocus = null; 6311 } 6312 6313 if (queuedDrag !== null && attemptReplayContinuousQueuedEvent(queuedDrag)) { 6314 queuedDrag = null; 6315 } 6316 6317 if (queuedMouse !== null && attemptReplayContinuousQueuedEvent(queuedMouse)) { 6318 queuedMouse = null; 6319 } 6320 6321 queuedPointers.forEach(attemptReplayContinuousQueuedEventInMap); 6322 queuedPointerCaptures.forEach(attemptReplayContinuousQueuedEventInMap); 6323 } 6324 6325 function scheduleCallbackIfUnblocked(queuedEvent, unblocked) { 6326 if (queuedEvent.blockedOn === unblocked) { 6327 queuedEvent.blockedOn = null; 6328 6329 if (!hasScheduledReplayAttempt) { 6330 hasScheduledReplayAttempt = true; // Schedule a callback to attempt replaying as many events as are 6331 // now unblocked. This first might not actually be unblocked yet. 6332 // We could check it early to avoid scheduling an unnecessary callback. 6333 6334 unstable_scheduleCallback(unstable_NormalPriority, replayUnblockedEvents); 6335 } 6336 } 6337 } 6338 6339 function retryIfBlockedOn(unblocked) { 6340 // Mark anything that was blocked on this as no longer blocked 6341 // and eligible for a replay. 6342 if (queuedDiscreteEvents.length > 0) { 6343 scheduleCallbackIfUnblocked(queuedDiscreteEvents[0], unblocked); // This is a exponential search for each boundary that commits. I think it's 6344 // worth it because we expect very few discrete events to queue up and once 6345 // we are actually fully unblocked it will be fast to replay them. 6346 6347 for (var i = 1; i < queuedDiscreteEvents.length; i++) { 6348 var queuedEvent = queuedDiscreteEvents[i]; 6349 6350 if (queuedEvent.blockedOn === unblocked) { 6351 queuedEvent.blockedOn = null; 6352 } 6353 } 6354 } 6355 6356 if (queuedFocus !== null) { 6357 scheduleCallbackIfUnblocked(queuedFocus, unblocked); 6358 } 6359 6360 if (queuedDrag !== null) { 6361 scheduleCallbackIfUnblocked(queuedDrag, unblocked); 6362 } 6363 6364 if (queuedMouse !== null) { 6365 scheduleCallbackIfUnblocked(queuedMouse, unblocked); 6366 } 6367 6368 var unblock = function (queuedEvent) { 6369 return scheduleCallbackIfUnblocked(queuedEvent, unblocked); 6370 }; 6371 6372 queuedPointers.forEach(unblock); 6373 queuedPointerCaptures.forEach(unblock); 6374 6375 for (var _i = 0; _i < queuedExplicitHydrationTargets.length; _i++) { 6376 var queuedTarget = queuedExplicitHydrationTargets[_i]; 6377 6378 if (queuedTarget.blockedOn === unblocked) { 6379 queuedTarget.blockedOn = null; 6380 } 6381 } 6382 6383 while (queuedExplicitHydrationTargets.length > 0) { 6384 var nextExplicitTarget = queuedExplicitHydrationTargets[0]; 6385 6386 if (nextExplicitTarget.blockedOn !== null) { 6387 // We're still blocked. 6388 break; 6389 } else { 6390 attemptExplicitHydrationTarget(nextExplicitTarget); 6391 6392 if (nextExplicitTarget.blockedOn === null) { 6393 // We're unblocked. 6394 queuedExplicitHydrationTargets.shift(); 6395 } 6396 } 6397 } 6398 } 6399 6400 var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; // TODO: can we stop exporting these? 6401 6402 var _enabled = true; // This is exported in FB builds for use by legacy FB layer infra. 6403 // We'd like to remove this but it's not clear if this is safe. 6404 6405 function setEnabled(enabled) { 6406 _enabled = !!enabled; 6407 } 6408 function isEnabled() { 6409 return _enabled; 6410 } 6411 function createEventListenerWrapperWithPriority(targetContainer, domEventName, eventSystemFlags) { 6412 var eventPriority = getEventPriority(domEventName); 6413 var listenerWrapper; 6414 6415 switch (eventPriority) { 6416 case DiscreteEventPriority: 6417 listenerWrapper = dispatchDiscreteEvent; 6418 break; 6419 6420 case ContinuousEventPriority: 6421 listenerWrapper = dispatchContinuousEvent; 6422 break; 6423 6424 case DefaultEventPriority: 6425 default: 6426 listenerWrapper = dispatchEvent; 6427 break; 6428 } 6429 6430 return listenerWrapper.bind(null, domEventName, eventSystemFlags, targetContainer); 6431 } 6432 6433 function dispatchDiscreteEvent(domEventName, eventSystemFlags, container, nativeEvent) { 6434 var previousPriority = getCurrentUpdatePriority(); 6435 var prevTransition = ReactCurrentBatchConfig.transition; 6436 ReactCurrentBatchConfig.transition = null; 6437 6438 try { 6439 setCurrentUpdatePriority(DiscreteEventPriority); 6440 dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); 6441 } finally { 6442 setCurrentUpdatePriority(previousPriority); 6443 ReactCurrentBatchConfig.transition = prevTransition; 6444 } 6445 } 6446 6447 function dispatchContinuousEvent(domEventName, eventSystemFlags, container, nativeEvent) { 6448 var previousPriority = getCurrentUpdatePriority(); 6449 var prevTransition = ReactCurrentBatchConfig.transition; 6450 ReactCurrentBatchConfig.transition = null; 6451 6452 try { 6453 setCurrentUpdatePriority(ContinuousEventPriority); 6454 dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); 6455 } finally { 6456 setCurrentUpdatePriority(previousPriority); 6457 ReactCurrentBatchConfig.transition = prevTransition; 6458 } 6459 } 6460 6461 function dispatchEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6462 if (!_enabled) { 6463 return; 6464 } 6465 6466 { 6467 dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6468 } 6469 } 6470 6471 function dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6472 var blockedOn = findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6473 6474 if (blockedOn === null) { 6475 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer); 6476 clearIfContinuousEvent(domEventName, nativeEvent); 6477 return; 6478 } 6479 6480 if (queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent)) { 6481 nativeEvent.stopPropagation(); 6482 return; 6483 } // We need to clear only if we didn't queue because 6484 // queueing is accumulative. 6485 6486 6487 clearIfContinuousEvent(domEventName, nativeEvent); 6488 6489 if (eventSystemFlags & IS_CAPTURE_PHASE && isDiscreteEventThatRequiresHydration(domEventName)) { 6490 while (blockedOn !== null) { 6491 var fiber = getInstanceFromNode(blockedOn); 6492 6493 if (fiber !== null) { 6494 attemptSynchronousHydration(fiber); 6495 } 6496 6497 var nextBlockedOn = findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6498 6499 if (nextBlockedOn === null) { 6500 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer); 6501 } 6502 6503 if (nextBlockedOn === blockedOn) { 6504 break; 6505 } 6506 6507 blockedOn = nextBlockedOn; 6508 } 6509 6510 if (blockedOn !== null) { 6511 nativeEvent.stopPropagation(); 6512 } 6513 6514 return; 6515 } // This is not replayable so we'll invoke it but without a target, 6516 // in case the event system needs to trace it. 6517 6518 6519 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, null, targetContainer); 6520 } 6521 6522 var return_targetInst = null; // Returns a SuspenseInstance or Container if it's blocked. 6523 // The return_targetInst field above is conceptually part of the return value. 6524 6525 function findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6526 // TODO: Warn if _enabled is false. 6527 return_targetInst = null; 6528 var nativeEventTarget = getEventTarget(nativeEvent); 6529 var targetInst = getClosestInstanceFromNode(nativeEventTarget); 6530 6531 if (targetInst !== null) { 6532 var nearestMounted = getNearestMountedFiber(targetInst); 6533 6534 if (nearestMounted === null) { 6535 // This tree has been unmounted already. Dispatch without a target. 6536 targetInst = null; 6537 } else { 6538 var tag = nearestMounted.tag; 6539 6540 if (tag === SuspenseComponent) { 6541 var instance = getSuspenseInstanceFromFiber(nearestMounted); 6542 6543 if (instance !== null) { 6544 // Queue the event to be replayed later. Abort dispatching since we 6545 // don't want this event dispatched twice through the event system. 6546 // TODO: If this is the first discrete event in the queue. Schedule an increased 6547 // priority for this boundary. 6548 return instance; 6549 } // This shouldn't happen, something went wrong but to avoid blocking 6550 // the whole system, dispatch the event without a target. 6551 // TODO: Warn. 6552 6553 6554 targetInst = null; 6555 } else if (tag === HostRoot) { 6556 var root = nearestMounted.stateNode; 6557 6558 if (isRootDehydrated(root)) { 6559 // If this happens during a replay something went wrong and it might block 6560 // the whole system. 6561 return getContainerFromFiber(nearestMounted); 6562 } 6563 6564 targetInst = null; 6565 } else if (nearestMounted !== targetInst) { 6566 // If we get an event (ex: img onload) before committing that 6567 // component's mount, ignore it for now (that is, treat it as if it was an 6568 // event on a non-React tree). We might also consider queueing events and 6569 // dispatching them after the mount. 6570 targetInst = null; 6571 } 6572 } 6573 } 6574 6575 return_targetInst = targetInst; // We're not blocked on anything. 6576 6577 return null; 6578 } 6579 function getEventPriority(domEventName) { 6580 switch (domEventName) { 6581 // Used by SimpleEventPlugin: 6582 case 'cancel': 6583 case 'click': 6584 case 'close': 6585 case 'contextmenu': 6586 case 'copy': 6587 case 'cut': 6588 case 'auxclick': 6589 case 'dblclick': 6590 case 'dragend': 6591 case 'dragstart': 6592 case 'drop': 6593 case 'focusin': 6594 case 'focusout': 6595 case 'input': 6596 case 'invalid': 6597 case 'keydown': 6598 case 'keypress': 6599 case 'keyup': 6600 case 'mousedown': 6601 case 'mouseup': 6602 case 'paste': 6603 case 'pause': 6604 case 'play': 6605 case 'pointercancel': 6606 case 'pointerdown': 6607 case 'pointerup': 6608 case 'ratechange': 6609 case 'reset': 6610 case 'resize': 6611 case 'seeked': 6612 case 'submit': 6613 case 'touchcancel': 6614 case 'touchend': 6615 case 'touchstart': 6616 case 'volumechange': // Used by polyfills: 6617 // eslint-disable-next-line no-fallthrough 6618 6619 case 'change': 6620 case 'selectionchange': 6621 case 'textInput': 6622 case 'compositionstart': 6623 case 'compositionend': 6624 case 'compositionupdate': // Only enableCreateEventHandleAPI: 6625 // eslint-disable-next-line no-fallthrough 6626 6627 case 'beforeblur': 6628 case 'afterblur': // Not used by React but could be by user code: 6629 // eslint-disable-next-line no-fallthrough 6630 6631 case 'beforeinput': 6632 case 'blur': 6633 case 'fullscreenchange': 6634 case 'focus': 6635 case 'hashchange': 6636 case 'popstate': 6637 case 'select': 6638 case 'selectstart': 6639 return DiscreteEventPriority; 6640 6641 case 'drag': 6642 case 'dragenter': 6643 case 'dragexit': 6644 case 'dragleave': 6645 case 'dragover': 6646 case 'mousemove': 6647 case 'mouseout': 6648 case 'mouseover': 6649 case 'pointermove': 6650 case 'pointerout': 6651 case 'pointerover': 6652 case 'scroll': 6653 case 'toggle': 6654 case 'touchmove': 6655 case 'wheel': // Not used by React but could be by user code: 6656 // eslint-disable-next-line no-fallthrough 6657 6658 case 'mouseenter': 6659 case 'mouseleave': 6660 case 'pointerenter': 6661 case 'pointerleave': 6662 return ContinuousEventPriority; 6663 6664 case 'message': 6665 { 6666 // We might be in the Scheduler callback. 6667 // Eventually this mechanism will be replaced by a check 6668 // of the current priority on the native scheduler. 6669 var schedulerPriority = getCurrentPriorityLevel(); 6670 6671 switch (schedulerPriority) { 6672 case ImmediatePriority: 6673 return DiscreteEventPriority; 6674 6675 case UserBlockingPriority: 6676 return ContinuousEventPriority; 6677 6678 case NormalPriority: 6679 case LowPriority: 6680 // TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration. 6681 return DefaultEventPriority; 6682 6683 case IdlePriority: 6684 return IdleEventPriority; 6685 6686 default: 6687 return DefaultEventPriority; 6688 } 6689 } 6690 6691 default: 6692 return DefaultEventPriority; 6693 } 6694 } 6695 6696 function addEventBubbleListener(target, eventType, listener) { 6697 target.addEventListener(eventType, listener, false); 6698 return listener; 6699 } 6700 function addEventCaptureListener(target, eventType, listener) { 6701 target.addEventListener(eventType, listener, true); 6702 return listener; 6703 } 6704 function addEventCaptureListenerWithPassiveFlag(target, eventType, listener, passive) { 6705 target.addEventListener(eventType, listener, { 6706 capture: true, 6707 passive: passive 6708 }); 6709 return listener; 6710 } 6711 function addEventBubbleListenerWithPassiveFlag(target, eventType, listener, passive) { 6712 target.addEventListener(eventType, listener, { 6713 passive: passive 6714 }); 6715 return listener; 6716 } 6717 6718 /** 6719 * These variables store information about text content of a target node, 6720 * allowing comparison of content before and after a given event. 6721 * 6722 * Identify the node where selection currently begins, then observe 6723 * both its text content and its current position in the DOM. Since the 6724 * browser may natively replace the target node during composition, we can 6725 * use its position to find its replacement. 6726 * 6727 * 6728 */ 6729 var root = null; 6730 var startText = null; 6731 var fallbackText = null; 6732 function initialize(nativeEventTarget) { 6733 root = nativeEventTarget; 6734 startText = getText(); 6735 return true; 6736 } 6737 function reset() { 6738 root = null; 6739 startText = null; 6740 fallbackText = null; 6741 } 6742 function getData() { 6743 if (fallbackText) { 6744 return fallbackText; 6745 } 6746 6747 var start; 6748 var startValue = startText; 6749 var startLength = startValue.length; 6750 var end; 6751 var endValue = getText(); 6752 var endLength = endValue.length; 6753 6754 for (start = 0; start < startLength; start++) { 6755 if (startValue[start] !== endValue[start]) { 6756 break; 6757 } 6758 } 6759 6760 var minEnd = startLength - start; 6761 6762 for (end = 1; end <= minEnd; end++) { 6763 if (startValue[startLength - end] !== endValue[endLength - end]) { 6764 break; 6765 } 6766 } 6767 6768 var sliceTail = end > 1 ? 1 - end : undefined; 6769 fallbackText = endValue.slice(start, sliceTail); 6770 return fallbackText; 6771 } 6772 function getText() { 6773 if ('value' in root) { 6774 return root.value; 6775 } 6776 6777 return root.textContent; 6778 } 6779 6780 /** 6781 * `charCode` represents the actual "character code" and is safe to use with 6782 * `String.fromCharCode`. As such, only keys that correspond to printable 6783 * characters produce a valid `charCode`, the only exception to this is Enter. 6784 * The Tab-key is considered non-printable and does not have a `charCode`, 6785 * presumably because it does not produce a tab-character in browsers. 6786 * 6787 * @param {object} nativeEvent Native browser event. 6788 * @return {number} Normalized `charCode` property. 6789 */ 6790 function getEventCharCode(nativeEvent) { 6791 var charCode; 6792 var keyCode = nativeEvent.keyCode; 6793 6794 if ('charCode' in nativeEvent) { 6795 charCode = nativeEvent.charCode; // FF does not set `charCode` for the Enter-key, check against `keyCode`. 6796 6797 if (charCode === 0 && keyCode === 13) { 6798 charCode = 13; 6799 } 6800 } else { 6801 // IE8 does not implement `charCode`, but `keyCode` has the correct value. 6802 charCode = keyCode; 6803 } // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux) 6804 // report Enter as charCode 10 when ctrl is pressed. 6805 6806 6807 if (charCode === 10) { 6808 charCode = 13; 6809 } // Some non-printable keys are reported in `charCode`/`keyCode`, discard them. 6810 // Must not discard the (non-)printable Enter-key. 6811 6812 6813 if (charCode >= 32 || charCode === 13) { 6814 return charCode; 6815 } 6816 6817 return 0; 6818 } 6819 6820 function functionThatReturnsTrue() { 6821 return true; 6822 } 6823 6824 function functionThatReturnsFalse() { 6825 return false; 6826 } // This is intentionally a factory so that we have different returned constructors. 6827 // If we had a single constructor, it would be megamorphic and engines would deopt. 6828 6829 6830 function createSyntheticEvent(Interface) { 6831 /** 6832 * Synthetic events are dispatched by event plugins, typically in response to a 6833 * top-level event delegation handler. 6834 * 6835 * These systems should generally use pooling to reduce the frequency of garbage 6836 * collection. The system should check `isPersistent` to determine whether the 6837 * event should be released into the pool after being dispatched. Users that 6838 * need a persisted event should invoke `persist`. 6839 * 6840 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by 6841 * normalizing browser quirks. Subclasses do not necessarily have to implement a 6842 * DOM interface; custom application-specific events can also subclass this. 6843 */ 6844 function SyntheticBaseEvent(reactName, reactEventType, targetInst, nativeEvent, nativeEventTarget) { 6845 this._reactName = reactName; 6846 this._targetInst = targetInst; 6847 this.type = reactEventType; 6848 this.nativeEvent = nativeEvent; 6849 this.target = nativeEventTarget; 6850 this.currentTarget = null; 6851 6852 for (var _propName in Interface) { 6853 if (!Interface.hasOwnProperty(_propName)) { 6854 continue; 6855 } 6856 6857 var normalize = Interface[_propName]; 6858 6859 if (normalize) { 6860 this[_propName] = normalize(nativeEvent); 6861 } else { 6862 this[_propName] = nativeEvent[_propName]; 6863 } 6864 } 6865 6866 var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false; 6867 6868 if (defaultPrevented) { 6869 this.isDefaultPrevented = functionThatReturnsTrue; 6870 } else { 6871 this.isDefaultPrevented = functionThatReturnsFalse; 6872 } 6873 6874 this.isPropagationStopped = functionThatReturnsFalse; 6875 return this; 6876 } 6877 6878 assign(SyntheticBaseEvent.prototype, { 6879 preventDefault: function () { 6880 this.defaultPrevented = true; 6881 var event = this.nativeEvent; 6882 6883 if (!event) { 6884 return; 6885 } 6886 6887 if (event.preventDefault) { 6888 event.preventDefault(); // $FlowFixMe - flow is not aware of `unknown` in IE 6889 } else if (typeof event.returnValue !== 'unknown') { 6890 event.returnValue = false; 6891 } 6892 6893 this.isDefaultPrevented = functionThatReturnsTrue; 6894 }, 6895 stopPropagation: function () { 6896 var event = this.nativeEvent; 6897 6898 if (!event) { 6899 return; 6900 } 6901 6902 if (event.stopPropagation) { 6903 event.stopPropagation(); // $FlowFixMe - flow is not aware of `unknown` in IE 6904 } else if (typeof event.cancelBubble !== 'unknown') { 6905 // The ChangeEventPlugin registers a "propertychange" event for 6906 // IE. This event does not support bubbling or cancelling, and 6907 // any references to cancelBubble throw "Member not found". A 6908 // typeof check of "unknown" circumvents this issue (and is also 6909 // IE specific). 6910 event.cancelBubble = true; 6911 } 6912 6913 this.isPropagationStopped = functionThatReturnsTrue; 6914 }, 6915 6916 /** 6917 * We release all dispatched `SyntheticEvent`s after each event loop, adding 6918 * them back into the pool. This allows a way to hold onto a reference that 6919 * won't be added back into the pool. 6920 */ 6921 persist: function () {// Modern event system doesn't use pooling. 6922 }, 6923 6924 /** 6925 * Checks if this event should be released back into the pool. 6926 * 6927 * @return {boolean} True if this should not be released, false otherwise. 6928 */ 6929 isPersistent: functionThatReturnsTrue 6930 }); 6931 return SyntheticBaseEvent; 6932 } 6933 /** 6934 * @interface Event 6935 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 6936 */ 6937 6938 6939 var EventInterface = { 6940 eventPhase: 0, 6941 bubbles: 0, 6942 cancelable: 0, 6943 timeStamp: function (event) { 6944 return event.timeStamp || Date.now(); 6945 }, 6946 defaultPrevented: 0, 6947 isTrusted: 0 6948 }; 6949 var SyntheticEvent = createSyntheticEvent(EventInterface); 6950 6951 var UIEventInterface = assign({}, EventInterface, { 6952 view: 0, 6953 detail: 0 6954 }); 6955 6956 var SyntheticUIEvent = createSyntheticEvent(UIEventInterface); 6957 var lastMovementX; 6958 var lastMovementY; 6959 var lastMouseEvent; 6960 6961 function updateMouseMovementPolyfillState(event) { 6962 if (event !== lastMouseEvent) { 6963 if (lastMouseEvent && event.type === 'mousemove') { 6964 lastMovementX = event.screenX - lastMouseEvent.screenX; 6965 lastMovementY = event.screenY - lastMouseEvent.screenY; 6966 } else { 6967 lastMovementX = 0; 6968 lastMovementY = 0; 6969 } 6970 6971 lastMouseEvent = event; 6972 } 6973 } 6974 /** 6975 * @interface MouseEvent 6976 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 6977 */ 6978 6979 6980 var MouseEventInterface = assign({}, UIEventInterface, { 6981 screenX: 0, 6982 screenY: 0, 6983 clientX: 0, 6984 clientY: 0, 6985 pageX: 0, 6986 pageY: 0, 6987 ctrlKey: 0, 6988 shiftKey: 0, 6989 altKey: 0, 6990 metaKey: 0, 6991 getModifierState: getEventModifierState, 6992 button: 0, 6993 buttons: 0, 6994 relatedTarget: function (event) { 6995 if (event.relatedTarget === undefined) return event.fromElement === event.srcElement ? event.toElement : event.fromElement; 6996 return event.relatedTarget; 6997 }, 6998 movementX: function (event) { 6999 if ('movementX' in event) { 7000 return event.movementX; 7001 } 7002 7003 updateMouseMovementPolyfillState(event); 7004 return lastMovementX; 7005 }, 7006 movementY: function (event) { 7007 if ('movementY' in event) { 7008 return event.movementY; 7009 } // Don't need to call updateMouseMovementPolyfillState() here 7010 // because it's guaranteed to have already run when movementX 7011 // was copied. 7012 7013 7014 return lastMovementY; 7015 } 7016 }); 7017 7018 var SyntheticMouseEvent = createSyntheticEvent(MouseEventInterface); 7019 /** 7020 * @interface DragEvent 7021 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7022 */ 7023 7024 var DragEventInterface = assign({}, MouseEventInterface, { 7025 dataTransfer: 0 7026 }); 7027 7028 var SyntheticDragEvent = createSyntheticEvent(DragEventInterface); 7029 /** 7030 * @interface FocusEvent 7031 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7032 */ 7033 7034 var FocusEventInterface = assign({}, UIEventInterface, { 7035 relatedTarget: 0 7036 }); 7037 7038 var SyntheticFocusEvent = createSyntheticEvent(FocusEventInterface); 7039 /** 7040 * @interface Event 7041 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface 7042 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent 7043 */ 7044 7045 var AnimationEventInterface = assign({}, EventInterface, { 7046 animationName: 0, 7047 elapsedTime: 0, 7048 pseudoElement: 0 7049 }); 7050 7051 var SyntheticAnimationEvent = createSyntheticEvent(AnimationEventInterface); 7052 /** 7053 * @interface Event 7054 * @see http://www.w3.org/TR/clipboard-apis/ 7055 */ 7056 7057 var ClipboardEventInterface = assign({}, EventInterface, { 7058 clipboardData: function (event) { 7059 return 'clipboardData' in event ? event.clipboardData : window.clipboardData; 7060 } 7061 }); 7062 7063 var SyntheticClipboardEvent = createSyntheticEvent(ClipboardEventInterface); 7064 /** 7065 * @interface Event 7066 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents 7067 */ 7068 7069 var CompositionEventInterface = assign({}, EventInterface, { 7070 data: 0 7071 }); 7072 7073 var SyntheticCompositionEvent = createSyntheticEvent(CompositionEventInterface); 7074 /** 7075 * @interface Event 7076 * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105 7077 * /#events-inputevents 7078 */ 7079 // Happens to share the same list for now. 7080 7081 var SyntheticInputEvent = SyntheticCompositionEvent; 7082 /** 7083 * Normalization of deprecated HTML5 `key` values 7084 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 7085 */ 7086 7087 var normalizeKey = { 7088 Esc: 'Escape', 7089 Spacebar: ' ', 7090 Left: 'ArrowLeft', 7091 Up: 'ArrowUp', 7092 Right: 'ArrowRight', 7093 Down: 'ArrowDown', 7094 Del: 'Delete', 7095 Win: 'OS', 7096 Menu: 'ContextMenu', 7097 Apps: 'ContextMenu', 7098 Scroll: 'ScrollLock', 7099 MozPrintableKey: 'Unidentified' 7100 }; 7101 /** 7102 * Translation from legacy `keyCode` to HTML5 `key` 7103 * Only special keys supported, all others depend on keyboard layout or browser 7104 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 7105 */ 7106 7107 var translateToKey = { 7108 '8': 'Backspace', 7109 '9': 'Tab', 7110 '12': 'Clear', 7111 '13': 'Enter', 7112 '16': 'Shift', 7113 '17': 'Control', 7114 '18': 'Alt', 7115 '19': 'Pause', 7116 '20': 'CapsLock', 7117 '27': 'Escape', 7118 '32': ' ', 7119 '33': 'PageUp', 7120 '34': 'PageDown', 7121 '35': 'End', 7122 '36': 'Home', 7123 '37': 'ArrowLeft', 7124 '38': 'ArrowUp', 7125 '39': 'ArrowRight', 7126 '40': 'ArrowDown', 7127 '45': 'Insert', 7128 '46': 'Delete', 7129 '112': 'F1', 7130 '113': 'F2', 7131 '114': 'F3', 7132 '115': 'F4', 7133 '116': 'F5', 7134 '117': 'F6', 7135 '118': 'F7', 7136 '119': 'F8', 7137 '120': 'F9', 7138 '121': 'F10', 7139 '122': 'F11', 7140 '123': 'F12', 7141 '144': 'NumLock', 7142 '145': 'ScrollLock', 7143 '224': 'Meta' 7144 }; 7145 /** 7146 * @param {object} nativeEvent Native browser event. 7147 * @return {string} Normalized `key` property. 7148 */ 7149 7150 function getEventKey(nativeEvent) { 7151 if (nativeEvent.key) { 7152 // Normalize inconsistent values reported by browsers due to 7153 // implementations of a working draft specification. 7154 // FireFox implements `key` but returns `MozPrintableKey` for all 7155 // printable characters (normalized to `Unidentified`), ignore it. 7156 var key = normalizeKey[nativeEvent.key] || nativeEvent.key; 7157 7158 if (key !== 'Unidentified') { 7159 return key; 7160 } 7161 } // Browser does not implement `key`, polyfill as much of it as we can. 7162 7163 7164 if (nativeEvent.type === 'keypress') { 7165 var charCode = getEventCharCode(nativeEvent); // The enter-key is technically both printable and non-printable and can 7166 // thus be captured by `keypress`, no other non-printable key should. 7167 7168 return charCode === 13 ? 'Enter' : String.fromCharCode(charCode); 7169 } 7170 7171 if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') { 7172 // While user keyboard layout determines the actual meaning of each 7173 // `keyCode` value, almost all function keys have a universal value. 7174 return translateToKey[nativeEvent.keyCode] || 'Unidentified'; 7175 } 7176 7177 return ''; 7178 } 7179 /** 7180 * Translation from modifier key to the associated property in the event. 7181 * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers 7182 */ 7183 7184 7185 var modifierKeyToProp = { 7186 Alt: 'altKey', 7187 Control: 'ctrlKey', 7188 Meta: 'metaKey', 7189 Shift: 'shiftKey' 7190 }; // Older browsers (Safari <= 10, iOS Safari <= 10.2) do not support 7191 // getModifierState. If getModifierState is not supported, we map it to a set of 7192 // modifier keys exposed by the event. In this case, Lock-keys are not supported. 7193 7194 function modifierStateGetter(keyArg) { 7195 var syntheticEvent = this; 7196 var nativeEvent = syntheticEvent.nativeEvent; 7197 7198 if (nativeEvent.getModifierState) { 7199 return nativeEvent.getModifierState(keyArg); 7200 } 7201 7202 var keyProp = modifierKeyToProp[keyArg]; 7203 return keyProp ? !!nativeEvent[keyProp] : false; 7204 } 7205 7206 function getEventModifierState(nativeEvent) { 7207 return modifierStateGetter; 7208 } 7209 /** 7210 * @interface KeyboardEvent 7211 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7212 */ 7213 7214 7215 var KeyboardEventInterface = assign({}, UIEventInterface, { 7216 key: getEventKey, 7217 code: 0, 7218 location: 0, 7219 ctrlKey: 0, 7220 shiftKey: 0, 7221 altKey: 0, 7222 metaKey: 0, 7223 repeat: 0, 7224 locale: 0, 7225 getModifierState: getEventModifierState, 7226 // Legacy Interface 7227 charCode: function (event) { 7228 // `charCode` is the result of a KeyPress event and represents the value of 7229 // the actual printable character. 7230 // KeyPress is deprecated, but its replacement is not yet final and not 7231 // implemented in any major browser. Only KeyPress has charCode. 7232 if (event.type === 'keypress') { 7233 return getEventCharCode(event); 7234 } 7235 7236 return 0; 7237 }, 7238 keyCode: function (event) { 7239 // `keyCode` is the result of a KeyDown/Up event and represents the value of 7240 // physical keyboard key. 7241 // The actual meaning of the value depends on the users' keyboard layout 7242 // which cannot be detected. Assuming that it is a US keyboard layout 7243 // provides a surprisingly accurate mapping for US and European users. 7244 // Due to this, it is left to the user to implement at this time. 7245 if (event.type === 'keydown' || event.type === 'keyup') { 7246 return event.keyCode; 7247 } 7248 7249 return 0; 7250 }, 7251 which: function (event) { 7252 // `which` is an alias for either `keyCode` or `charCode` depending on the 7253 // type of the event. 7254 if (event.type === 'keypress') { 7255 return getEventCharCode(event); 7256 } 7257 7258 if (event.type === 'keydown' || event.type === 'keyup') { 7259 return event.keyCode; 7260 } 7261 7262 return 0; 7263 } 7264 }); 7265 7266 var SyntheticKeyboardEvent = createSyntheticEvent(KeyboardEventInterface); 7267 /** 7268 * @interface PointerEvent 7269 * @see http://www.w3.org/TR/pointerevents/ 7270 */ 7271 7272 var PointerEventInterface = assign({}, MouseEventInterface, { 7273 pointerId: 0, 7274 width: 0, 7275 height: 0, 7276 pressure: 0, 7277 tangentialPressure: 0, 7278 tiltX: 0, 7279 tiltY: 0, 7280 twist: 0, 7281 pointerType: 0, 7282 isPrimary: 0 7283 }); 7284 7285 var SyntheticPointerEvent = createSyntheticEvent(PointerEventInterface); 7286 /** 7287 * @interface TouchEvent 7288 * @see http://www.w3.org/TR/touch-events/ 7289 */ 7290 7291 var TouchEventInterface = assign({}, UIEventInterface, { 7292 touches: 0, 7293 targetTouches: 0, 7294 changedTouches: 0, 7295 altKey: 0, 7296 metaKey: 0, 7297 ctrlKey: 0, 7298 shiftKey: 0, 7299 getModifierState: getEventModifierState 7300 }); 7301 7302 var SyntheticTouchEvent = createSyntheticEvent(TouchEventInterface); 7303 /** 7304 * @interface Event 7305 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events- 7306 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent 7307 */ 7308 7309 var TransitionEventInterface = assign({}, EventInterface, { 7310 propertyName: 0, 7311 elapsedTime: 0, 7312 pseudoElement: 0 7313 }); 7314 7315 var SyntheticTransitionEvent = createSyntheticEvent(TransitionEventInterface); 7316 /** 7317 * @interface WheelEvent 7318 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7319 */ 7320 7321 var WheelEventInterface = assign({}, MouseEventInterface, { 7322 deltaX: function (event) { 7323 return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). 7324 'wheelDeltaX' in event ? -event.wheelDeltaX : 0; 7325 }, 7326 deltaY: function (event) { 7327 return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). 7328 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). 7329 'wheelDelta' in event ? -event.wheelDelta : 0; 7330 }, 7331 deltaZ: 0, 7332 // Browsers without "deltaMode" is reporting in raw wheel delta where one 7333 // notch on the scroll is always +/- 120, roughly equivalent to pixels. 7334 // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or 7335 // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size. 7336 deltaMode: 0 7337 }); 7338 7339 var SyntheticWheelEvent = createSyntheticEvent(WheelEventInterface); 7340 7341 var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space 7342 7343 var START_KEYCODE = 229; 7344 var canUseCompositionEvent = canUseDOM && 'CompositionEvent' in window; 7345 var documentMode = null; 7346 7347 if (canUseDOM && 'documentMode' in document) { 7348 documentMode = document.documentMode; 7349 } // Webkit offers a very useful `textInput` event that can be used to 7350 // directly represent `beforeInput`. The IE `textinput` event is not as 7351 // useful, so we don't use it. 7352 7353 7354 var canUseTextInputEvent = canUseDOM && 'TextEvent' in window && !documentMode; // In IE9+, we have access to composition events, but the data supplied 7355 // by the native compositionend event may be incorrect. Japanese ideographic 7356 // spaces, for instance (\u3000) are not recorded correctly. 7357 7358 var useFallbackCompositionData = canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11); 7359 var SPACEBAR_CODE = 32; 7360 var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE); 7361 7362 function registerEvents() { 7363 registerTwoPhaseEvent('onBeforeInput', ['compositionend', 'keypress', 'textInput', 'paste']); 7364 registerTwoPhaseEvent('onCompositionEnd', ['compositionend', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7365 registerTwoPhaseEvent('onCompositionStart', ['compositionstart', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7366 registerTwoPhaseEvent('onCompositionUpdate', ['compositionupdate', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7367 } // Track whether we've ever handled a keypress on the space key. 7368 7369 7370 var hasSpaceKeypress = false; 7371 /** 7372 * Return whether a native keypress event is assumed to be a command. 7373 * This is required because Firefox fires `keypress` events for key commands 7374 * (cut, copy, select-all, etc.) even though no character is inserted. 7375 */ 7376 7377 function isKeypressCommand(nativeEvent) { 7378 return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && // ctrlKey && altKey is equivalent to AltGr, and is not a command. 7379 !(nativeEvent.ctrlKey && nativeEvent.altKey); 7380 } 7381 /** 7382 * Translate native top level events into event types. 7383 */ 7384 7385 7386 function getCompositionEventType(domEventName) { 7387 switch (domEventName) { 7388 case 'compositionstart': 7389 return 'onCompositionStart'; 7390 7391 case 'compositionend': 7392 return 'onCompositionEnd'; 7393 7394 case 'compositionupdate': 7395 return 'onCompositionUpdate'; 7396 } 7397 } 7398 /** 7399 * Does our fallback best-guess model think this event signifies that 7400 * composition has begun? 7401 */ 7402 7403 7404 function isFallbackCompositionStart(domEventName, nativeEvent) { 7405 return domEventName === 'keydown' && nativeEvent.keyCode === START_KEYCODE; 7406 } 7407 /** 7408 * Does our fallback mode think that this event is the end of composition? 7409 */ 7410 7411 7412 function isFallbackCompositionEnd(domEventName, nativeEvent) { 7413 switch (domEventName) { 7414 case 'keyup': 7415 // Command keys insert or clear IME input. 7416 return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; 7417 7418 case 'keydown': 7419 // Expect IME keyCode on each keydown. If we get any other 7420 // code we must have exited earlier. 7421 return nativeEvent.keyCode !== START_KEYCODE; 7422 7423 case 'keypress': 7424 case 'mousedown': 7425 case 'focusout': 7426 // Events are not possible without cancelling IME. 7427 return true; 7428 7429 default: 7430 return false; 7431 } 7432 } 7433 /** 7434 * Google Input Tools provides composition data via a CustomEvent, 7435 * with the `data` property populated in the `detail` object. If this 7436 * is available on the event object, use it. If not, this is a plain 7437 * composition event and we have nothing special to extract. 7438 * 7439 * @param {object} nativeEvent 7440 * @return {?string} 7441 */ 7442 7443 7444 function getDataFromCustomEvent(nativeEvent) { 7445 var detail = nativeEvent.detail; 7446 7447 if (typeof detail === 'object' && 'data' in detail) { 7448 return detail.data; 7449 } 7450 7451 return null; 7452 } 7453 /** 7454 * Check if a composition event was triggered by Korean IME. 7455 * Our fallback mode does not work well with IE's Korean IME, 7456 * so just use native composition events when Korean IME is used. 7457 * Although CompositionEvent.locale property is deprecated, 7458 * it is available in IE, where our fallback mode is enabled. 7459 * 7460 * @param {object} nativeEvent 7461 * @return {boolean} 7462 */ 7463 7464 7465 function isUsingKoreanIME(nativeEvent) { 7466 return nativeEvent.locale === 'ko'; 7467 } // Track the current IME composition status, if any. 7468 7469 7470 var isComposing = false; 7471 /** 7472 * @return {?object} A SyntheticCompositionEvent. 7473 */ 7474 7475 function extractCompositionEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget) { 7476 var eventType; 7477 var fallbackData; 7478 7479 if (canUseCompositionEvent) { 7480 eventType = getCompositionEventType(domEventName); 7481 } else if (!isComposing) { 7482 if (isFallbackCompositionStart(domEventName, nativeEvent)) { 7483 eventType = 'onCompositionStart'; 7484 } 7485 } else if (isFallbackCompositionEnd(domEventName, nativeEvent)) { 7486 eventType = 'onCompositionEnd'; 7487 } 7488 7489 if (!eventType) { 7490 return null; 7491 } 7492 7493 if (useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)) { 7494 // The current composition is stored statically and must not be 7495 // overwritten while composition continues. 7496 if (!isComposing && eventType === 'onCompositionStart') { 7497 isComposing = initialize(nativeEventTarget); 7498 } else if (eventType === 'onCompositionEnd') { 7499 if (isComposing) { 7500 fallbackData = getData(); 7501 } 7502 } 7503 } 7504 7505 var listeners = accumulateTwoPhaseListeners(targetInst, eventType); 7506 7507 if (listeners.length > 0) { 7508 var event = new SyntheticCompositionEvent(eventType, domEventName, null, nativeEvent, nativeEventTarget); 7509 dispatchQueue.push({ 7510 event: event, 7511 listeners: listeners 7512 }); 7513 7514 if (fallbackData) { 7515 // Inject data generated from fallback path into the synthetic event. 7516 // This matches the property of native CompositionEventInterface. 7517 event.data = fallbackData; 7518 } else { 7519 var customData = getDataFromCustomEvent(nativeEvent); 7520 7521 if (customData !== null) { 7522 event.data = customData; 7523 } 7524 } 7525 } 7526 } 7527 7528 function getNativeBeforeInputChars(domEventName, nativeEvent) { 7529 switch (domEventName) { 7530 case 'compositionend': 7531 return getDataFromCustomEvent(nativeEvent); 7532 7533 case 'keypress': 7534 /** 7535 * If native `textInput` events are available, our goal is to make 7536 * use of them. However, there is a special case: the spacebar key. 7537 * In Webkit, preventing default on a spacebar `textInput` event 7538 * cancels character insertion, but it *also* causes the browser 7539 * to fall back to its default spacebar behavior of scrolling the 7540 * page. 7541 * 7542 * Tracking at: 7543 * https://code.google.com/p/chromium/issues/detail?id=355103 7544 * 7545 * To avoid this issue, use the keypress event as if no `textInput` 7546 * event is available. 7547 */ 7548 var which = nativeEvent.which; 7549 7550 if (which !== SPACEBAR_CODE) { 7551 return null; 7552 } 7553 7554 hasSpaceKeypress = true; 7555 return SPACEBAR_CHAR; 7556 7557 case 'textInput': 7558 // Record the characters to be added to the DOM. 7559 var chars = nativeEvent.data; // If it's a spacebar character, assume that we have already handled 7560 // it at the keypress level and bail immediately. Android Chrome 7561 // doesn't give us keycodes, so we need to ignore it. 7562 7563 if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { 7564 return null; 7565 } 7566 7567 return chars; 7568 7569 default: 7570 // For other native event types, do nothing. 7571 return null; 7572 } 7573 } 7574 /** 7575 * For browsers that do not provide the `textInput` event, extract the 7576 * appropriate string to use for SyntheticInputEvent. 7577 */ 7578 7579 7580 function getFallbackBeforeInputChars(domEventName, nativeEvent) { 7581 // If we are currently composing (IME) and using a fallback to do so, 7582 // try to extract the composed characters from the fallback object. 7583 // If composition event is available, we extract a string only at 7584 // compositionevent, otherwise extract it at fallback events. 7585 if (isComposing) { 7586 if (domEventName === 'compositionend' || !canUseCompositionEvent && isFallbackCompositionEnd(domEventName, nativeEvent)) { 7587 var chars = getData(); 7588 reset(); 7589 isComposing = false; 7590 return chars; 7591 } 7592 7593 return null; 7594 } 7595 7596 switch (domEventName) { 7597 case 'paste': 7598 // If a paste event occurs after a keypress, throw out the input 7599 // chars. Paste events should not lead to BeforeInput events. 7600 return null; 7601 7602 case 'keypress': 7603 /** 7604 * As of v27, Firefox may fire keypress events even when no character 7605 * will be inserted. A few possibilities: 7606 * 7607 * - `which` is `0`. Arrow keys, Esc key, etc. 7608 * 7609 * - `which` is the pressed key code, but no char is available. 7610 * Ex: 'AltGr + d` in Polish. There is no modified character for 7611 * this key combination and no character is inserted into the 7612 * document, but FF fires the keypress for char code `100` anyway. 7613 * No `input` event will occur. 7614 * 7615 * - `which` is the pressed key code, but a command combination is 7616 * being used. Ex: `Cmd+C`. No character is inserted, and no 7617 * `input` event will occur. 7618 */ 7619 if (!isKeypressCommand(nativeEvent)) { 7620 // IE fires the `keypress` event when a user types an emoji via 7621 // Touch keyboard of Windows. In such a case, the `char` property 7622 // holds an emoji character like `\uD83D\uDE0A`. Because its length 7623 // is 2, the property `which` does not represent an emoji correctly. 7624 // In such a case, we directly return the `char` property instead of 7625 // using `which`. 7626 if (nativeEvent.char && nativeEvent.char.length > 1) { 7627 return nativeEvent.char; 7628 } else if (nativeEvent.which) { 7629 return String.fromCharCode(nativeEvent.which); 7630 } 7631 } 7632 7633 return null; 7634 7635 case 'compositionend': 7636 return useFallbackCompositionData && !isUsingKoreanIME(nativeEvent) ? null : nativeEvent.data; 7637 7638 default: 7639 return null; 7640 } 7641 } 7642 /** 7643 * Extract a SyntheticInputEvent for `beforeInput`, based on either native 7644 * `textInput` or fallback behavior. 7645 * 7646 * @return {?object} A SyntheticInputEvent. 7647 */ 7648 7649 7650 function extractBeforeInputEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget) { 7651 var chars; 7652 7653 if (canUseTextInputEvent) { 7654 chars = getNativeBeforeInputChars(domEventName, nativeEvent); 7655 } else { 7656 chars = getFallbackBeforeInputChars(domEventName, nativeEvent); 7657 } // If no characters are being inserted, no BeforeInput event should 7658 // be fired. 7659 7660 7661 if (!chars) { 7662 return null; 7663 } 7664 7665 var listeners = accumulateTwoPhaseListeners(targetInst, 'onBeforeInput'); 7666 7667 if (listeners.length > 0) { 7668 var event = new SyntheticInputEvent('onBeforeInput', 'beforeinput', null, nativeEvent, nativeEventTarget); 7669 dispatchQueue.push({ 7670 event: event, 7671 listeners: listeners 7672 }); 7673 event.data = chars; 7674 } 7675 } 7676 /** 7677 * Create an `onBeforeInput` event to match 7678 * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. 7679 * 7680 * This event plugin is based on the native `textInput` event 7681 * available in Chrome, Safari, Opera, and IE. This event fires after 7682 * `onKeyPress` and `onCompositionEnd`, but before `onInput`. 7683 * 7684 * `beforeInput` is spec'd but not implemented in any browsers, and 7685 * the `input` event does not provide any useful information about what has 7686 * actually been added, contrary to the spec. Thus, `textInput` is the best 7687 * available event to identify the characters that have actually been inserted 7688 * into the target node. 7689 * 7690 * This plugin is also responsible for emitting `composition` events, thus 7691 * allowing us to share composition fallback code for both `beforeInput` and 7692 * `composition` event types. 7693 */ 7694 7695 7696 function extractEvents(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 7697 extractCompositionEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 7698 extractBeforeInputEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 7699 } 7700 7701 /** 7702 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 7703 */ 7704 var supportedInputTypes = { 7705 color: true, 7706 date: true, 7707 datetime: true, 7708 'datetime-local': true, 7709 email: true, 7710 month: true, 7711 number: true, 7712 password: true, 7713 range: true, 7714 search: true, 7715 tel: true, 7716 text: true, 7717 time: true, 7718 url: true, 7719 week: true 7720 }; 7721 7722 function isTextInputElement(elem) { 7723 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); 7724 7725 if (nodeName === 'input') { 7726 return !!supportedInputTypes[elem.type]; 7727 } 7728 7729 if (nodeName === 'textarea') { 7730 return true; 7731 } 7732 7733 return false; 7734 } 7735 7736 /** 7737 * Checks if an event is supported in the current execution environment. 7738 * 7739 * NOTE: This will not work correctly for non-generic events such as `change`, 7740 * `reset`, `load`, `error`, and `select`. 7741 * 7742 * Borrows from Modernizr. 7743 * 7744 * @param {string} eventNameSuffix Event name, e.g. "click". 7745 * @return {boolean} True if the event is supported. 7746 * @internal 7747 * @license Modernizr 3.0.0pre (Custom Build) | MIT 7748 */ 7749 7750 function isEventSupported(eventNameSuffix) { 7751 if (!canUseDOM) { 7752 return false; 7753 } 7754 7755 var eventName = 'on' + eventNameSuffix; 7756 var isSupported = (eventName in document); 7757 7758 if (!isSupported) { 7759 var element = document.createElement('div'); 7760 element.setAttribute(eventName, 'return;'); 7761 isSupported = typeof element[eventName] === 'function'; 7762 } 7763 7764 return isSupported; 7765 } 7766 7767 function registerEvents$1() { 7768 registerTwoPhaseEvent('onChange', ['change', 'click', 'focusin', 'focusout', 'input', 'keydown', 'keyup', 'selectionchange']); 7769 } 7770 7771 function createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, target) { 7772 // Flag this event loop as needing state restore. 7773 enqueueStateRestore(target); 7774 var listeners = accumulateTwoPhaseListeners(inst, 'onChange'); 7775 7776 if (listeners.length > 0) { 7777 var event = new SyntheticEvent('onChange', 'change', null, nativeEvent, target); 7778 dispatchQueue.push({ 7779 event: event, 7780 listeners: listeners 7781 }); 7782 } 7783 } 7784 /** 7785 * For IE shims 7786 */ 7787 7788 7789 var activeElement = null; 7790 var activeElementInst = null; 7791 /** 7792 * SECTION: handle `change` event 7793 */ 7794 7795 function shouldUseChangeEvent(elem) { 7796 var nodeName = elem.nodeName && elem.nodeName.toLowerCase(); 7797 return nodeName === 'select' || nodeName === 'input' && elem.type === 'file'; 7798 } 7799 7800 function manualDispatchChangeEvent(nativeEvent) { 7801 var dispatchQueue = []; 7802 createAndAccumulateChangeEvent(dispatchQueue, activeElementInst, nativeEvent, getEventTarget(nativeEvent)); // If change and propertychange bubbled, we'd just bind to it like all the 7803 // other events and have it go through ReactBrowserEventEmitter. Since it 7804 // doesn't, we manually listen for the events and so we have to enqueue and 7805 // process the abstract event manually. 7806 // 7807 // Batching is necessary here in order to ensure that all event handlers run 7808 // before the next rerender (including event handlers attached to ancestor 7809 // elements instead of directly on the input). Without this, controlled 7810 // components don't work properly in conjunction with event bubbling because 7811 // the component is rerendered and the value reverted before all the event 7812 // handlers can run. See https://github.com/facebook/react/issues/708. 7813 7814 batchedUpdates(runEventInBatch, dispatchQueue); 7815 } 7816 7817 function runEventInBatch(dispatchQueue) { 7818 processDispatchQueue(dispatchQueue, 0); 7819 } 7820 7821 function getInstIfValueChanged(targetInst) { 7822 var targetNode = getNodeFromInstance(targetInst); 7823 7824 if (updateValueIfChanged(targetNode)) { 7825 return targetInst; 7826 } 7827 } 7828 7829 function getTargetInstForChangeEvent(domEventName, targetInst) { 7830 if (domEventName === 'change') { 7831 return targetInst; 7832 } 7833 } 7834 /** 7835 * SECTION: handle `input` event 7836 */ 7837 7838 7839 var isInputEventSupported = false; 7840 7841 if (canUseDOM) { 7842 // IE9 claims to support the input event but fails to trigger it when 7843 // deleting text, so we ignore its input events. 7844 isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9); 7845 } 7846 /** 7847 * (For IE <=9) Starts tracking propertychange events on the passed-in element 7848 * and override the value property so that we can distinguish user events from 7849 * value changes in JS. 7850 */ 7851 7852 7853 function startWatchingForValueChange(target, targetInst) { 7854 activeElement = target; 7855 activeElementInst = targetInst; 7856 activeElement.attachEvent('onpropertychange', handlePropertyChange); 7857 } 7858 /** 7859 * (For IE <=9) Removes the event listeners from the currently-tracked element, 7860 * if any exists. 7861 */ 7862 7863 7864 function stopWatchingForValueChange() { 7865 if (!activeElement) { 7866 return; 7867 } 7868 7869 activeElement.detachEvent('onpropertychange', handlePropertyChange); 7870 activeElement = null; 7871 activeElementInst = null; 7872 } 7873 /** 7874 * (For IE <=9) Handles a propertychange event, sending a `change` event if 7875 * the value of the active element has changed. 7876 */ 7877 7878 7879 function handlePropertyChange(nativeEvent) { 7880 if (nativeEvent.propertyName !== 'value') { 7881 return; 7882 } 7883 7884 if (getInstIfValueChanged(activeElementInst)) { 7885 manualDispatchChangeEvent(nativeEvent); 7886 } 7887 } 7888 7889 function handleEventsForInputEventPolyfill(domEventName, target, targetInst) { 7890 if (domEventName === 'focusin') { 7891 // In IE9, propertychange fires for most input events but is buggy and 7892 // doesn't fire when text is deleted, but conveniently, selectionchange 7893 // appears to fire in all of the remaining cases so we catch those and 7894 // forward the event if the value has changed 7895 // In either case, we don't want to call the event handler if the value 7896 // is changed from JS so we redefine a setter for `.value` that updates 7897 // our activeElementValue variable, allowing us to ignore those changes 7898 // 7899 // stopWatching() should be a noop here but we call it just in case we 7900 // missed a blur event somehow. 7901 stopWatchingForValueChange(); 7902 startWatchingForValueChange(target, targetInst); 7903 } else if (domEventName === 'focusout') { 7904 stopWatchingForValueChange(); 7905 } 7906 } // For IE8 and IE9. 7907 7908 7909 function getTargetInstForInputEventPolyfill(domEventName, targetInst) { 7910 if (domEventName === 'selectionchange' || domEventName === 'keyup' || domEventName === 'keydown') { 7911 // On the selectionchange event, the target is just document which isn't 7912 // helpful for us so just check activeElement instead. 7913 // 7914 // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire 7915 // propertychange on the first input event after setting `value` from a 7916 // script and fires only keydown, keypress, keyup. Catching keyup usually 7917 // gets it and catching keydown lets us fire an event for the first 7918 // keystroke if user does a key repeat (it'll be a little delayed: right 7919 // before the second keystroke). Other input methods (e.g., paste) seem to 7920 // fire selectionchange normally. 7921 return getInstIfValueChanged(activeElementInst); 7922 } 7923 } 7924 /** 7925 * SECTION: handle `click` event 7926 */ 7927 7928 7929 function shouldUseClickEvent(elem) { 7930 // Use the `click` event to detect changes to checkbox and radio inputs. 7931 // This approach works across all browsers, whereas `change` does not fire 7932 // until `blur` in IE8. 7933 var nodeName = elem.nodeName; 7934 return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio'); 7935 } 7936 7937 function getTargetInstForClickEvent(domEventName, targetInst) { 7938 if (domEventName === 'click') { 7939 return getInstIfValueChanged(targetInst); 7940 } 7941 } 7942 7943 function getTargetInstForInputOrChangeEvent(domEventName, targetInst) { 7944 if (domEventName === 'input' || domEventName === 'change') { 7945 return getInstIfValueChanged(targetInst); 7946 } 7947 } 7948 7949 function handleControlledInputBlur(node) { 7950 var state = node._wrapperState; 7951 7952 if (!state || !state.controlled || node.type !== 'number') { 7953 return; 7954 } 7955 7956 { 7957 // If controlled, assign the value attribute to the current value on blur 7958 setDefaultValue(node, 'number', node.value); 7959 } 7960 } 7961 /** 7962 * This plugin creates an `onChange` event that normalizes change events 7963 * across form elements. This event fires at a time when it's possible to 7964 * change the element's value without seeing a flicker. 7965 * 7966 * Supported elements are: 7967 * - input (see `isTextInputElement`) 7968 * - textarea 7969 * - select 7970 */ 7971 7972 7973 function extractEvents$1(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 7974 var targetNode = targetInst ? getNodeFromInstance(targetInst) : window; 7975 var getTargetInstFunc, handleEventFunc; 7976 7977 if (shouldUseChangeEvent(targetNode)) { 7978 getTargetInstFunc = getTargetInstForChangeEvent; 7979 } else if (isTextInputElement(targetNode)) { 7980 if (isInputEventSupported) { 7981 getTargetInstFunc = getTargetInstForInputOrChangeEvent; 7982 } else { 7983 getTargetInstFunc = getTargetInstForInputEventPolyfill; 7984 handleEventFunc = handleEventsForInputEventPolyfill; 7985 } 7986 } else if (shouldUseClickEvent(targetNode)) { 7987 getTargetInstFunc = getTargetInstForClickEvent; 7988 } 7989 7990 if (getTargetInstFunc) { 7991 var inst = getTargetInstFunc(domEventName, targetInst); 7992 7993 if (inst) { 7994 createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, nativeEventTarget); 7995 return; 7996 } 7997 } 7998 7999 if (handleEventFunc) { 8000 handleEventFunc(domEventName, targetNode, targetInst); 8001 } // When blurring, set the value attribute for number inputs 8002 8003 8004 if (domEventName === 'focusout') { 8005 handleControlledInputBlur(targetNode); 8006 } 8007 } 8008 8009 function registerEvents$2() { 8010 registerDirectEvent('onMouseEnter', ['mouseout', 'mouseover']); 8011 registerDirectEvent('onMouseLeave', ['mouseout', 'mouseover']); 8012 registerDirectEvent('onPointerEnter', ['pointerout', 'pointerover']); 8013 registerDirectEvent('onPointerLeave', ['pointerout', 'pointerover']); 8014 } 8015 /** 8016 * For almost every interaction we care about, there will be both a top-level 8017 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that 8018 * we do not extract duplicate events. However, moving the mouse into the 8019 * browser from outside will not fire a `mouseout` event. In this case, we use 8020 * the `mouseover` top-level event. 8021 */ 8022 8023 8024 function extractEvents$2(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8025 var isOverEvent = domEventName === 'mouseover' || domEventName === 'pointerover'; 8026 var isOutEvent = domEventName === 'mouseout' || domEventName === 'pointerout'; 8027 8028 if (isOverEvent && !isReplayingEvent(nativeEvent)) { 8029 // If this is an over event with a target, we might have already dispatched 8030 // the event in the out event of the other target. If this is replayed, 8031 // then it's because we couldn't dispatch against this target previously 8032 // so we have to do it now instead. 8033 var related = nativeEvent.relatedTarget || nativeEvent.fromElement; 8034 8035 if (related) { 8036 // If the related node is managed by React, we can assume that we have 8037 // already dispatched the corresponding events during its mouseout. 8038 if (getClosestInstanceFromNode(related) || isContainerMarkedAsRoot(related)) { 8039 return; 8040 } 8041 } 8042 } 8043 8044 if (!isOutEvent && !isOverEvent) { 8045 // Must not be a mouse or pointer in or out - ignoring. 8046 return; 8047 } 8048 8049 var win; // TODO: why is this nullable in the types but we read from it? 8050 8051 if (nativeEventTarget.window === nativeEventTarget) { 8052 // `nativeEventTarget` is probably a window object. 8053 win = nativeEventTarget; 8054 } else { 8055 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. 8056 var doc = nativeEventTarget.ownerDocument; 8057 8058 if (doc) { 8059 win = doc.defaultView || doc.parentWindow; 8060 } else { 8061 win = window; 8062 } 8063 } 8064 8065 var from; 8066 var to; 8067 8068 if (isOutEvent) { 8069 var _related = nativeEvent.relatedTarget || nativeEvent.toElement; 8070 8071 from = targetInst; 8072 to = _related ? getClosestInstanceFromNode(_related) : null; 8073 8074 if (to !== null) { 8075 var nearestMounted = getNearestMountedFiber(to); 8076 8077 if (to !== nearestMounted || to.tag !== HostComponent && to.tag !== HostText) { 8078 to = null; 8079 } 8080 } 8081 } else { 8082 // Moving to a node from outside the window. 8083 from = null; 8084 to = targetInst; 8085 } 8086 8087 if (from === to) { 8088 // Nothing pertains to our managed components. 8089 return; 8090 } 8091 8092 var SyntheticEventCtor = SyntheticMouseEvent; 8093 var leaveEventType = 'onMouseLeave'; 8094 var enterEventType = 'onMouseEnter'; 8095 var eventTypePrefix = 'mouse'; 8096 8097 if (domEventName === 'pointerout' || domEventName === 'pointerover') { 8098 SyntheticEventCtor = SyntheticPointerEvent; 8099 leaveEventType = 'onPointerLeave'; 8100 enterEventType = 'onPointerEnter'; 8101 eventTypePrefix = 'pointer'; 8102 } 8103 8104 var fromNode = from == null ? win : getNodeFromInstance(from); 8105 var toNode = to == null ? win : getNodeFromInstance(to); 8106 var leave = new SyntheticEventCtor(leaveEventType, eventTypePrefix + 'leave', from, nativeEvent, nativeEventTarget); 8107 leave.target = fromNode; 8108 leave.relatedTarget = toNode; 8109 var enter = null; // We should only process this nativeEvent if we are processing 8110 // the first ancestor. Next time, we will ignore the event. 8111 8112 var nativeTargetInst = getClosestInstanceFromNode(nativeEventTarget); 8113 8114 if (nativeTargetInst === targetInst) { 8115 var enterEvent = new SyntheticEventCtor(enterEventType, eventTypePrefix + 'enter', to, nativeEvent, nativeEventTarget); 8116 enterEvent.target = toNode; 8117 enterEvent.relatedTarget = fromNode; 8118 enter = enterEvent; 8119 } 8120 8121 accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leave, enter, from, to); 8122 } 8123 8124 /** 8125 * inlined Object.is polyfill to avoid requiring consumers ship their own 8126 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 8127 */ 8128 function is(x, y) { 8129 return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare 8130 ; 8131 } 8132 8133 var objectIs = typeof Object.is === 'function' ? Object.is : is; 8134 8135 /** 8136 * Performs equality by iterating through keys on an object and returning false 8137 * when any key has values which are not strictly equal between the arguments. 8138 * Returns true when the values of all keys are strictly equal. 8139 */ 8140 8141 function shallowEqual(objA, objB) { 8142 if (objectIs(objA, objB)) { 8143 return true; 8144 } 8145 8146 if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { 8147 return false; 8148 } 8149 8150 var keysA = Object.keys(objA); 8151 var keysB = Object.keys(objB); 8152 8153 if (keysA.length !== keysB.length) { 8154 return false; 8155 } // Test for A's keys different from B. 8156 8157 8158 for (var i = 0; i < keysA.length; i++) { 8159 var currentKey = keysA[i]; 8160 8161 if (!hasOwnProperty.call(objB, currentKey) || !objectIs(objA[currentKey], objB[currentKey])) { 8162 return false; 8163 } 8164 } 8165 8166 return true; 8167 } 8168 8169 /** 8170 * Given any node return the first leaf node without children. 8171 * 8172 * @param {DOMElement|DOMTextNode} node 8173 * @return {DOMElement|DOMTextNode} 8174 */ 8175 8176 function getLeafNode(node) { 8177 while (node && node.firstChild) { 8178 node = node.firstChild; 8179 } 8180 8181 return node; 8182 } 8183 /** 8184 * Get the next sibling within a container. This will walk up the 8185 * DOM if a node's siblings have been exhausted. 8186 * 8187 * @param {DOMElement|DOMTextNode} node 8188 * @return {?DOMElement|DOMTextNode} 8189 */ 8190 8191 8192 function getSiblingNode(node) { 8193 while (node) { 8194 if (node.nextSibling) { 8195 return node.nextSibling; 8196 } 8197 8198 node = node.parentNode; 8199 } 8200 } 8201 /** 8202 * Get object describing the nodes which contain characters at offset. 8203 * 8204 * @param {DOMElement|DOMTextNode} root 8205 * @param {number} offset 8206 * @return {?object} 8207 */ 8208 8209 8210 function getNodeForCharacterOffset(root, offset) { 8211 var node = getLeafNode(root); 8212 var nodeStart = 0; 8213 var nodeEnd = 0; 8214 8215 while (node) { 8216 if (node.nodeType === TEXT_NODE) { 8217 nodeEnd = nodeStart + node.textContent.length; 8218 8219 if (nodeStart <= offset && nodeEnd >= offset) { 8220 return { 8221 node: node, 8222 offset: offset - nodeStart 8223 }; 8224 } 8225 8226 nodeStart = nodeEnd; 8227 } 8228 8229 node = getLeafNode(getSiblingNode(node)); 8230 } 8231 } 8232 8233 /** 8234 * @param {DOMElement} outerNode 8235 * @return {?object} 8236 */ 8237 8238 function getOffsets(outerNode) { 8239 var ownerDocument = outerNode.ownerDocument; 8240 var win = ownerDocument && ownerDocument.defaultView || window; 8241 var selection = win.getSelection && win.getSelection(); 8242 8243 if (!selection || selection.rangeCount === 0) { 8244 return null; 8245 } 8246 8247 var anchorNode = selection.anchorNode, 8248 anchorOffset = selection.anchorOffset, 8249 focusNode = selection.focusNode, 8250 focusOffset = selection.focusOffset; // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the 8251 // up/down buttons on an <input type="number">. Anonymous divs do not seem to 8252 // expose properties, triggering a "Permission denied error" if any of its 8253 // properties are accessed. The only seemingly possible way to avoid erroring 8254 // is to access a property that typically works for non-anonymous divs and 8255 // catch any error that may otherwise arise. See 8256 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 8257 8258 try { 8259 /* eslint-disable no-unused-expressions */ 8260 anchorNode.nodeType; 8261 focusNode.nodeType; 8262 /* eslint-enable no-unused-expressions */ 8263 } catch (e) { 8264 return null; 8265 } 8266 8267 return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset); 8268 } 8269 /** 8270 * Returns {start, end} where `start` is the character/codepoint index of 8271 * (anchorNode, anchorOffset) within the textContent of `outerNode`, and 8272 * `end` is the index of (focusNode, focusOffset). 8273 * 8274 * Returns null if you pass in garbage input but we should probably just crash. 8275 * 8276 * Exported only for testing. 8277 */ 8278 8279 function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) { 8280 var length = 0; 8281 var start = -1; 8282 var end = -1; 8283 var indexWithinAnchor = 0; 8284 var indexWithinFocus = 0; 8285 var node = outerNode; 8286 var parentNode = null; 8287 8288 outer: while (true) { 8289 var next = null; 8290 8291 while (true) { 8292 if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) { 8293 start = length + anchorOffset; 8294 } 8295 8296 if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) { 8297 end = length + focusOffset; 8298 } 8299 8300 if (node.nodeType === TEXT_NODE) { 8301 length += node.nodeValue.length; 8302 } 8303 8304 if ((next = node.firstChild) === null) { 8305 break; 8306 } // Moving from `node` to its first child `next`. 8307 8308 8309 parentNode = node; 8310 node = next; 8311 } 8312 8313 while (true) { 8314 if (node === outerNode) { 8315 // If `outerNode` has children, this is always the second time visiting 8316 // it. If it has no children, this is still the first loop, and the only 8317 // valid selection is anchorNode and focusNode both equal to this node 8318 // and both offsets 0, in which case we will have handled above. 8319 break outer; 8320 } 8321 8322 if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) { 8323 start = length; 8324 } 8325 8326 if (parentNode === focusNode && ++indexWithinFocus === focusOffset) { 8327 end = length; 8328 } 8329 8330 if ((next = node.nextSibling) !== null) { 8331 break; 8332 } 8333 8334 node = parentNode; 8335 parentNode = node.parentNode; 8336 } // Moving from `node` to its next sibling `next`. 8337 8338 8339 node = next; 8340 } 8341 8342 if (start === -1 || end === -1) { 8343 // This should never happen. (Would happen if the anchor/focus nodes aren't 8344 // actually inside the passed-in node.) 8345 return null; 8346 } 8347 8348 return { 8349 start: start, 8350 end: end 8351 }; 8352 } 8353 /** 8354 * In modern non-IE browsers, we can support both forward and backward 8355 * selections. 8356 * 8357 * Note: IE10+ supports the Selection object, but it does not support 8358 * the `extend` method, which means that even in modern IE, it's not possible 8359 * to programmatically create a backward selection. Thus, for all IE 8360 * versions, we use the old IE API to create our selections. 8361 * 8362 * @param {DOMElement|DOMTextNode} node 8363 * @param {object} offsets 8364 */ 8365 8366 function setOffsets(node, offsets) { 8367 var doc = node.ownerDocument || document; 8368 var win = doc && doc.defaultView || window; // Edge fails with "Object expected" in some scenarios. 8369 // (For instance: TinyMCE editor used in a list component that supports pasting to add more, 8370 // fails when pasting 100+ items) 8371 8372 if (!win.getSelection) { 8373 return; 8374 } 8375 8376 var selection = win.getSelection(); 8377 var length = node.textContent.length; 8378 var start = Math.min(offsets.start, length); 8379 var end = offsets.end === undefined ? start : Math.min(offsets.end, length); // IE 11 uses modern selection, but doesn't support the extend method. 8380 // Flip backward selections, so we can set with a single range. 8381 8382 if (!selection.extend && start > end) { 8383 var temp = end; 8384 end = start; 8385 start = temp; 8386 } 8387 8388 var startMarker = getNodeForCharacterOffset(node, start); 8389 var endMarker = getNodeForCharacterOffset(node, end); 8390 8391 if (startMarker && endMarker) { 8392 if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) { 8393 return; 8394 } 8395 8396 var range = doc.createRange(); 8397 range.setStart(startMarker.node, startMarker.offset); 8398 selection.removeAllRanges(); 8399 8400 if (start > end) { 8401 selection.addRange(range); 8402 selection.extend(endMarker.node, endMarker.offset); 8403 } else { 8404 range.setEnd(endMarker.node, endMarker.offset); 8405 selection.addRange(range); 8406 } 8407 } 8408 } 8409 8410 function isTextNode(node) { 8411 return node && node.nodeType === TEXT_NODE; 8412 } 8413 8414 function containsNode(outerNode, innerNode) { 8415 if (!outerNode || !innerNode) { 8416 return false; 8417 } else if (outerNode === innerNode) { 8418 return true; 8419 } else if (isTextNode(outerNode)) { 8420 return false; 8421 } else if (isTextNode(innerNode)) { 8422 return containsNode(outerNode, innerNode.parentNode); 8423 } else if ('contains' in outerNode) { 8424 return outerNode.contains(innerNode); 8425 } else if (outerNode.compareDocumentPosition) { 8426 return !!(outerNode.compareDocumentPosition(innerNode) & 16); 8427 } else { 8428 return false; 8429 } 8430 } 8431 8432 function isInDocument(node) { 8433 return node && node.ownerDocument && containsNode(node.ownerDocument.documentElement, node); 8434 } 8435 8436 function isSameOriginFrame(iframe) { 8437 try { 8438 // Accessing the contentDocument of a HTMLIframeElement can cause the browser 8439 // to throw, e.g. if it has a cross-origin src attribute. 8440 // Safari will show an error in the console when the access results in "Blocked a frame with origin". e.g: 8441 // iframe.contentDocument.defaultView; 8442 // A safety way is to access one of the cross origin properties: Window or Location 8443 // Which might result in "SecurityError" DOM Exception and it is compatible to Safari. 8444 // https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl 8445 return typeof iframe.contentWindow.location.href === 'string'; 8446 } catch (err) { 8447 return false; 8448 } 8449 } 8450 8451 function getActiveElementDeep() { 8452 var win = window; 8453 var element = getActiveElement(); 8454 8455 while (element instanceof win.HTMLIFrameElement) { 8456 if (isSameOriginFrame(element)) { 8457 win = element.contentWindow; 8458 } else { 8459 return element; 8460 } 8461 8462 element = getActiveElement(win.document); 8463 } 8464 8465 return element; 8466 } 8467 /** 8468 * @ReactInputSelection: React input selection module. Based on Selection.js, 8469 * but modified to be suitable for react and has a couple of bug fixes (doesn't 8470 * assume buttons have range selections allowed). 8471 * Input selection module for React. 8472 */ 8473 8474 /** 8475 * @hasSelectionCapabilities: we get the element types that support selection 8476 * from https://html.spec.whatwg.org/#do-not-apply, looking at `selectionStart` 8477 * and `selectionEnd` rows. 8478 */ 8479 8480 8481 function hasSelectionCapabilities(elem) { 8482 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); 8483 return nodeName && (nodeName === 'input' && (elem.type === 'text' || elem.type === 'search' || elem.type === 'tel' || elem.type === 'url' || elem.type === 'password') || nodeName === 'textarea' || elem.contentEditable === 'true'); 8484 } 8485 function getSelectionInformation() { 8486 var focusedElem = getActiveElementDeep(); 8487 return { 8488 focusedElem: focusedElem, 8489 selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection(focusedElem) : null 8490 }; 8491 } 8492 /** 8493 * @restoreSelection: If any selection information was potentially lost, 8494 * restore it. This is useful when performing operations that could remove dom 8495 * nodes and place them back in, resulting in focus being lost. 8496 */ 8497 8498 function restoreSelection(priorSelectionInformation) { 8499 var curFocusedElem = getActiveElementDeep(); 8500 var priorFocusedElem = priorSelectionInformation.focusedElem; 8501 var priorSelectionRange = priorSelectionInformation.selectionRange; 8502 8503 if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) { 8504 if (priorSelectionRange !== null && hasSelectionCapabilities(priorFocusedElem)) { 8505 setSelection(priorFocusedElem, priorSelectionRange); 8506 } // Focusing a node can change the scroll position, which is undesirable 8507 8508 8509 var ancestors = []; 8510 var ancestor = priorFocusedElem; 8511 8512 while (ancestor = ancestor.parentNode) { 8513 if (ancestor.nodeType === ELEMENT_NODE) { 8514 ancestors.push({ 8515 element: ancestor, 8516 left: ancestor.scrollLeft, 8517 top: ancestor.scrollTop 8518 }); 8519 } 8520 } 8521 8522 if (typeof priorFocusedElem.focus === 'function') { 8523 priorFocusedElem.focus(); 8524 } 8525 8526 for (var i = 0; i < ancestors.length; i++) { 8527 var info = ancestors[i]; 8528 info.element.scrollLeft = info.left; 8529 info.element.scrollTop = info.top; 8530 } 8531 } 8532 } 8533 /** 8534 * @getSelection: Gets the selection bounds of a focused textarea, input or 8535 * contentEditable node. 8536 * -@input: Look up selection bounds of this input 8537 * -@return {start: selectionStart, end: selectionEnd} 8538 */ 8539 8540 function getSelection(input) { 8541 var selection; 8542 8543 if ('selectionStart' in input) { 8544 // Modern browser with input or textarea. 8545 selection = { 8546 start: input.selectionStart, 8547 end: input.selectionEnd 8548 }; 8549 } else { 8550 // Content editable or old IE textarea. 8551 selection = getOffsets(input); 8552 } 8553 8554 return selection || { 8555 start: 0, 8556 end: 0 8557 }; 8558 } 8559 /** 8560 * @setSelection: Sets the selection bounds of a textarea or input and focuses 8561 * the input. 8562 * -@input Set selection bounds of this input or textarea 8563 * -@offsets Object of same form that is returned from get* 8564 */ 8565 8566 function setSelection(input, offsets) { 8567 var start = offsets.start; 8568 var end = offsets.end; 8569 8570 if (end === undefined) { 8571 end = start; 8572 } 8573 8574 if ('selectionStart' in input) { 8575 input.selectionStart = start; 8576 input.selectionEnd = Math.min(end, input.value.length); 8577 } else { 8578 setOffsets(input, offsets); 8579 } 8580 } 8581 8582 var skipSelectionChangeEvent = canUseDOM && 'documentMode' in document && document.documentMode <= 11; 8583 8584 function registerEvents$3() { 8585 registerTwoPhaseEvent('onSelect', ['focusout', 'contextmenu', 'dragend', 'focusin', 'keydown', 'keyup', 'mousedown', 'mouseup', 'selectionchange']); 8586 } 8587 8588 var activeElement$1 = null; 8589 var activeElementInst$1 = null; 8590 var lastSelection = null; 8591 var mouseDown = false; 8592 /** 8593 * Get an object which is a unique representation of the current selection. 8594 * 8595 * The return value will not be consistent across nodes or browsers, but 8596 * two identical selections on the same node will return identical objects. 8597 */ 8598 8599 function getSelection$1(node) { 8600 if ('selectionStart' in node && hasSelectionCapabilities(node)) { 8601 return { 8602 start: node.selectionStart, 8603 end: node.selectionEnd 8604 }; 8605 } else { 8606 var win = node.ownerDocument && node.ownerDocument.defaultView || window; 8607 var selection = win.getSelection(); 8608 return { 8609 anchorNode: selection.anchorNode, 8610 anchorOffset: selection.anchorOffset, 8611 focusNode: selection.focusNode, 8612 focusOffset: selection.focusOffset 8613 }; 8614 } 8615 } 8616 /** 8617 * Get document associated with the event target. 8618 */ 8619 8620 8621 function getEventTargetDocument(eventTarget) { 8622 return eventTarget.window === eventTarget ? eventTarget.document : eventTarget.nodeType === DOCUMENT_NODE ? eventTarget : eventTarget.ownerDocument; 8623 } 8624 /** 8625 * Poll selection to see whether it's changed. 8626 * 8627 * @param {object} nativeEvent 8628 * @param {object} nativeEventTarget 8629 * @return {?SyntheticEvent} 8630 */ 8631 8632 8633 function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) { 8634 // Ensure we have the right element, and that the user is not dragging a 8635 // selection (this matches native `select` event behavior). In HTML5, select 8636 // fires only on input and textarea thus if there's no focused element we 8637 // won't dispatch. 8638 var doc = getEventTargetDocument(nativeEventTarget); 8639 8640 if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement(doc)) { 8641 return; 8642 } // Only fire when selection has actually changed. 8643 8644 8645 var currentSelection = getSelection$1(activeElement$1); 8646 8647 if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) { 8648 lastSelection = currentSelection; 8649 var listeners = accumulateTwoPhaseListeners(activeElementInst$1, 'onSelect'); 8650 8651 if (listeners.length > 0) { 8652 var event = new SyntheticEvent('onSelect', 'select', null, nativeEvent, nativeEventTarget); 8653 dispatchQueue.push({ 8654 event: event, 8655 listeners: listeners 8656 }); 8657 event.target = activeElement$1; 8658 } 8659 } 8660 } 8661 /** 8662 * This plugin creates an `onSelect` event that normalizes select events 8663 * across form elements. 8664 * 8665 * Supported elements are: 8666 * - input (see `isTextInputElement`) 8667 * - textarea 8668 * - contentEditable 8669 * 8670 * This differs from native browser implementations in the following ways: 8671 * - Fires on contentEditable fields as well as inputs. 8672 * - Fires for collapsed selection. 8673 * - Fires after user input. 8674 */ 8675 8676 8677 function extractEvents$3(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8678 var targetNode = targetInst ? getNodeFromInstance(targetInst) : window; 8679 8680 switch (domEventName) { 8681 // Track the input node that has focus. 8682 case 'focusin': 8683 if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') { 8684 activeElement$1 = targetNode; 8685 activeElementInst$1 = targetInst; 8686 lastSelection = null; 8687 } 8688 8689 break; 8690 8691 case 'focusout': 8692 activeElement$1 = null; 8693 activeElementInst$1 = null; 8694 lastSelection = null; 8695 break; 8696 // Don't fire the event while the user is dragging. This matches the 8697 // semantics of the native select event. 8698 8699 case 'mousedown': 8700 mouseDown = true; 8701 break; 8702 8703 case 'contextmenu': 8704 case 'mouseup': 8705 case 'dragend': 8706 mouseDown = false; 8707 constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget); 8708 break; 8709 // Chrome and IE fire non-standard event when selection is changed (and 8710 // sometimes when it hasn't). IE's event fires out of order with respect 8711 // to key and input events on deletion, so we discard it. 8712 // 8713 // Firefox doesn't support selectionchange, so check selection status 8714 // after each key entry. The selection changes after keydown and before 8715 // keyup, but we check on keydown as well in the case of holding down a 8716 // key, when multiple keydown events are fired but only one keyup is. 8717 // This is also our approach for IE handling, for the reason above. 8718 8719 case 'selectionchange': 8720 if (skipSelectionChangeEvent) { 8721 break; 8722 } 8723 8724 // falls through 8725 8726 case 'keydown': 8727 case 'keyup': 8728 constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget); 8729 } 8730 } 8731 8732 /** 8733 * Generate a mapping of standard vendor prefixes using the defined style property and event name. 8734 * 8735 * @param {string} styleProp 8736 * @param {string} eventName 8737 * @returns {object} 8738 */ 8739 8740 function makePrefixMap(styleProp, eventName) { 8741 var prefixes = {}; 8742 prefixes[styleProp.toLowerCase()] = eventName.toLowerCase(); 8743 prefixes['Webkit' + styleProp] = 'webkit' + eventName; 8744 prefixes['Moz' + styleProp] = 'moz' + eventName; 8745 return prefixes; 8746 } 8747 /** 8748 * A list of event names to a configurable list of vendor prefixes. 8749 */ 8750 8751 8752 var vendorPrefixes = { 8753 animationend: makePrefixMap('Animation', 'AnimationEnd'), 8754 animationiteration: makePrefixMap('Animation', 'AnimationIteration'), 8755 animationstart: makePrefixMap('Animation', 'AnimationStart'), 8756 transitionend: makePrefixMap('Transition', 'TransitionEnd') 8757 }; 8758 /** 8759 * Event names that have already been detected and prefixed (if applicable). 8760 */ 8761 8762 var prefixedEventNames = {}; 8763 /** 8764 * Element to check for prefixes on. 8765 */ 8766 8767 var style = {}; 8768 /** 8769 * Bootstrap if a DOM exists. 8770 */ 8771 8772 if (canUseDOM) { 8773 style = document.createElement('div').style; // On some platforms, in particular some releases of Android 4.x, 8774 // the un-prefixed "animation" and "transition" properties are defined on the 8775 // style object but the events that fire will still be prefixed, so we need 8776 // to check if the un-prefixed events are usable, and if not remove them from the map. 8777 8778 if (!('AnimationEvent' in window)) { 8779 delete vendorPrefixes.animationend.animation; 8780 delete vendorPrefixes.animationiteration.animation; 8781 delete vendorPrefixes.animationstart.animation; 8782 } // Same as above 8783 8784 8785 if (!('TransitionEvent' in window)) { 8786 delete vendorPrefixes.transitionend.transition; 8787 } 8788 } 8789 /** 8790 * Attempts to determine the correct vendor prefixed event name. 8791 * 8792 * @param {string} eventName 8793 * @returns {string} 8794 */ 8795 8796 8797 function getVendorPrefixedEventName(eventName) { 8798 if (prefixedEventNames[eventName]) { 8799 return prefixedEventNames[eventName]; 8800 } else if (!vendorPrefixes[eventName]) { 8801 return eventName; 8802 } 8803 8804 var prefixMap = vendorPrefixes[eventName]; 8805 8806 for (var styleProp in prefixMap) { 8807 if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) { 8808 return prefixedEventNames[eventName] = prefixMap[styleProp]; 8809 } 8810 } 8811 8812 return eventName; 8813 } 8814 8815 var ANIMATION_END = getVendorPrefixedEventName('animationend'); 8816 var ANIMATION_ITERATION = getVendorPrefixedEventName('animationiteration'); 8817 var ANIMATION_START = getVendorPrefixedEventName('animationstart'); 8818 var TRANSITION_END = getVendorPrefixedEventName('transitionend'); 8819 8820 var topLevelEventsToReactNames = new Map(); // NOTE: Capitalization is important in this list! 8821 // 8822 // E.g. it needs "pointerDown", not "pointerdown". 8823 // This is because we derive both React name ("onPointerDown") 8824 // and DOM name ("pointerdown") from the same list. 8825 // 8826 // Exceptions that don't match this convention are listed separately. 8827 // 8828 // prettier-ignore 8829 8830 var simpleEventPluginEvents = ['abort', 'auxClick', 'cancel', 'canPlay', 'canPlayThrough', 'click', 'close', 'contextMenu', 'copy', 'cut', 'drag', 'dragEnd', 'dragEnter', 'dragExit', 'dragLeave', 'dragOver', 'dragStart', 'drop', 'durationChange', 'emptied', 'encrypted', 'ended', 'error', 'gotPointerCapture', 'input', 'invalid', 'keyDown', 'keyPress', 'keyUp', 'load', 'loadedData', 'loadedMetadata', 'loadStart', 'lostPointerCapture', 'mouseDown', 'mouseMove', 'mouseOut', 'mouseOver', 'mouseUp', 'paste', 'pause', 'play', 'playing', 'pointerCancel', 'pointerDown', 'pointerMove', 'pointerOut', 'pointerOver', 'pointerUp', 'progress', 'rateChange', 'reset', 'resize', 'seeked', 'seeking', 'stalled', 'submit', 'suspend', 'timeUpdate', 'touchCancel', 'touchEnd', 'touchStart', 'volumeChange', 'scroll', 'toggle', 'touchMove', 'waiting', 'wheel']; 8831 8832 function registerSimpleEvent(domEventName, reactName) { 8833 topLevelEventsToReactNames.set(domEventName, reactName); 8834 registerTwoPhaseEvent(reactName, [domEventName]); 8835 } 8836 8837 function registerSimpleEvents() { 8838 for (var i = 0; i < simpleEventPluginEvents.length; i++) { 8839 var eventName = simpleEventPluginEvents[i]; 8840 var domEventName = eventName.toLowerCase(); 8841 var capitalizedEvent = eventName[0].toUpperCase() + eventName.slice(1); 8842 registerSimpleEvent(domEventName, 'on' + capitalizedEvent); 8843 } // Special cases where event names don't match. 8844 8845 8846 registerSimpleEvent(ANIMATION_END, 'onAnimationEnd'); 8847 registerSimpleEvent(ANIMATION_ITERATION, 'onAnimationIteration'); 8848 registerSimpleEvent(ANIMATION_START, 'onAnimationStart'); 8849 registerSimpleEvent('dblclick', 'onDoubleClick'); 8850 registerSimpleEvent('focusin', 'onFocus'); 8851 registerSimpleEvent('focusout', 'onBlur'); 8852 registerSimpleEvent(TRANSITION_END, 'onTransitionEnd'); 8853 } 8854 8855 function extractEvents$4(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8856 var reactName = topLevelEventsToReactNames.get(domEventName); 8857 8858 if (reactName === undefined) { 8859 return; 8860 } 8861 8862 var SyntheticEventCtor = SyntheticEvent; 8863 var reactEventType = domEventName; 8864 8865 switch (domEventName) { 8866 case 'keypress': 8867 // Firefox creates a keypress event for function keys too. This removes 8868 // the unwanted keypress events. Enter is however both printable and 8869 // non-printable. One would expect Tab to be as well (but it isn't). 8870 if (getEventCharCode(nativeEvent) === 0) { 8871 return; 8872 } 8873 8874 /* falls through */ 8875 8876 case 'keydown': 8877 case 'keyup': 8878 SyntheticEventCtor = SyntheticKeyboardEvent; 8879 break; 8880 8881 case 'focusin': 8882 reactEventType = 'focus'; 8883 SyntheticEventCtor = SyntheticFocusEvent; 8884 break; 8885 8886 case 'focusout': 8887 reactEventType = 'blur'; 8888 SyntheticEventCtor = SyntheticFocusEvent; 8889 break; 8890 8891 case 'beforeblur': 8892 case 'afterblur': 8893 SyntheticEventCtor = SyntheticFocusEvent; 8894 break; 8895 8896 case 'click': 8897 // Firefox creates a click event on right mouse clicks. This removes the 8898 // unwanted click events. 8899 if (nativeEvent.button === 2) { 8900 return; 8901 } 8902 8903 /* falls through */ 8904 8905 case 'auxclick': 8906 case 'dblclick': 8907 case 'mousedown': 8908 case 'mousemove': 8909 case 'mouseup': // TODO: Disabled elements should not respond to mouse events 8910 8911 /* falls through */ 8912 8913 case 'mouseout': 8914 case 'mouseover': 8915 case 'contextmenu': 8916 SyntheticEventCtor = SyntheticMouseEvent; 8917 break; 8918 8919 case 'drag': 8920 case 'dragend': 8921 case 'dragenter': 8922 case 'dragexit': 8923 case 'dragleave': 8924 case 'dragover': 8925 case 'dragstart': 8926 case 'drop': 8927 SyntheticEventCtor = SyntheticDragEvent; 8928 break; 8929 8930 case 'touchcancel': 8931 case 'touchend': 8932 case 'touchmove': 8933 case 'touchstart': 8934 SyntheticEventCtor = SyntheticTouchEvent; 8935 break; 8936 8937 case ANIMATION_END: 8938 case ANIMATION_ITERATION: 8939 case ANIMATION_START: 8940 SyntheticEventCtor = SyntheticAnimationEvent; 8941 break; 8942 8943 case TRANSITION_END: 8944 SyntheticEventCtor = SyntheticTransitionEvent; 8945 break; 8946 8947 case 'scroll': 8948 SyntheticEventCtor = SyntheticUIEvent; 8949 break; 8950 8951 case 'wheel': 8952 SyntheticEventCtor = SyntheticWheelEvent; 8953 break; 8954 8955 case 'copy': 8956 case 'cut': 8957 case 'paste': 8958 SyntheticEventCtor = SyntheticClipboardEvent; 8959 break; 8960 8961 case 'gotpointercapture': 8962 case 'lostpointercapture': 8963 case 'pointercancel': 8964 case 'pointerdown': 8965 case 'pointermove': 8966 case 'pointerout': 8967 case 'pointerover': 8968 case 'pointerup': 8969 SyntheticEventCtor = SyntheticPointerEvent; 8970 break; 8971 } 8972 8973 var inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0; 8974 8975 { 8976 // Some events don't bubble in the browser. 8977 // In the past, React has always bubbled them, but this can be surprising. 8978 // We're going to try aligning closer to the browser behavior by not bubbling 8979 // them in React either. We'll start by not bubbling onScroll, and then expand. 8980 var accumulateTargetOnly = !inCapturePhase && // TODO: ideally, we'd eventually add all events from 8981 // nonDelegatedEvents list in DOMPluginEventSystem. 8982 // Then we can remove this special list. 8983 // This is a breaking change that can wait until React 18. 8984 domEventName === 'scroll'; 8985 8986 var _listeners = accumulateSinglePhaseListeners(targetInst, reactName, nativeEvent.type, inCapturePhase, accumulateTargetOnly); 8987 8988 if (_listeners.length > 0) { 8989 // Intentionally create event lazily. 8990 var _event = new SyntheticEventCtor(reactName, reactEventType, null, nativeEvent, nativeEventTarget); 8991 8992 dispatchQueue.push({ 8993 event: _event, 8994 listeners: _listeners 8995 }); 8996 } 8997 } 8998 } 8999 9000 // TODO: remove top-level side effect. 9001 registerSimpleEvents(); 9002 registerEvents$2(); 9003 registerEvents$1(); 9004 registerEvents$3(); 9005 registerEvents(); 9006 9007 function extractEvents$5(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 9008 // TODO: we should remove the concept of a "SimpleEventPlugin". 9009 // This is the basic functionality of the event system. All 9010 // the other plugins are essentially polyfills. So the plugin 9011 // should probably be inlined somewhere and have its logic 9012<