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