react-dom.development.js (1077022B)
1/** 2 * @license React 3 * react-dom.development.js 4 * 5 * Copyright (c) Facebook, Inc. and its affiliates. 6 * 7 * This source code is licensed under the MIT license found in the 8 * LICENSE file in the root directory of this source tree. 9 */ 10(function (global, factory) { 11 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) : 12 typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) : 13 (global = global || self, factory(global.ReactDOM = {}, global.React)); 14}(this, (function (exports, React) { 'use strict'; 15 16 var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; 17 18 var suppressWarning = false; 19 function setSuppressWarning(newSuppressWarning) { 20 { 21 suppressWarning = newSuppressWarning; 22 } 23 } // In DEV, calls to console.warn and console.error get replaced 24 // by calls to these methods by a Babel plugin. 25 // 26 // In PROD (or in packages without access to React internals), 27 // they are left as they are instead. 28 29 function warn(format) { 30 { 31 if (!suppressWarning) { 32 for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { 33 args[_key - 1] = arguments[_key]; 34 } 35 36 printWarning('warn', format, args); 37 } 38 } 39 } 40 function error(format) { 41 { 42 if (!suppressWarning) { 43 for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { 44 args[_key2 - 1] = arguments[_key2]; 45 } 46 47 printWarning('error', format, args); 48 } 49 } 50 } 51 52 function printWarning(level, format, args) { 53 // When changing this logic, you might want to also 54 // update consoleWithStackDev.www.js as well. 55 { 56 var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; 57 var stack = ReactDebugCurrentFrame.getStackAddendum(); 58 59 if (stack !== '') { 60 format += '%s'; 61 args = args.concat([stack]); 62 } // eslint-disable-next-line react-internal/safe-string-coercion 63 64 65 var argsWithFormat = args.map(function (item) { 66 return String(item); 67 }); // Careful: RN currently depends on this prefix 68 69 argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it 70 // breaks IE9: https://github.com/facebook/react/issues/13610 71 // eslint-disable-next-line react-internal/no-production-logging 72 73 Function.prototype.apply.call(console[level], console, argsWithFormat); 74 } 75 } 76 77 var FunctionComponent = 0; 78 var ClassComponent = 1; 79 var IndeterminateComponent = 2; // Before we know whether it is function or class 80 81 var HostRoot = 3; // Root of a host tree. Could be nested inside another node. 82 83 var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. 84 85 var HostComponent = 5; 86 var HostText = 6; 87 var Fragment = 7; 88 var Mode = 8; 89 var ContextConsumer = 9; 90 var ContextProvider = 10; 91 var ForwardRef = 11; 92 var Profiler = 12; 93 var SuspenseComponent = 13; 94 var MemoComponent = 14; 95 var SimpleMemoComponent = 15; 96 var LazyComponent = 16; 97 var IncompleteClassComponent = 17; 98 var DehydratedFragment = 18; 99 var SuspenseListComponent = 19; 100 var ScopeComponent = 21; 101 var OffscreenComponent = 22; 102 var LegacyHiddenComponent = 23; 103 var CacheComponent = 24; 104 var TracingMarkerComponent = 25; 105 106 // ----------------------------------------------------------------------------- 107 108 var enableClientRenderFallbackOnTextMismatch = true; // TODO: Need to review this code one more time before landing 109 // the react-reconciler package. 110 111 var enableNewReconciler = false; // Support legacy Primer support on internal FB www 112 113 var enableLazyContextPropagation = false; // FB-only usage. The new API has different semantics. 114 115 var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber 116 117 var enableSuspenseAvoidThisFallback = false; // Enables unstable_avoidThisFallback feature in Fizz 118 // React DOM Chopping Block 119 // 120 // Similar to main Chopping Block but only flags related to React DOM. These are 121 // grouped because we will likely batch all of them into a single major release. 122 // ----------------------------------------------------------------------------- 123 // Disable support for comment nodes as React DOM containers. Already disabled 124 // in open source, but www codebase still relies on it. Need to remove. 125 126 var disableCommentsAsDOMContainers = true; // Disable javascript: URL strings in href for XSS protection. 127 // and client rendering, mostly to allow JSX attributes to apply to the custom 128 // element's object properties instead of only HTML attributes. 129 // https://github.com/facebook/react/issues/11347 130 131 var enableCustomElementPropertySupport = false; // Disables children for <textarea> elements 132 var warnAboutStringRefs = false; // ----------------------------------------------------------------------------- 133 // Debugging and DevTools 134 // ----------------------------------------------------------------------------- 135 // Adds user timing marks for e.g. state updates, suspense, and work loop stuff, 136 // for an experimental timeline tool. 137 138 var enableSchedulingProfiler = true; // Helps identify side effects in render-phase lifecycle hooks and setState 139 140 var enableProfilerTimer = true; // Record durations for commit and passive effects phases. 141 142 var enableProfilerCommitHooks = true; // Phase param passed to onRender callback differentiates between an "update" and a "cascading-update". 143 144 var allNativeEvents = new Set(); 145 /** 146 * Mapping from registration name to event name 147 */ 148 149 150 var registrationNameDependencies = {}; 151 /** 152 * Mapping from lowercase registration names to the properly cased version, 153 * used to warn in the case of missing event handlers. Available 154 * only in true. 155 * @type {Object} 156 */ 157 158 var possibleRegistrationNames = {} ; // Trust the developer to only use possibleRegistrationNames in true 159 160 function registerTwoPhaseEvent(registrationName, dependencies) { 161 registerDirectEvent(registrationName, dependencies); 162 registerDirectEvent(registrationName + 'Capture', dependencies); 163 } 164 function registerDirectEvent(registrationName, dependencies) { 165 { 166 if (registrationNameDependencies[registrationName]) { 167 error('EventRegistry: More than one plugin attempted to publish the same ' + 'registration name, `%s`.', registrationName); 168 } 169 } 170 171 registrationNameDependencies[registrationName] = dependencies; 172 173 { 174 var lowerCasedName = registrationName.toLowerCase(); 175 possibleRegistrationNames[lowerCasedName] = registrationName; 176 177 if (registrationName === 'onDoubleClick') { 178 possibleRegistrationNames.ondblclick = registrationName; 179 } 180 } 181 182 for (var i = 0; i < dependencies.length; i++) { 183 allNativeEvents.add(dependencies[i]); 184 } 185 } 186 187 var canUseDOM = !!(typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined'); 188 189 var hasOwnProperty = Object.prototype.hasOwnProperty; 190 191 /* 192 * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol 193 * and Temporal.* types. See https://github.com/facebook/react/pull/22064. 194 * 195 * The functions in this module will throw an easier-to-understand, 196 * easier-to-debug exception with a clear errors message message explaining the 197 * problem. (Instead of a confusing exception thrown inside the implementation 198 * of the `value` object). 199 */ 200 // $FlowFixMe only called in DEV, so void return is not possible. 201 function typeName(value) { 202 { 203 // toStringTag is needed for namespaced types like Temporal.Instant 204 var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag; 205 var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object'; 206 return type; 207 } 208 } // $FlowFixMe only called in DEV, so void return is not possible. 209 210 211 function willCoercionThrow(value) { 212 { 213 try { 214 testStringCoercion(value); 215 return false; 216 } catch (e) { 217 return true; 218 } 219 } 220 } 221 222 function testStringCoercion(value) { 223 // If you ended up here by following an exception call stack, here's what's 224 // happened: you supplied an object or symbol value to React (as a prop, key, 225 // DOM attribute, CSS property, string ref, etc.) and when React tried to 226 // coerce it to a string using `'' + value`, an exception was thrown. 227 // 228 // The most common types that will cause this exception are `Symbol` instances 229 // and Temporal objects like `Temporal.Instant`. But any object that has a 230 // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this 231 // exception. (Library authors do this to prevent users from using built-in 232 // numeric operators like `+` or comparison operators like `>=` because custom 233 // methods are needed to perform accurate arithmetic or comparison.) 234 // 235 // To fix the problem, coerce this object or symbol value to a string before 236 // passing it to React. The most reliable way is usually `String(value)`. 237 // 238 // To find which value is throwing, check the browser or debugger console. 239 // Before this exception was thrown, there should be `console.error` output 240 // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the 241 // problem and how that type was used: key, atrribute, input value prop, etc. 242 // In most cases, this console output also shows the component and its 243 // ancestor components where the exception happened. 244 // 245 // eslint-disable-next-line react-internal/safe-string-coercion 246 return '' + value; 247 } 248 249 function checkAttributeStringCoercion(value, attributeName) { 250 { 251 if (willCoercionThrow(value)) { 252 error('The provided `%s` attribute is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', attributeName, typeName(value)); 253 254 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 255 } 256 } 257 } 258 function checkKeyStringCoercion(value) { 259 { 260 if (willCoercionThrow(value)) { 261 error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 262 263 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 264 } 265 } 266 } 267 function checkPropStringCoercion(value, propName) { 268 { 269 if (willCoercionThrow(value)) { 270 error('The provided `%s` prop is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value)); 271 272 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 273 } 274 } 275 } 276 function checkCSSPropertyStringCoercion(value, propName) { 277 { 278 if (willCoercionThrow(value)) { 279 error('The provided `%s` CSS property is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value)); 280 281 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 282 } 283 } 284 } 285 function checkHtmlStringCoercion(value) { 286 { 287 if (willCoercionThrow(value)) { 288 error('The provided HTML markup uses a value of unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 289 290 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 291 } 292 } 293 } 294 function checkFormFieldValueStringCoercion(value) { 295 { 296 if (willCoercionThrow(value)) { 297 error('Form field values (value, checked, defaultValue, or defaultChecked props)' + ' must be strings, not %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); 298 299 return testStringCoercion(value); // throw (to help callers find troubleshooting comments) 300 } 301 } 302 } 303 304 // A reserved attribute. 305 // It is handled by React separately and shouldn't be written to the DOM. 306 var RESERVED = 0; // A simple string attribute. 307 // Attributes that aren't in the filter are presumed to have this type. 308 309 var STRING = 1; // A string attribute that accepts booleans in React. In HTML, these are called 310 // "enumerated" attributes with "true" and "false" as possible values. 311 // When true, it should be set to a "true" string. 312 // When false, it should be set to a "false" string. 313 314 var BOOLEANISH_STRING = 2; // A real boolean attribute. 315 // When true, it should be present (set either to an empty string or its name). 316 // When false, it should be omitted. 317 318 var BOOLEAN = 3; // An attribute that can be used as a flag as well as with a value. 319 // When true, it should be present (set either to an empty string or its name). 320 // When false, it should be omitted. 321 // For any other value, should be present with that value. 322 323 var OVERLOADED_BOOLEAN = 4; // An attribute that must be numeric or parse as a numeric. 324 // When falsy, it should be removed. 325 326 var NUMERIC = 5; // An attribute that must be positive numeric or parse as a positive numeric. 327 // When falsy, it should be removed. 328 329 var POSITIVE_NUMERIC = 6; 330 331 /* eslint-disable max-len */ 332 var ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; 333 /* eslint-enable max-len */ 334 335 var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; 336 var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$'); 337 var illegalAttributeNameCache = {}; 338 var validatedAttributeNameCache = {}; 339 function isAttributeNameSafe(attributeName) { 340 if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { 341 return true; 342 } 343 344 if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { 345 return false; 346 } 347 348 if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { 349 validatedAttributeNameCache[attributeName] = true; 350 return true; 351 } 352 353 illegalAttributeNameCache[attributeName] = true; 354 355 { 356 error('Invalid attribute name: `%s`', attributeName); 357 } 358 359 return false; 360 } 361 function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) { 362 if (propertyInfo !== null) { 363 return propertyInfo.type === RESERVED; 364 } 365 366 if (isCustomComponentTag) { 367 return false; 368 } 369 370 if (name.length > 2 && (name[0] === 'o' || name[0] === 'O') && (name[1] === 'n' || name[1] === 'N')) { 371 return true; 372 } 373 374 return false; 375 } 376 function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) { 377 if (propertyInfo !== null && propertyInfo.type === RESERVED) { 378 return false; 379 } 380 381 switch (typeof value) { 382 case 'function': // $FlowIssue symbol is perfectly valid here 383 384 case 'symbol': 385 // eslint-disable-line 386 return true; 387 388 case 'boolean': 389 { 390 if (isCustomComponentTag) { 391 return false; 392 } 393 394 if (propertyInfo !== null) { 395 return !propertyInfo.acceptsBooleans; 396 } else { 397 var prefix = name.toLowerCase().slice(0, 5); 398 return prefix !== 'data-' && prefix !== 'aria-'; 399 } 400 } 401 402 default: 403 return false; 404 } 405 } 406 function shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag) { 407 if (value === null || typeof value === 'undefined') { 408 return true; 409 } 410 411 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag)) { 412 return true; 413 } 414 415 if (isCustomComponentTag) { 416 417 return false; 418 } 419 420 if (propertyInfo !== null) { 421 422 switch (propertyInfo.type) { 423 case BOOLEAN: 424 return !value; 425 426 case OVERLOADED_BOOLEAN: 427 return value === false; 428 429 case NUMERIC: 430 return isNaN(value); 431 432 case POSITIVE_NUMERIC: 433 return isNaN(value) || value < 1; 434 } 435 } 436 437 return false; 438 } 439 function getPropertyInfo(name) { 440 return properties.hasOwnProperty(name) ? properties[name] : null; 441 } 442 443 function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace, sanitizeURL, removeEmptyString) { 444 this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN; 445 this.attributeName = attributeName; 446 this.attributeNamespace = attributeNamespace; 447 this.mustUseProperty = mustUseProperty; 448 this.propertyName = name; 449 this.type = type; 450 this.sanitizeURL = sanitizeURL; 451 this.removeEmptyString = removeEmptyString; 452 } // When adding attributes to this list, be sure to also add them to 453 // the `possibleStandardNames` module to ensure casing and incorrect 454 // name warnings. 455 456 457 var properties = {}; // These props are reserved by React. They shouldn't be written to the DOM. 458 459 var reservedProps = ['children', 'dangerouslySetInnerHTML', // TODO: This prevents the assignment of defaultValue to regular 460 // elements (not just inputs). Now that ReactDOMInput assigns to the 461 // defaultValue property -- do we need this? 462 'defaultValue', 'defaultChecked', 'innerHTML', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'style']; 463 464 reservedProps.forEach(function (name) { 465 properties[name] = new PropertyInfoRecord(name, RESERVED, false, // mustUseProperty 466 name, // attributeName 467 null, // attributeNamespace 468 false, // sanitizeURL 469 false); 470 }); // A few React string attributes have a different name. 471 // This is a mapping from React prop names to the attribute names. 472 473 [['acceptCharset', 'accept-charset'], ['className', 'class'], ['htmlFor', 'for'], ['httpEquiv', 'http-equiv']].forEach(function (_ref) { 474 var name = _ref[0], 475 attributeName = _ref[1]; 476 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 477 attributeName, // attributeName 478 null, // attributeNamespace 479 false, // sanitizeURL 480 false); 481 }); // These are "enumerated" HTML attributes that accept "true" and "false". 482 // In React, we let users pass `true` and `false` even though technically 483 // these aren't boolean attributes (they are coerced to strings). 484 485 ['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (name) { 486 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty 487 name.toLowerCase(), // attributeName 488 null, // attributeNamespace 489 false, // sanitizeURL 490 false); 491 }); // These are "enumerated" SVG attributes that accept "true" and "false". 492 // In React, we let users pass `true` and `false` even though technically 493 // these aren't boolean attributes (they are coerced to strings). 494 // Since these are SVG attributes, their attribute names are case-sensitive. 495 496 ['autoReverse', 'externalResourcesRequired', 'focusable', 'preserveAlpha'].forEach(function (name) { 497 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty 498 name, // attributeName 499 null, // attributeNamespace 500 false, // sanitizeURL 501 false); 502 }); // These are HTML boolean attributes. 503 504 ['allowFullScreen', 'async', // Note: there is a special case that prevents it from being written to the DOM 505 // on the client side because the browsers are inconsistent. Instead we call focus(). 506 'autoFocus', 'autoPlay', 'controls', 'default', 'defer', 'disabled', 'disablePictureInPicture', 'disableRemotePlayback', 'formNoValidate', 'hidden', 'loop', 'noModule', 'noValidate', 'open', 'playsInline', 'readOnly', 'required', 'reversed', 'scoped', 'seamless', // Microdata 507 'itemScope'].forEach(function (name) { 508 properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, // mustUseProperty 509 name.toLowerCase(), // attributeName 510 null, // attributeNamespace 511 false, // sanitizeURL 512 false); 513 }); // These are the few React props that we set as DOM properties 514 // rather than attributes. These are all booleans. 515 516 ['checked', // Note: `option.selected` is not updated if `select.multiple` is 517 // disabled with `removeAttribute`. We have special logic for handling this. 518 'multiple', 'muted', 'selected' // NOTE: if you add a camelCased prop to this list, 519 // you'll need to set attributeName to name.toLowerCase() 520 // instead in the assignment below. 521 ].forEach(function (name) { 522 properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, // mustUseProperty 523 name, // attributeName 524 null, // attributeNamespace 525 false, // sanitizeURL 526 false); 527 }); // These are HTML attributes that are "overloaded booleans": they behave like 528 // booleans, but can also accept a string value. 529 530 ['capture', 'download' // NOTE: if you add a camelCased prop to this list, 531 // you'll need to set attributeName to name.toLowerCase() 532 // instead in the assignment below. 533 ].forEach(function (name) { 534 properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, // mustUseProperty 535 name, // attributeName 536 null, // attributeNamespace 537 false, // sanitizeURL 538 false); 539 }); // These are HTML attributes that must be positive numbers. 540 541 ['cols', 'rows', 'size', 'span' // NOTE: if you add a camelCased prop to this list, 542 // you'll need to set attributeName to name.toLowerCase() 543 // instead in the assignment below. 544 ].forEach(function (name) { 545 properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, // mustUseProperty 546 name, // attributeName 547 null, // attributeNamespace 548 false, // sanitizeURL 549 false); 550 }); // These are HTML attributes that must be numbers. 551 552 ['rowSpan', 'start'].forEach(function (name) { 553 properties[name] = new PropertyInfoRecord(name, NUMERIC, false, // mustUseProperty 554 name.toLowerCase(), // attributeName 555 null, // attributeNamespace 556 false, // sanitizeURL 557 false); 558 }); 559 var CAMELIZE = /[\-\:]([a-z])/g; 560 561 var capitalize = function (token) { 562 return token[1].toUpperCase(); 563 }; // This is a list of all SVG attributes that need special casing, namespacing, 564 // or boolean value assignment. Regular attributes that just accept strings 565 // and have the same names are omitted, just like in the HTML attribute filter. 566 // Some of these attributes can be hard to find. This list was created by 567 // scraping the MDN documentation. 568 569 570 ['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'xmlns:xlink', 'x-height' // NOTE: if you add a camelCased prop to this list, 571 // you'll need to set attributeName to name.toLowerCase() 572 // instead in the assignment below. 573 ].forEach(function (attributeName) { 574 var name = attributeName.replace(CAMELIZE, capitalize); 575 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 576 attributeName, null, // attributeNamespace 577 false, // sanitizeURL 578 false); 579 }); // String SVG attributes with the xlink namespace. 580 581 ['xlink:actuate', 'xlink:arcrole', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type' // NOTE: if you add a camelCased prop to this list, 582 // you'll need to set attributeName to name.toLowerCase() 583 // instead in the assignment below. 584 ].forEach(function (attributeName) { 585 var name = attributeName.replace(CAMELIZE, capitalize); 586 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 587 attributeName, 'http://www.w3.org/1999/xlink', false, // sanitizeURL 588 false); 589 }); // String SVG attributes with the xml namespace. 590 591 ['xml:base', 'xml:lang', 'xml:space' // NOTE: if you add a camelCased prop to this list, 592 // you'll need to set attributeName to name.toLowerCase() 593 // instead in the assignment below. 594 ].forEach(function (attributeName) { 595 var name = attributeName.replace(CAMELIZE, capitalize); 596 properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty 597 attributeName, 'http://www.w3.org/XML/1998/namespace', false, // sanitizeURL 598 false); 599 }); // These attribute exists both in HTML and SVG. 600 // The attribute name is case-sensitive in SVG so we can't just use 601 // the React name like we do for attributes that exist only in HTML. 602 603 ['tabIndex', 'crossOrigin'].forEach(function (attributeName) { 604 properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty 605 attributeName.toLowerCase(), // attributeName 606 null, // attributeNamespace 607 false, // sanitizeURL 608 false); 609 }); // These attributes accept URLs. These must not allow javascript: URLS. 610 // These will also need to accept Trusted Types object in the future. 611 612 var xlinkHref = 'xlinkHref'; 613 properties[xlinkHref] = new PropertyInfoRecord('xlinkHref', STRING, false, // mustUseProperty 614 'xlink:href', 'http://www.w3.org/1999/xlink', true, // sanitizeURL 615 false); 616 ['src', 'href', 'action', 'formAction'].forEach(function (attributeName) { 617 properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty 618 attributeName.toLowerCase(), // attributeName 619 null, // attributeNamespace 620 true, // sanitizeURL 621 true); 622 }); 623 624 // and any newline or tab are filtered out as if they're not part of the URL. 625 // https://url.spec.whatwg.org/#url-parsing 626 // Tab or newline are defined as \r\n\t: 627 // https://infra.spec.whatwg.org/#ascii-tab-or-newline 628 // A C0 control is a code point in the range \u0000 NULL to \u001F 629 // INFORMATION SEPARATOR ONE, inclusive: 630 // https://infra.spec.whatwg.org/#c0-control-or-space 631 632 /* eslint-disable max-len */ 633 634 var isJavaScriptProtocol = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; 635 var didWarn = false; 636 637 function sanitizeURL(url) { 638 { 639 if (!didWarn && isJavaScriptProtocol.test(url)) { 640 didWarn = true; 641 642 error('A future version of React will block javascript: URLs as a security precaution. ' + 'Use event handlers instead if you can. If you need to generate unsafe HTML try ' + 'using dangerouslySetInnerHTML instead. React was passed %s.', JSON.stringify(url)); 643 } 644 } 645 } 646 647 /** 648 * Get the value for a property on a node. Only used in DEV for SSR validation. 649 * The "expected" argument is used as a hint of what the expected value is. 650 * Some properties have multiple equivalent values. 651 */ 652 function getValueForProperty(node, name, expected, propertyInfo) { 653 { 654 if (propertyInfo.mustUseProperty) { 655 var propertyName = propertyInfo.propertyName; 656 return node[propertyName]; 657 } else { 658 // This check protects multiple uses of `expected`, which is why the 659 // react-internal/safe-string-coercion rule is disabled in several spots 660 // below. 661 { 662 checkAttributeStringCoercion(expected, name); 663 } 664 665 if ( propertyInfo.sanitizeURL) { 666 // If we haven't fully disabled javascript: URLs, and if 667 // the hydration is successful of a javascript: URL, we 668 // still want to warn on the client. 669 // eslint-disable-next-line react-internal/safe-string-coercion 670 sanitizeURL('' + expected); 671 } 672 673 var attributeName = propertyInfo.attributeName; 674 var stringValue = null; 675 676 if (propertyInfo.type === OVERLOADED_BOOLEAN) { 677 if (node.hasAttribute(attributeName)) { 678 var value = node.getAttribute(attributeName); 679 680 if (value === '') { 681 return true; 682 } 683 684 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 685 return value; 686 } // eslint-disable-next-line react-internal/safe-string-coercion 687 688 689 if (value === '' + expected) { 690 return expected; 691 } 692 693 return value; 694 } 695 } else if (node.hasAttribute(attributeName)) { 696 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 697 // We had an attribute but shouldn't have had one, so read it 698 // for the error message. 699 return node.getAttribute(attributeName); 700 } 701 702 if (propertyInfo.type === BOOLEAN) { 703 // If this was a boolean, it doesn't matter what the value is 704 // the fact that we have it is the same as the expected. 705 return expected; 706 } // Even if this property uses a namespace we use getAttribute 707 // because we assume its namespaced name is the same as our config. 708 // To use getAttributeNS we need the local name which we don't have 709 // in our config atm. 710 711 712 stringValue = node.getAttribute(attributeName); 713 } 714 715 if (shouldRemoveAttribute(name, expected, propertyInfo, false)) { 716 return stringValue === null ? expected : stringValue; // eslint-disable-next-line react-internal/safe-string-coercion 717 } else if (stringValue === '' + expected) { 718 return expected; 719 } else { 720 return stringValue; 721 } 722 } 723 } 724 } 725 /** 726 * Get the value for a attribute on a node. Only used in DEV for SSR validation. 727 * The third argument is used as a hint of what the expected value is. Some 728 * attributes have multiple equivalent values. 729 */ 730 731 function getValueForAttribute(node, name, expected, isCustomComponentTag) { 732 { 733 if (!isAttributeNameSafe(name)) { 734 return; 735 } 736 737 if (!node.hasAttribute(name)) { 738 return expected === undefined ? undefined : null; 739 } 740 741 var value = node.getAttribute(name); 742 743 { 744 checkAttributeStringCoercion(expected, name); 745 } 746 747 if (value === '' + expected) { 748 return expected; 749 } 750 751 return value; 752 } 753 } 754 /** 755 * Sets the value for a property on a node. 756 * 757 * @param {DOMElement} node 758 * @param {string} name 759 * @param {*} value 760 */ 761 762 function setValueForProperty(node, name, value, isCustomComponentTag) { 763 var propertyInfo = getPropertyInfo(name); 764 765 if (shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag)) { 766 return; 767 } 768 769 if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) { 770 value = null; 771 } 772 773 774 if (isCustomComponentTag || propertyInfo === null) { 775 if (isAttributeNameSafe(name)) { 776 var _attributeName = name; 777 778 if (value === null) { 779 node.removeAttribute(_attributeName); 780 } else { 781 { 782 checkAttributeStringCoercion(value, name); 783 } 784 785 node.setAttribute(_attributeName, '' + value); 786 } 787 } 788 789 return; 790 } 791 792 var mustUseProperty = propertyInfo.mustUseProperty; 793 794 if (mustUseProperty) { 795 var propertyName = propertyInfo.propertyName; 796 797 if (value === null) { 798 var type = propertyInfo.type; 799 node[propertyName] = type === BOOLEAN ? false : ''; 800 } else { 801 // Contrary to `setAttribute`, object properties are properly 802 // `toString`ed by IE8/9. 803 node[propertyName] = value; 804 } 805 806 return; 807 } // The rest are treated as attributes with special cases. 808 809 810 var attributeName = propertyInfo.attributeName, 811 attributeNamespace = propertyInfo.attributeNamespace; 812 813 if (value === null) { 814 node.removeAttribute(attributeName); 815 } else { 816 var _type = propertyInfo.type; 817 var attributeValue; 818 819 if (_type === BOOLEAN || _type === OVERLOADED_BOOLEAN && value === true) { 820 // If attribute type is boolean, we know for sure it won't be an execution sink 821 // and we won't require Trusted Type here. 822 attributeValue = ''; 823 } else { 824 // `setAttribute` with objects becomes only `[object]` in IE8/9, 825 // ('' + value) makes it output the correct toString()-value. 826 { 827 { 828 checkAttributeStringCoercion(value, attributeName); 829 } 830 831 attributeValue = '' + value; 832 } 833 834 if (propertyInfo.sanitizeURL) { 835 sanitizeURL(attributeValue.toString()); 836 } 837 } 838 839 if (attributeNamespace) { 840 node.setAttributeNS(attributeNamespace, attributeName, attributeValue); 841 } else { 842 node.setAttribute(attributeName, attributeValue); 843 } 844 } 845 } 846 847 // ATTENTION 848 // When adding new symbols to this file, 849 // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' 850 // The Symbol used to tag the ReactElement-like types. 851 var REACT_ELEMENT_TYPE = Symbol.for('react.element'); 852 var REACT_PORTAL_TYPE = Symbol.for('react.portal'); 853 var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); 854 var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode'); 855 var REACT_PROFILER_TYPE = Symbol.for('react.profiler'); 856 var REACT_PROVIDER_TYPE = Symbol.for('react.provider'); 857 var REACT_CONTEXT_TYPE = Symbol.for('react.context'); 858 var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref'); 859 var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense'); 860 var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list'); 861 var REACT_MEMO_TYPE = Symbol.for('react.memo'); 862 var REACT_LAZY_TYPE = Symbol.for('react.lazy'); 863 var REACT_SCOPE_TYPE = Symbol.for('react.scope'); 864 var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for('react.debug_trace_mode'); 865 var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen'); 866 var REACT_LEGACY_HIDDEN_TYPE = Symbol.for('react.legacy_hidden'); 867 var REACT_CACHE_TYPE = Symbol.for('react.cache'); 868 var REACT_TRACING_MARKER_TYPE = Symbol.for('react.tracing_marker'); 869 var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; 870 var FAUX_ITERATOR_SYMBOL = '@@iterator'; 871 function getIteratorFn(maybeIterable) { 872 if (maybeIterable === null || typeof maybeIterable !== 'object') { 873 return null; 874 } 875 876 var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; 877 878 if (typeof maybeIterator === 'function') { 879 return maybeIterator; 880 } 881 882 return null; 883 } 884 885 var assign = Object.assign; 886 887 // Helpers to patch console.logs to avoid logging during side-effect free 888 // replaying on render function. This currently only patches the object 889 // lazily which won't cover if the log function was extracted eagerly. 890 // We could also eagerly patch the method. 891 var disabledDepth = 0; 892 var prevLog; 893 var prevInfo; 894 var prevWarn; 895 var prevError; 896 var prevGroup; 897 var prevGroupCollapsed; 898 var prevGroupEnd; 899 900 function disabledLog() {} 901 902 disabledLog.__reactDisabledLog = true; 903 function disableLogs() { 904 { 905 if (disabledDepth === 0) { 906 /* eslint-disable react-internal/no-production-logging */ 907 prevLog = console.log; 908 prevInfo = console.info; 909 prevWarn = console.warn; 910 prevError = console.error; 911 prevGroup = console.group; 912 prevGroupCollapsed = console.groupCollapsed; 913 prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 914 915 var props = { 916 configurable: true, 917 enumerable: true, 918 value: disabledLog, 919 writable: true 920 }; // $FlowFixMe Flow thinks console is immutable. 921 922 Object.defineProperties(console, { 923 info: props, 924 log: props, 925 warn: props, 926 error: props, 927 group: props, 928 groupCollapsed: props, 929 groupEnd: props 930 }); 931 /* eslint-enable react-internal/no-production-logging */ 932 } 933 934 disabledDepth++; 935 } 936 } 937 function reenableLogs() { 938 { 939 disabledDepth--; 940 941 if (disabledDepth === 0) { 942 /* eslint-disable react-internal/no-production-logging */ 943 var props = { 944 configurable: true, 945 enumerable: true, 946 writable: true 947 }; // $FlowFixMe Flow thinks console is immutable. 948 949 Object.defineProperties(console, { 950 log: assign({}, props, { 951 value: prevLog 952 }), 953 info: assign({}, props, { 954 value: prevInfo 955 }), 956 warn: assign({}, props, { 957 value: prevWarn 958 }), 959 error: assign({}, props, { 960 value: prevError 961 }), 962 group: assign({}, props, { 963 value: prevGroup 964 }), 965 groupCollapsed: assign({}, props, { 966 value: prevGroupCollapsed 967 }), 968 groupEnd: assign({}, props, { 969 value: prevGroupEnd 970 }) 971 }); 972 /* eslint-enable react-internal/no-production-logging */ 973 } 974 975 if (disabledDepth < 0) { 976 error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.'); 977 } 978 } 979 } 980 981 var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; 982 var prefix; 983 function describeBuiltInComponentFrame(name, source, ownerFn) { 984 { 985 if (prefix === undefined) { 986 // Extract the VM specific prefix used by each line. 987 try { 988 throw Error(); 989 } catch (x) { 990 var match = x.stack.trim().match(/\n( *(at )?)/); 991 prefix = match && match[1] || ''; 992 } 993 } // We use the prefix to ensure our stacks line up with native stack frames. 994 995 996 return '\n' + prefix + name; 997 } 998 } 999 var reentry = false; 1000 var componentFrameCache; 1001 1002 { 1003 var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; 1004 componentFrameCache = new PossiblyWeakMap(); 1005 } 1006 1007 function describeNativeComponentFrame(fn, construct) { 1008 // If something asked for a stack inside a fake render, it should get ignored. 1009 if ( !fn || reentry) { 1010 return ''; 1011 } 1012 1013 { 1014 var frame = componentFrameCache.get(fn); 1015 1016 if (frame !== undefined) { 1017 return frame; 1018 } 1019 } 1020 1021 var control; 1022 reentry = true; 1023 var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined. 1024 1025 Error.prepareStackTrace = undefined; 1026 var previousDispatcher; 1027 1028 { 1029 previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function 1030 // for warnings. 1031 1032 ReactCurrentDispatcher.current = null; 1033 disableLogs(); 1034 } 1035 1036 try { 1037 // This should throw. 1038 if (construct) { 1039 // Something should be setting the props in the constructor. 1040 var Fake = function () { 1041 throw Error(); 1042 }; // $FlowFixMe 1043 1044 1045 Object.defineProperty(Fake.prototype, 'props', { 1046 set: function () { 1047 // We use a throwing setter instead of frozen or non-writable props 1048 // because that won't throw in a non-strict mode function. 1049 throw Error(); 1050 } 1051 }); 1052 1053 if (typeof Reflect === 'object' && Reflect.construct) { 1054 // We construct a different control for this case to include any extra 1055 // frames added by the construct call. 1056 try { 1057 Reflect.construct(Fake, []); 1058 } catch (x) { 1059 control = x; 1060 } 1061 1062 Reflect.construct(fn, [], Fake); 1063 } else { 1064 try { 1065 Fake.call(); 1066 } catch (x) { 1067 control = x; 1068 } 1069 1070 fn.call(Fake.prototype); 1071 } 1072 } else { 1073 try { 1074 throw Error(); 1075 } catch (x) { 1076 control = x; 1077 } 1078 1079 fn(); 1080 } 1081 } catch (sample) { 1082 // This is inlined manually because closure doesn't do it for us. 1083 if (sample && control && typeof sample.stack === 'string') { 1084 // This extracts the first frame from the sample that isn't also in the control. 1085 // Skipping one frame that we assume is the frame that calls the two. 1086 var sampleLines = sample.stack.split('\n'); 1087 var controlLines = control.stack.split('\n'); 1088 var s = sampleLines.length - 1; 1089 var c = controlLines.length - 1; 1090 1091 while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { 1092 // We expect at least one stack frame to be shared. 1093 // Typically this will be the root most one. However, stack frames may be 1094 // cut off due to maximum stack limits. In this case, one maybe cut off 1095 // earlier than the other. We assume that the sample is longer or the same 1096 // and there for cut off earlier. So we should find the root most frame in 1097 // the sample somewhere in the control. 1098 c--; 1099 } 1100 1101 for (; s >= 1 && c >= 0; s--, c--) { 1102 // Next we find the first one that isn't the same which should be the 1103 // frame that called our sample function and the control. 1104 if (sampleLines[s] !== controlLines[c]) { 1105 // In V8, the first line is describing the message but other VMs don't. 1106 // If we're about to return the first line, and the control is also on the same 1107 // line, that's a pretty good indicator that our sample threw at same line as 1108 // the control. I.e. before we entered the sample frame. So we ignore this result. 1109 // This can happen if you passed a class to function component, or non-function. 1110 if (s !== 1 || c !== 1) { 1111 do { 1112 s--; 1113 c--; // We may still have similar intermediate frames from the construct call. 1114 // The next one that isn't the same should be our match though. 1115 1116 if (c < 0 || sampleLines[s] !== controlLines[c]) { 1117 // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. 1118 var _frame = '\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled "<anonymous>" 1119 // but we have a user-provided "displayName" 1120 // splice it in to make the stack more readable. 1121 1122 1123 if (fn.displayName && _frame.includes('<anonymous>')) { 1124 _frame = _frame.replace('<anonymous>', fn.displayName); 1125 } 1126 1127 { 1128 if (typeof fn === 'function') { 1129 componentFrameCache.set(fn, _frame); 1130 } 1131 } // Return the line we found. 1132 1133 1134 return _frame; 1135 } 1136 } while (s >= 1 && c >= 0); 1137 } 1138 1139 break; 1140 } 1141 } 1142 } 1143 } finally { 1144 reentry = false; 1145 1146 { 1147 ReactCurrentDispatcher.current = previousDispatcher; 1148 reenableLogs(); 1149 } 1150 1151 Error.prepareStackTrace = previousPrepareStackTrace; 1152 } // Fallback to just using the name if we couldn't make it throw. 1153 1154 1155 var name = fn ? fn.displayName || fn.name : ''; 1156 var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ''; 1157 1158 { 1159 if (typeof fn === 'function') { 1160 componentFrameCache.set(fn, syntheticFrame); 1161 } 1162 } 1163 1164 return syntheticFrame; 1165 } 1166 1167 function describeClassComponentFrame(ctor, source, ownerFn) { 1168 { 1169 return describeNativeComponentFrame(ctor, true); 1170 } 1171 } 1172 function describeFunctionComponentFrame(fn, source, ownerFn) { 1173 { 1174 return describeNativeComponentFrame(fn, false); 1175 } 1176 } 1177 1178 function shouldConstruct(Component) { 1179 var prototype = Component.prototype; 1180 return !!(prototype && prototype.isReactComponent); 1181 } 1182 1183 function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { 1184 1185 if (type == null) { 1186 return ''; 1187 } 1188 1189 if (typeof type === 'function') { 1190 { 1191 return describeNativeComponentFrame(type, shouldConstruct(type)); 1192 } 1193 } 1194 1195 if (typeof type === 'string') { 1196 return describeBuiltInComponentFrame(type); 1197 } 1198 1199 switch (type) { 1200 case REACT_SUSPENSE_TYPE: 1201 return describeBuiltInComponentFrame('Suspense'); 1202 1203 case REACT_SUSPENSE_LIST_TYPE: 1204 return describeBuiltInComponentFrame('SuspenseList'); 1205 } 1206 1207 if (typeof type === 'object') { 1208 switch (type.$$typeof) { 1209 case REACT_FORWARD_REF_TYPE: 1210 return describeFunctionComponentFrame(type.render); 1211 1212 case REACT_MEMO_TYPE: 1213 // Memo may contain any component type so we recursively resolve it. 1214 return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); 1215 1216 case REACT_LAZY_TYPE: 1217 { 1218 var lazyComponent = type; 1219 var payload = lazyComponent._payload; 1220 var init = lazyComponent._init; 1221 1222 try { 1223 // Lazy may contain any component type so we recursively resolve it. 1224 return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn); 1225 } catch (x) {} 1226 } 1227 } 1228 } 1229 1230 return ''; 1231 } 1232 1233 function describeFiber(fiber) { 1234 var owner = fiber._debugOwner ? fiber._debugOwner.type : null ; 1235 var source = fiber._debugSource ; 1236 1237 switch (fiber.tag) { 1238 case HostComponent: 1239 return describeBuiltInComponentFrame(fiber.type); 1240 1241 case LazyComponent: 1242 return describeBuiltInComponentFrame('Lazy'); 1243 1244 case SuspenseComponent: 1245 return describeBuiltInComponentFrame('Suspense'); 1246 1247 case SuspenseListComponent: 1248 return describeBuiltInComponentFrame('SuspenseList'); 1249 1250 case FunctionComponent: 1251 case IndeterminateComponent: 1252 case SimpleMemoComponent: 1253 return describeFunctionComponentFrame(fiber.type); 1254 1255 case ForwardRef: 1256 return describeFunctionComponentFrame(fiber.type.render); 1257 1258 case ClassComponent: 1259 return describeClassComponentFrame(fiber.type); 1260 1261 default: 1262 return ''; 1263 } 1264 } 1265 1266 function getStackByFiberInDevAndProd(workInProgress) { 1267 try { 1268 var info = ''; 1269 var node = workInProgress; 1270 1271 do { 1272 info += describeFiber(node); 1273 node = node.return; 1274 } while (node); 1275 1276 return info; 1277 } catch (x) { 1278 return '\nError generating stack: ' + x.message + '\n' + x.stack; 1279 } 1280 } 1281 1282 function getWrappedName(outerType, innerType, wrapperName) { 1283 var displayName = outerType.displayName; 1284 1285 if (displayName) { 1286 return displayName; 1287 } 1288 1289 var functionName = innerType.displayName || innerType.name || ''; 1290 return functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName; 1291 } // Keep in sync with react-reconciler/getComponentNameFromFiber 1292 1293 1294 function getContextName(type) { 1295 return type.displayName || 'Context'; 1296 } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. 1297 1298 1299 function getComponentNameFromType(type) { 1300 if (type == null) { 1301 // Host root, text node or just invalid type. 1302 return null; 1303 } 1304 1305 { 1306 if (typeof type.tag === 'number') { 1307 error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.'); 1308 } 1309 } 1310 1311 if (typeof type === 'function') { 1312 return type.displayName || type.name || null; 1313 } 1314 1315 if (typeof type === 'string') { 1316 return type; 1317 } 1318 1319 switch (type) { 1320 case REACT_FRAGMENT_TYPE: 1321 return 'Fragment'; 1322 1323 case REACT_PORTAL_TYPE: 1324 return 'Portal'; 1325 1326 case REACT_PROFILER_TYPE: 1327 return 'Profiler'; 1328 1329 case REACT_STRICT_MODE_TYPE: 1330 return 'StrictMode'; 1331 1332 case REACT_SUSPENSE_TYPE: 1333 return 'Suspense'; 1334 1335 case REACT_SUSPENSE_LIST_TYPE: 1336 return 'SuspenseList'; 1337 1338 } 1339 1340 if (typeof type === 'object') { 1341 switch (type.$$typeof) { 1342 case REACT_CONTEXT_TYPE: 1343 var context = type; 1344 return getContextName(context) + '.Consumer'; 1345 1346 case REACT_PROVIDER_TYPE: 1347 var provider = type; 1348 return getContextName(provider._context) + '.Provider'; 1349 1350 case REACT_FORWARD_REF_TYPE: 1351 return getWrappedName(type, type.render, 'ForwardRef'); 1352 1353 case REACT_MEMO_TYPE: 1354 var outerName = type.displayName || null; 1355 1356 if (outerName !== null) { 1357 return outerName; 1358 } 1359 1360 return getComponentNameFromType(type.type) || 'Memo'; 1361 1362 case REACT_LAZY_TYPE: 1363 { 1364 var lazyComponent = type; 1365 var payload = lazyComponent._payload; 1366 var init = lazyComponent._init; 1367 1368 try { 1369 return getComponentNameFromType(init(payload)); 1370 } catch (x) { 1371 return null; 1372 } 1373 } 1374 1375 // eslint-disable-next-line no-fallthrough 1376 } 1377 } 1378 1379 return null; 1380 } 1381 1382 function getWrappedName$1(outerType, innerType, wrapperName) { 1383 var functionName = innerType.displayName || innerType.name || ''; 1384 return outerType.displayName || (functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName); 1385 } // Keep in sync with shared/getComponentNameFromType 1386 1387 1388 function getContextName$1(type) { 1389 return type.displayName || 'Context'; 1390 } 1391 1392 function getComponentNameFromFiber(fiber) { 1393 var tag = fiber.tag, 1394 type = fiber.type; 1395 1396 switch (tag) { 1397 case CacheComponent: 1398 return 'Cache'; 1399 1400 case ContextConsumer: 1401 var context = type; 1402 return getContextName$1(context) + '.Consumer'; 1403 1404 case ContextProvider: 1405 var provider = type; 1406 return getContextName$1(provider._context) + '.Provider'; 1407 1408 case DehydratedFragment: 1409 return 'DehydratedFragment'; 1410 1411 case ForwardRef: 1412 return getWrappedName$1(type, type.render, 'ForwardRef'); 1413 1414 case Fragment: 1415 return 'Fragment'; 1416 1417 case HostComponent: 1418 // Host component type is the display name (e.g. "div", "View") 1419 return type; 1420 1421 case HostPortal: 1422 return 'Portal'; 1423 1424 case HostRoot: 1425 return 'Root'; 1426 1427 case HostText: 1428 return 'Text'; 1429 1430 case LazyComponent: 1431 // Name comes from the type in this case; we don't have a tag. 1432 return getComponentNameFromType(type); 1433 1434 case Mode: 1435 if (type === REACT_STRICT_MODE_TYPE) { 1436 // Don't be less specific than shared/getComponentNameFromType 1437 return 'StrictMode'; 1438 } 1439 1440 return 'Mode'; 1441 1442 case OffscreenComponent: 1443 return 'Offscreen'; 1444 1445 case Profiler: 1446 return 'Profiler'; 1447 1448 case ScopeComponent: 1449 return 'Scope'; 1450 1451 case SuspenseComponent: 1452 return 'Suspense'; 1453 1454 case SuspenseListComponent: 1455 return 'SuspenseList'; 1456 1457 case TracingMarkerComponent: 1458 return 'TracingMarker'; 1459 // The display name for this tags come from the user-provided type: 1460 1461 case ClassComponent: 1462 case FunctionComponent: 1463 case IncompleteClassComponent: 1464 case IndeterminateComponent: 1465 case MemoComponent: 1466 case SimpleMemoComponent: 1467 if (typeof type === 'function') { 1468 return type.displayName || type.name || null; 1469 } 1470 1471 if (typeof type === 'string') { 1472 return type; 1473 } 1474 1475 break; 1476 1477 } 1478 1479 return null; 1480 } 1481 1482 var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; 1483 var current = null; 1484 var isRendering = false; 1485 function getCurrentFiberOwnerNameInDevOrNull() { 1486 { 1487 if (current === null) { 1488 return null; 1489 } 1490 1491 var owner = current._debugOwner; 1492 1493 if (owner !== null && typeof owner !== 'undefined') { 1494 return getComponentNameFromFiber(owner); 1495 } 1496 } 1497 1498 return null; 1499 } 1500 1501 function getCurrentFiberStackInDev() { 1502 { 1503 if (current === null) { 1504 return ''; 1505 } // Safe because if current fiber exists, we are reconciling, 1506 // and it is guaranteed to be the work-in-progress version. 1507 1508 1509 return getStackByFiberInDevAndProd(current); 1510 } 1511 } 1512 1513 function resetCurrentFiber() { 1514 { 1515 ReactDebugCurrentFrame.getCurrentStack = null; 1516 current = null; 1517 isRendering = false; 1518 } 1519 } 1520 function setCurrentFiber(fiber) { 1521 { 1522 ReactDebugCurrentFrame.getCurrentStack = fiber === null ? null : getCurrentFiberStackInDev; 1523 current = fiber; 1524 isRendering = false; 1525 } 1526 } 1527 function getCurrentFiber() { 1528 { 1529 return current; 1530 } 1531 } 1532 function setIsRendering(rendering) { 1533 { 1534 isRendering = rendering; 1535 } 1536 } 1537 1538 // Flow does not allow string concatenation of most non-string types. To work 1539 // around this limitation, we use an opaque type that can only be obtained by 1540 // passing the value through getToStringValue first. 1541 function toString(value) { 1542 // The coercion safety check is performed in getToStringValue(). 1543 // eslint-disable-next-line react-internal/safe-string-coercion 1544 return '' + value; 1545 } 1546 function getToStringValue(value) { 1547 switch (typeof value) { 1548 case 'boolean': 1549 case 'number': 1550 case 'string': 1551 case 'undefined': 1552 return value; 1553 1554 case 'object': 1555 { 1556 checkFormFieldValueStringCoercion(value); 1557 } 1558 1559 return value; 1560 1561 default: 1562 // function, symbol are assigned as empty strings 1563 return ''; 1564 } 1565 } 1566 1567 var hasReadOnlyValue = { 1568 button: true, 1569 checkbox: true, 1570 image: true, 1571 hidden: true, 1572 radio: true, 1573 reset: true, 1574 submit: true 1575 }; 1576 function checkControlledValueProps(tagName, props) { 1577 { 1578 if (!(hasReadOnlyValue[props.type] || props.onChange || props.onInput || props.readOnly || props.disabled || props.value == null)) { 1579 error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); 1580 } 1581 1582 if (!(props.onChange || props.readOnly || props.disabled || props.checked == null)) { 1583 error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); 1584 } 1585 } 1586 } 1587 1588 function isCheckable(elem) { 1589 var type = elem.type; 1590 var nodeName = elem.nodeName; 1591 return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio'); 1592 } 1593 1594 function getTracker(node) { 1595 return node._valueTracker; 1596 } 1597 1598 function detachTracker(node) { 1599 node._valueTracker = null; 1600 } 1601 1602 function getValueFromNode(node) { 1603 var value = ''; 1604 1605 if (!node) { 1606 return value; 1607 } 1608 1609 if (isCheckable(node)) { 1610 value = node.checked ? 'true' : 'false'; 1611 } else { 1612 value = node.value; 1613 } 1614 1615 return value; 1616 } 1617 1618 function trackValueOnNode(node) { 1619 var valueField = isCheckable(node) ? 'checked' : 'value'; 1620 var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField); 1621 1622 { 1623 checkFormFieldValueStringCoercion(node[valueField]); 1624 } 1625 1626 var currentValue = '' + node[valueField]; // if someone has already defined a value or Safari, then bail 1627 // and don't track value will cause over reporting of changes, 1628 // but it's better then a hard failure 1629 // (needed for certain tests that spyOn input values and Safari) 1630 1631 if (node.hasOwnProperty(valueField) || typeof descriptor === 'undefined' || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') { 1632 return; 1633 } 1634 1635 var get = descriptor.get, 1636 set = descriptor.set; 1637 Object.defineProperty(node, valueField, { 1638 configurable: true, 1639 get: function () { 1640 return get.call(this); 1641 }, 1642 set: function (value) { 1643 { 1644 checkFormFieldValueStringCoercion(value); 1645 } 1646 1647 currentValue = '' + value; 1648 set.call(this, value); 1649 } 1650 }); // We could've passed this the first time 1651 // but it triggers a bug in IE11 and Edge 14/15. 1652 // Calling defineProperty() again should be equivalent. 1653 // https://github.com/facebook/react/issues/11768 1654 1655 Object.defineProperty(node, valueField, { 1656 enumerable: descriptor.enumerable 1657 }); 1658 var tracker = { 1659 getValue: function () { 1660 return currentValue; 1661 }, 1662 setValue: function (value) { 1663 { 1664 checkFormFieldValueStringCoercion(value); 1665 } 1666 1667 currentValue = '' + value; 1668 }, 1669 stopTracking: function () { 1670 detachTracker(node); 1671 delete node[valueField]; 1672 } 1673 }; 1674 return tracker; 1675 } 1676 1677 function track(node) { 1678 if (getTracker(node)) { 1679 return; 1680 } // TODO: Once it's just Fiber we can move this to node._wrapperState 1681 1682 1683 node._valueTracker = trackValueOnNode(node); 1684 } 1685 function updateValueIfChanged(node) { 1686 if (!node) { 1687 return false; 1688 } 1689 1690 var tracker = getTracker(node); // if there is no tracker at this point it's unlikely 1691 // that trying again will succeed 1692 1693 if (!tracker) { 1694 return true; 1695 } 1696 1697 var lastValue = tracker.getValue(); 1698 var nextValue = getValueFromNode(node); 1699 1700 if (nextValue !== lastValue) { 1701 tracker.setValue(nextValue); 1702 return true; 1703 } 1704 1705 return false; 1706 } 1707 1708 function getActiveElement(doc) { 1709 doc = doc || (typeof document !== 'undefined' ? document : undefined); 1710 1711 if (typeof doc === 'undefined') { 1712 return null; 1713 } 1714 1715 try { 1716 return doc.activeElement || doc.body; 1717 } catch (e) { 1718 return doc.body; 1719 } 1720 } 1721 1722 var didWarnValueDefaultValue = false; 1723 var didWarnCheckedDefaultChecked = false; 1724 var didWarnControlledToUncontrolled = false; 1725 var didWarnUncontrolledToControlled = false; 1726 1727 function isControlled(props) { 1728 var usesChecked = props.type === 'checkbox' || props.type === 'radio'; 1729 return usesChecked ? props.checked != null : props.value != null; 1730 } 1731 /** 1732 * Implements an <input> host component that allows setting these optional 1733 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. 1734 * 1735 * If `checked` or `value` are not supplied (or null/undefined), user actions 1736 * that affect the checked state or value will trigger updates to the element. 1737 * 1738 * If they are supplied (and not null/undefined), the rendered element will not 1739 * trigger updates to the element. Instead, the props must change in order for 1740 * the rendered element to be updated. 1741 * 1742 * The rendered element will be initialized as unchecked (or `defaultChecked`) 1743 * with an empty value (or `defaultValue`). 1744 * 1745 * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html 1746 */ 1747 1748 1749 function getHostProps(element, props) { 1750 var node = element; 1751 var checked = props.checked; 1752 var hostProps = assign({}, props, { 1753 defaultChecked: undefined, 1754 defaultValue: undefined, 1755 value: undefined, 1756 checked: checked != null ? checked : node._wrapperState.initialChecked 1757 }); 1758 return hostProps; 1759 } 1760 function initWrapperState(element, props) { 1761 { 1762 checkControlledValueProps('input', props); 1763 1764 if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) { 1765 error('%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component', props.type); 1766 1767 didWarnCheckedDefaultChecked = true; 1768 } 1769 1770 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) { 1771 error('%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component', props.type); 1772 1773 didWarnValueDefaultValue = true; 1774 } 1775 } 1776 1777 var node = element; 1778 var defaultValue = props.defaultValue == null ? '' : props.defaultValue; 1779 node._wrapperState = { 1780 initialChecked: props.checked != null ? props.checked : props.defaultChecked, 1781 initialValue: getToStringValue(props.value != null ? props.value : defaultValue), 1782 controlled: isControlled(props) 1783 }; 1784 } 1785 function updateChecked(element, props) { 1786 var node = element; 1787 var checked = props.checked; 1788 1789 if (checked != null) { 1790 setValueForProperty(node, 'checked', checked, false); 1791 } 1792 } 1793 function updateWrapper(element, props) { 1794 var node = element; 1795 1796 { 1797 var controlled = isControlled(props); 1798 1799 if (!node._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) { 1800 error('A component is changing an uncontrolled input to be controlled. ' + 'This is likely caused by the value changing from undefined to ' + 'a defined value, which should not happen. ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components'); 1801 1802 didWarnUncontrolledToControlled = true; 1803 } 1804 1805 if (node._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) { 1806 error('A component is changing a controlled input to be uncontrolled. ' + 'This is likely caused by the value changing from a defined to ' + 'undefined, which should not happen. ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components'); 1807 1808 didWarnControlledToUncontrolled = true; 1809 } 1810 } 1811 1812 updateChecked(element, props); 1813 var value = getToStringValue(props.value); 1814 var type = props.type; 1815 1816 if (value != null) { 1817 if (type === 'number') { 1818 if (value === 0 && node.value === '' || // We explicitly want to coerce to number here if possible. 1819 // eslint-disable-next-line 1820 node.value != value) { 1821 node.value = toString(value); 1822 } 1823 } else if (node.value !== toString(value)) { 1824 node.value = toString(value); 1825 } 1826 } else if (type === 'submit' || type === 'reset') { 1827 // Submit/reset inputs need the attribute removed completely to avoid 1828 // blank-text buttons. 1829 node.removeAttribute('value'); 1830 return; 1831 } 1832 1833 { 1834 // When syncing the value attribute, the value comes from a cascade of 1835 // properties: 1836 // 1. The value React property 1837 // 2. The defaultValue React property 1838 // 3. Otherwise there should be no change 1839 if (props.hasOwnProperty('value')) { 1840 setDefaultValue(node, props.type, value); 1841 } else if (props.hasOwnProperty('defaultValue')) { 1842 setDefaultValue(node, props.type, getToStringValue(props.defaultValue)); 1843 } 1844 } 1845 1846 { 1847 // When syncing the checked attribute, it only changes when it needs 1848 // to be removed, such as transitioning from a checkbox into a text input 1849 if (props.checked == null && props.defaultChecked != null) { 1850 node.defaultChecked = !!props.defaultChecked; 1851 } 1852 } 1853 } 1854 function postMountWrapper(element, props, isHydrating) { 1855 var node = element; // Do not assign value if it is already set. This prevents user text input 1856 // from being lost during SSR hydration. 1857 1858 if (props.hasOwnProperty('value') || props.hasOwnProperty('defaultValue')) { 1859 var type = props.type; 1860 var isButton = type === 'submit' || type === 'reset'; // Avoid setting value attribute on submit/reset inputs as it overrides the 1861 // default value provided by the browser. See: #12872 1862 1863 if (isButton && (props.value === undefined || props.value === null)) { 1864 return; 1865 } 1866 1867 var initialValue = toString(node._wrapperState.initialValue); // Do not assign value if it is already set. This prevents user text input 1868 // from being lost during SSR hydration. 1869 1870 if (!isHydrating) { 1871 { 1872 // When syncing the value attribute, the value property should use 1873 // the wrapperState._initialValue property. This uses: 1874 // 1875 // 1. The value React property when present 1876 // 2. The defaultValue React property when present 1877 // 3. An empty string 1878 if (initialValue !== node.value) { 1879 node.value = initialValue; 1880 } 1881 } 1882 } 1883 1884 { 1885 // Otherwise, the value attribute is synchronized to the property, 1886 // so we assign defaultValue to the same thing as the value property 1887 // assignment step above. 1888 node.defaultValue = initialValue; 1889 } 1890 } // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug 1891 // this is needed to work around a chrome bug where setting defaultChecked 1892 // will sometimes influence the value of checked (even after detachment). 1893 // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416 1894 // We need to temporarily unset name to avoid disrupting radio button groups. 1895 1896 1897 var name = node.name; 1898 1899 if (name !== '') { 1900 node.name = ''; 1901 } 1902 1903 { 1904 // When syncing the checked attribute, both the checked property and 1905 // attribute are assigned at the same time using defaultChecked. This uses: 1906 // 1907 // 1. The checked React property when present 1908 // 2. The defaultChecked React property when present 1909 // 3. Otherwise, false 1910 node.defaultChecked = !node.defaultChecked; 1911 node.defaultChecked = !!node._wrapperState.initialChecked; 1912 } 1913 1914 if (name !== '') { 1915 node.name = name; 1916 } 1917 } 1918 function restoreControlledState(element, props) { 1919 var node = element; 1920 updateWrapper(node, props); 1921 updateNamedCousins(node, props); 1922 } 1923 1924 function updateNamedCousins(rootNode, props) { 1925 var name = props.name; 1926 1927 if (props.type === 'radio' && name != null) { 1928 var queryRoot = rootNode; 1929 1930 while (queryRoot.parentNode) { 1931 queryRoot = queryRoot.parentNode; 1932 } // If `rootNode.form` was non-null, then we could try `form.elements`, 1933 // but that sometimes behaves strangely in IE8. We could also try using 1934 // `form.getElementsByName`, but that will only return direct children 1935 // and won't include inputs that use the HTML5 `form=` attribute. Since 1936 // the input might not even be in a form. It might not even be in the 1937 // document. Let's just use the local `querySelectorAll` to ensure we don't 1938 // miss anything. 1939 1940 1941 { 1942 checkAttributeStringCoercion(name, 'name'); 1943 } 1944 1945 var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type="radio"]'); 1946 1947 for (var i = 0; i < group.length; i++) { 1948 var otherNode = group[i]; 1949 1950 if (otherNode === rootNode || otherNode.form !== rootNode.form) { 1951 continue; 1952 } // This will throw if radio buttons rendered by different copies of React 1953 // and the same name are rendered into the same form (same as #1939). 1954 // That's probably okay; we don't support it just as we don't support 1955 // mixing React radio buttons with non-React ones. 1956 1957 1958 var otherProps = getFiberCurrentPropsFromNode(otherNode); 1959 1960 if (!otherProps) { 1961 throw new Error('ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.'); 1962 } // We need update the tracked value on the named cousin since the value 1963 // was changed but the input saw no event or value set 1964 1965 1966 updateValueIfChanged(otherNode); // If this is a controlled radio button group, forcing the input that 1967 // was previously checked to update will cause it to be come re-checked 1968 // as appropriate. 1969 1970 updateWrapper(otherNode, otherProps); 1971 } 1972 } 1973 } // In Chrome, assigning defaultValue to certain input types triggers input validation. 1974 // For number inputs, the display value loses trailing decimal points. For email inputs, 1975 // Chrome raises "The specified value <x> is not a valid email address". 1976 // 1977 // Here we check to see if the defaultValue has actually changed, avoiding these problems 1978 // when the user is inputting text 1979 // 1980 // https://github.com/facebook/react/issues/7253 1981 1982 1983 function setDefaultValue(node, type, value) { 1984 if ( // Focused number inputs synchronize on blur. See ChangeEventPlugin.js 1985 type !== 'number' || getActiveElement(node.ownerDocument) !== node) { 1986 if (value == null) { 1987 node.defaultValue = toString(node._wrapperState.initialValue); 1988 } else if (node.defaultValue !== toString(value)) { 1989 node.defaultValue = toString(value); 1990 } 1991 } 1992 } 1993 1994 var didWarnSelectedSetOnOption = false; 1995 var didWarnInvalidChild = false; 1996 var didWarnInvalidInnerHTML = false; 1997 /** 1998 * Implements an <option> host component that warns when `selected` is set. 1999 */ 2000 2001 function validateProps(element, props) { 2002 { 2003 // If a value is not provided, then the children must be simple. 2004 if (props.value == null) { 2005 if (typeof props.children === 'object' && props.children !== null) { 2006 React.Children.forEach(props.children, function (child) { 2007 if (child == null) { 2008 return; 2009 } 2010 2011 if (typeof child === 'string' || typeof child === 'number') { 2012 return; 2013 } 2014 2015 if (!didWarnInvalidChild) { 2016 didWarnInvalidChild = true; 2017 2018 error('Cannot infer the option value of complex children. ' + 'Pass a `value` prop or use a plain string as children to <option>.'); 2019 } 2020 }); 2021 } else if (props.dangerouslySetInnerHTML != null) { 2022 if (!didWarnInvalidInnerHTML) { 2023 didWarnInvalidInnerHTML = true; 2024 2025 error('Pass a `value` prop if you set dangerouslyInnerHTML so React knows ' + 'which value should be selected.'); 2026 } 2027 } 2028 } // TODO: Remove support for `selected` in <option>. 2029 2030 2031 if (props.selected != null && !didWarnSelectedSetOnOption) { 2032 error('Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.'); 2033 2034 didWarnSelectedSetOnOption = true; 2035 } 2036 } 2037 } 2038 function postMountWrapper$1(element, props) { 2039 // value="" should make a value attribute (#6219) 2040 if (props.value != null) { 2041 element.setAttribute('value', toString(getToStringValue(props.value))); 2042 } 2043 } 2044 2045 var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare 2046 2047 function isArray(a) { 2048 return isArrayImpl(a); 2049 } 2050 2051 var didWarnValueDefaultValue$1; 2052 2053 { 2054 didWarnValueDefaultValue$1 = false; 2055 } 2056 2057 function getDeclarationErrorAddendum() { 2058 var ownerName = getCurrentFiberOwnerNameInDevOrNull(); 2059 2060 if (ownerName) { 2061 return '\n\nCheck the render method of `' + ownerName + '`.'; 2062 } 2063 2064 return ''; 2065 } 2066 2067 var valuePropNames = ['value', 'defaultValue']; 2068 /** 2069 * Validation function for `value` and `defaultValue`. 2070 */ 2071 2072 function checkSelectPropTypes(props) { 2073 { 2074 checkControlledValueProps('select', props); 2075 2076 for (var i = 0; i < valuePropNames.length; i++) { 2077 var propName = valuePropNames[i]; 2078 2079 if (props[propName] == null) { 2080 continue; 2081 } 2082 2083 var propNameIsArray = isArray(props[propName]); 2084 2085 if (props.multiple && !propNameIsArray) { 2086 error('The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum()); 2087 } else if (!props.multiple && propNameIsArray) { 2088 error('The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum()); 2089 } 2090 } 2091 } 2092 } 2093 2094 function updateOptions(node, multiple, propValue, setDefaultSelected) { 2095 var options = node.options; 2096 2097 if (multiple) { 2098 var selectedValues = propValue; 2099 var selectedValue = {}; 2100 2101 for (var i = 0; i < selectedValues.length; i++) { 2102 // Prefix to avoid chaos with special keys. 2103 selectedValue['$' + selectedValues[i]] = true; 2104 } 2105 2106 for (var _i = 0; _i < options.length; _i++) { 2107 var selected = selectedValue.hasOwnProperty('$' + options[_i].value); 2108 2109 if (options[_i].selected !== selected) { 2110 options[_i].selected = selected; 2111 } 2112 2113 if (selected && setDefaultSelected) { 2114 options[_i].defaultSelected = true; 2115 } 2116 } 2117 } else { 2118 // Do not set `select.value` as exact behavior isn't consistent across all 2119 // browsers for all cases. 2120 var _selectedValue = toString(getToStringValue(propValue)); 2121 2122 var defaultSelected = null; 2123 2124 for (var _i2 = 0; _i2 < options.length; _i2++) { 2125 if (options[_i2].value === _selectedValue) { 2126 options[_i2].selected = true; 2127 2128 if (setDefaultSelected) { 2129 options[_i2].defaultSelected = true; 2130 } 2131 2132 return; 2133 } 2134 2135 if (defaultSelected === null && !options[_i2].disabled) { 2136 defaultSelected = options[_i2]; 2137 } 2138 } 2139 2140 if (defaultSelected !== null) { 2141 defaultSelected.selected = true; 2142 } 2143 } 2144 } 2145 /** 2146 * Implements a <select> host component that allows optionally setting the 2147 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a 2148 * stringable. If `multiple` is true, the prop must be an array of stringables. 2149 * 2150 * If `value` is not supplied (or null/undefined), user actions that change the 2151 * selected option will trigger updates to the rendered options. 2152 * 2153 * If it is supplied (and not null/undefined), the rendered options will not 2154 * update in response to user actions. Instead, the `value` prop must change in 2155 * order for the rendered options to update. 2156 * 2157 * If `defaultValue` is provided, any options with the supplied values will be 2158 * selected. 2159 */ 2160 2161 2162 function getHostProps$1(element, props) { 2163 return assign({}, props, { 2164 value: undefined 2165 }); 2166 } 2167 function initWrapperState$1(element, props) { 2168 var node = element; 2169 2170 { 2171 checkSelectPropTypes(props); 2172 } 2173 2174 node._wrapperState = { 2175 wasMultiple: !!props.multiple 2176 }; 2177 2178 { 2179 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1) { 2180 error('Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components'); 2181 2182 didWarnValueDefaultValue$1 = true; 2183 } 2184 } 2185 } 2186 function postMountWrapper$2(element, props) { 2187 var node = element; 2188 node.multiple = !!props.multiple; 2189 var value = props.value; 2190 2191 if (value != null) { 2192 updateOptions(node, !!props.multiple, value, false); 2193 } else if (props.defaultValue != null) { 2194 updateOptions(node, !!props.multiple, props.defaultValue, true); 2195 } 2196 } 2197 function postUpdateWrapper(element, props) { 2198 var node = element; 2199 var wasMultiple = node._wrapperState.wasMultiple; 2200 node._wrapperState.wasMultiple = !!props.multiple; 2201 var value = props.value; 2202 2203 if (value != null) { 2204 updateOptions(node, !!props.multiple, value, false); 2205 } else if (wasMultiple !== !!props.multiple) { 2206 // For simplicity, reapply `defaultValue` if `multiple` is toggled. 2207 if (props.defaultValue != null) { 2208 updateOptions(node, !!props.multiple, props.defaultValue, true); 2209 } else { 2210 // Revert the select back to its default unselected state. 2211 updateOptions(node, !!props.multiple, props.multiple ? [] : '', false); 2212 } 2213 } 2214 } 2215 function restoreControlledState$1(element, props) { 2216 var node = element; 2217 var value = props.value; 2218 2219 if (value != null) { 2220 updateOptions(node, !!props.multiple, value, false); 2221 } 2222 } 2223 2224 var didWarnValDefaultVal = false; 2225 2226 /** 2227 * Implements a <textarea> host component that allows setting `value`, and 2228 * `defaultValue`. This differs from the traditional DOM API because value is 2229 * usually set as PCDATA children. 2230 * 2231 * If `value` is not supplied (or null/undefined), user actions that affect the 2232 * value will trigger updates to the element. 2233 * 2234 * If `value` is supplied (and not null/undefined), the rendered element will 2235 * not trigger updates to the element. Instead, the `value` prop must change in 2236 * order for the rendered element to be updated. 2237 * 2238 * The rendered element will be initialized with an empty value, the prop 2239 * `defaultValue` if specified, or the children content (deprecated). 2240 */ 2241 function getHostProps$2(element, props) { 2242 var node = element; 2243 2244 if (props.dangerouslySetInnerHTML != null) { 2245 throw new Error('`dangerouslySetInnerHTML` does not make sense on <textarea>.'); 2246 } // Always set children to the same thing. In IE9, the selection range will 2247 // get reset if `textContent` is mutated. We could add a check in setTextContent 2248 // to only set the value if/when the value differs from the node value (which would 2249 // completely solve this IE9 bug), but Sebastian+Sophie seemed to like this 2250 // solution. The value can be a boolean or object so that's why it's forced 2251 // to be a string. 2252 2253 2254 var hostProps = assign({}, props, { 2255 value: undefined, 2256 defaultValue: undefined, 2257 children: toString(node._wrapperState.initialValue) 2258 }); 2259 2260 return hostProps; 2261 } 2262 function initWrapperState$2(element, props) { 2263 var node = element; 2264 2265 { 2266 checkControlledValueProps('textarea', props); 2267 2268 if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) { 2269 error('%s contains a textarea with both value and defaultValue props. ' + 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://reactjs.org/link/controlled-components', getCurrentFiberOwnerNameInDevOrNull() || 'A component'); 2270 2271 didWarnValDefaultVal = true; 2272 } 2273 } 2274 2275 var initialValue = props.value; // Only bother fetching default value if we're going to use it 2276 2277 if (initialValue == null) { 2278 var children = props.children, 2279 defaultValue = props.defaultValue; 2280 2281 if (children != null) { 2282 { 2283 error('Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.'); 2284 } 2285 2286 { 2287 if (defaultValue != null) { 2288 throw new Error('If you supply `defaultValue` on a <textarea>, do not pass children.'); 2289 } 2290 2291 if (isArray(children)) { 2292 if (children.length > 1) { 2293 throw new Error('<textarea> can only have at most one child.'); 2294 } 2295 2296 children = children[0]; 2297 } 2298 2299 defaultValue = children; 2300 } 2301 } 2302 2303 if (defaultValue == null) { 2304 defaultValue = ''; 2305 } 2306 2307 initialValue = defaultValue; 2308 } 2309 2310 node._wrapperState = { 2311 initialValue: getToStringValue(initialValue) 2312 }; 2313 } 2314 function updateWrapper$1(element, props) { 2315 var node = element; 2316 var value = getToStringValue(props.value); 2317 var defaultValue = getToStringValue(props.defaultValue); 2318 2319 if (value != null) { 2320 // Cast `value` to a string to ensure the value is set correctly. While 2321 // browsers typically do this as necessary, jsdom doesn't. 2322 var newValue = toString(value); // To avoid side effects (such as losing text selection), only set value if changed 2323 2324 if (newValue !== node.value) { 2325 node.value = newValue; 2326 } 2327 2328 if (props.defaultValue == null && node.defaultValue !== newValue) { 2329 node.defaultValue = newValue; 2330 } 2331 } 2332 2333 if (defaultValue != null) { 2334 node.defaultValue = toString(defaultValue); 2335 } 2336 } 2337 function postMountWrapper$3(element, props) { 2338 var node = element; // This is in postMount because we need access to the DOM node, which is not 2339 // available until after the component has mounted. 2340 2341 var textContent = node.textContent; // Only set node.value if textContent is equal to the expected 2342 // initial value. In IE10/IE11 there is a bug where the placeholder attribute 2343 // will populate textContent as well. 2344 // https://developer.microsoft.com/microsoft-edge/platform/issues/101525/ 2345 2346 if (textContent === node._wrapperState.initialValue) { 2347 if (textContent !== '' && textContent !== null) { 2348 node.value = textContent; 2349 } 2350 } 2351 } 2352 function restoreControlledState$2(element, props) { 2353 // DOM component is still mounted; update 2354 updateWrapper$1(element, props); 2355 } 2356 2357 var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; 2358 var MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML'; 2359 var SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; // Assumes there is no parent namespace. 2360 2361 function getIntrinsicNamespace(type) { 2362 switch (type) { 2363 case 'svg': 2364 return SVG_NAMESPACE; 2365 2366 case 'math': 2367 return MATH_NAMESPACE; 2368 2369 default: 2370 return HTML_NAMESPACE; 2371 } 2372 } 2373 function getChildNamespace(parentNamespace, type) { 2374 if (parentNamespace == null || parentNamespace === HTML_NAMESPACE) { 2375 // No (or default) parent namespace: potential entry point. 2376 return getIntrinsicNamespace(type); 2377 } 2378 2379 if (parentNamespace === SVG_NAMESPACE && type === 'foreignObject') { 2380 // We're leaving SVG. 2381 return HTML_NAMESPACE; 2382 } // By default, pass namespace below. 2383 2384 2385 return parentNamespace; 2386 } 2387 2388 /* globals MSApp */ 2389 2390 /** 2391 * Create a function which has 'unsafe' privileges (required by windows8 apps) 2392 */ 2393 var createMicrosoftUnsafeLocalFunction = function (func) { 2394 if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) { 2395 return function (arg0, arg1, arg2, arg3) { 2396 MSApp.execUnsafeLocalFunction(function () { 2397 return func(arg0, arg1, arg2, arg3); 2398 }); 2399 }; 2400 } else { 2401 return func; 2402 } 2403 }; 2404 2405 var reusableSVGContainer; 2406 /** 2407 * Set the innerHTML property of a node 2408 * 2409 * @param {DOMElement} node 2410 * @param {string} html 2411 * @internal 2412 */ 2413 2414 var setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) { 2415 if (node.namespaceURI === SVG_NAMESPACE) { 2416 2417 if (!('innerHTML' in node)) { 2418 // IE does not have innerHTML for SVG nodes, so instead we inject the 2419 // new markup in a temp node and then move the child nodes across into 2420 // the target node 2421 reusableSVGContainer = reusableSVGContainer || document.createElement('div'); 2422 reusableSVGContainer.innerHTML = '<svg>' + html.valueOf().toString() + '</svg>'; 2423 var svgNode = reusableSVGContainer.firstChild; 2424 2425 while (node.firstChild) { 2426 node.removeChild(node.firstChild); 2427 } 2428 2429 while (svgNode.firstChild) { 2430 node.appendChild(svgNode.firstChild); 2431 } 2432 2433 return; 2434 } 2435 } 2436 2437 node.innerHTML = html; 2438 }); 2439 2440 /** 2441 * HTML nodeType values that represent the type of the node 2442 */ 2443 var ELEMENT_NODE = 1; 2444 var TEXT_NODE = 3; 2445 var COMMENT_NODE = 8; 2446 var DOCUMENT_NODE = 9; 2447 var DOCUMENT_FRAGMENT_NODE = 11; 2448 2449 /** 2450 * Set the textContent property of a node. For text updates, it's faster 2451 * to set the `nodeValue` of the Text node directly instead of using 2452 * `.textContent` which will remove the existing node and create a new one. 2453 * 2454 * @param {DOMElement} node 2455 * @param {string} text 2456 * @internal 2457 */ 2458 2459 var setTextContent = function (node, text) { 2460 if (text) { 2461 var firstChild = node.firstChild; 2462 2463 if (firstChild && firstChild === node.lastChild && firstChild.nodeType === TEXT_NODE) { 2464 firstChild.nodeValue = text; 2465 return; 2466 } 2467 } 2468 2469 node.textContent = text; 2470 }; 2471 2472 // List derived from Gecko source code: 2473 // https://github.com/mozilla/gecko-dev/blob/4e638efc71/layout/style/test/property_database.js 2474 var shorthandToLonghand = { 2475 animation: ['animationDelay', 'animationDirection', 'animationDuration', 'animationFillMode', 'animationIterationCount', 'animationName', 'animationPlayState', 'animationTimingFunction'], 2476 background: ['backgroundAttachment', 'backgroundClip', 'backgroundColor', 'backgroundImage', 'backgroundOrigin', 'backgroundPositionX', 'backgroundPositionY', 'backgroundRepeat', 'backgroundSize'], 2477 backgroundPosition: ['backgroundPositionX', 'backgroundPositionY'], 2478 border: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth', 'borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth', 'borderLeftColor', 'borderLeftStyle', 'borderLeftWidth', 'borderRightColor', 'borderRightStyle', 'borderRightWidth', 'borderTopColor', 'borderTopStyle', 'borderTopWidth'], 2479 borderBlockEnd: ['borderBlockEndColor', 'borderBlockEndStyle', 'borderBlockEndWidth'], 2480 borderBlockStart: ['borderBlockStartColor', 'borderBlockStartStyle', 'borderBlockStartWidth'], 2481 borderBottom: ['borderBottomColor', 'borderBottomStyle', 'borderBottomWidth'], 2482 borderColor: ['borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor'], 2483 borderImage: ['borderImageOutset', 'borderImageRepeat', 'borderImageSlice', 'borderImageSource', 'borderImageWidth'], 2484 borderInlineEnd: ['borderInlineEndColor', 'borderInlineEndStyle', 'borderInlineEndWidth'], 2485 borderInlineStart: ['borderInlineStartColor', 'borderInlineStartStyle', 'borderInlineStartWidth'], 2486 borderLeft: ['borderLeftColor', 'borderLeftStyle', 'borderLeftWidth'], 2487 borderRadius: ['borderBottomLeftRadius', 'borderBottomRightRadius', 'borderTopLeftRadius', 'borderTopRightRadius'], 2488 borderRight: ['borderRightColor', 'borderRightStyle', 'borderRightWidth'], 2489 borderStyle: ['borderBottomStyle', 'borderLeftStyle', 'borderRightStyle', 'borderTopStyle'], 2490 borderTop: ['borderTopColor', 'borderTopStyle', 'borderTopWidth'], 2491 borderWidth: ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth', 'borderTopWidth'], 2492 columnRule: ['columnRuleColor', 'columnRuleStyle', 'columnRuleWidth'], 2493 columns: ['columnCount', 'columnWidth'], 2494 flex: ['flexBasis', 'flexGrow', 'flexShrink'], 2495 flexFlow: ['flexDirection', 'flexWrap'], 2496 font: ['fontFamily', 'fontFeatureSettings', 'fontKerning', 'fontLanguageOverride', 'fontSize', 'fontSizeAdjust', 'fontStretch', 'fontStyle', 'fontVariant', 'fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition', 'fontWeight', 'lineHeight'], 2497 fontVariant: ['fontVariantAlternates', 'fontVariantCaps', 'fontVariantEastAsian', 'fontVariantLigatures', 'fontVariantNumeric', 'fontVariantPosition'], 2498 gap: ['columnGap', 'rowGap'], 2499 grid: ['gridAutoColumns', 'gridAutoFlow', 'gridAutoRows', 'gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'], 2500 gridArea: ['gridColumnEnd', 'gridColumnStart', 'gridRowEnd', 'gridRowStart'], 2501 gridColumn: ['gridColumnEnd', 'gridColumnStart'], 2502 gridColumnGap: ['columnGap'], 2503 gridGap: ['columnGap', 'rowGap'], 2504 gridRow: ['gridRowEnd', 'gridRowStart'], 2505 gridRowGap: ['rowGap'], 2506 gridTemplate: ['gridTemplateAreas', 'gridTemplateColumns', 'gridTemplateRows'], 2507 listStyle: ['listStyleImage', 'listStylePosition', 'listStyleType'], 2508 margin: ['marginBottom', 'marginLeft', 'marginRight', 'marginTop'], 2509 marker: ['markerEnd', 'markerMid', 'markerStart'], 2510 mask: ['maskClip', 'maskComposite', 'maskImage', 'maskMode', 'maskOrigin', 'maskPositionX', 'maskPositionY', 'maskRepeat', 'maskSize'], 2511 maskPosition: ['maskPositionX', 'maskPositionY'], 2512 outline: ['outlineColor', 'outlineStyle', 'outlineWidth'], 2513 overflow: ['overflowX', 'overflowY'], 2514 padding: ['paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop'], 2515 placeContent: ['alignContent', 'justifyContent'], 2516 placeItems: ['alignItems', 'justifyItems'], 2517 placeSelf: ['alignSelf', 'justifySelf'], 2518 textDecoration: ['textDecorationColor', 'textDecorationLine', 'textDecorationStyle'], 2519 textEmphasis: ['textEmphasisColor', 'textEmphasisStyle'], 2520 transition: ['transitionDelay', 'transitionDuration', 'transitionProperty', 'transitionTimingFunction'], 2521 wordWrap: ['overflowWrap'] 2522 }; 2523 2524 /** 2525 * CSS properties which accept numbers but are not in units of "px". 2526 */ 2527 var isUnitlessNumber = { 2528 animationIterationCount: true, 2529 aspectRatio: true, 2530 borderImageOutset: true, 2531 borderImageSlice: true, 2532 borderImageWidth: true, 2533 boxFlex: true, 2534 boxFlexGroup: true, 2535 boxOrdinalGroup: true, 2536 columnCount: true, 2537 columns: true, 2538 flex: true, 2539 flexGrow: true, 2540 flexPositive: true, 2541 flexShrink: true, 2542 flexNegative: true, 2543 flexOrder: true, 2544 gridArea: true, 2545 gridRow: true, 2546 gridRowEnd: true, 2547 gridRowSpan: true, 2548 gridRowStart: true, 2549 gridColumn: true, 2550 gridColumnEnd: true, 2551 gridColumnSpan: true, 2552 gridColumnStart: true, 2553 fontWeight: true, 2554 lineClamp: true, 2555 lineHeight: true, 2556 opacity: true, 2557 order: true, 2558 orphans: true, 2559 tabSize: true, 2560 widows: true, 2561 zIndex: true, 2562 zoom: true, 2563 // SVG-related properties 2564 fillOpacity: true, 2565 floodOpacity: true, 2566 stopOpacity: true, 2567 strokeDasharray: true, 2568 strokeDashoffset: true, 2569 strokeMiterlimit: true, 2570 strokeOpacity: true, 2571 strokeWidth: true 2572 }; 2573 /** 2574 * @param {string} prefix vendor-specific prefix, eg: Webkit 2575 * @param {string} key style name, eg: transitionDuration 2576 * @return {string} style name prefixed with `prefix`, properly camelCased, eg: 2577 * WebkitTransitionDuration 2578 */ 2579 2580 function prefixKey(prefix, key) { 2581 return prefix + key.charAt(0).toUpperCase() + key.substring(1); 2582 } 2583 /** 2584 * Support style names that may come passed in prefixed by adding permutations 2585 * of vendor prefixes. 2586 */ 2587 2588 2589 var prefixes = ['Webkit', 'ms', 'Moz', 'O']; // Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an 2590 // infinite loop, because it iterates over the newly added props too. 2591 2592 Object.keys(isUnitlessNumber).forEach(function (prop) { 2593 prefixes.forEach(function (prefix) { 2594 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; 2595 }); 2596 }); 2597 2598 /** 2599 * Convert a value into the proper css writable value. The style name `name` 2600 * should be logical (no hyphens), as specified 2601 * in `CSSProperty.isUnitlessNumber`. 2602 * 2603 * @param {string} name CSS property name such as `topMargin`. 2604 * @param {*} value CSS property value such as `10px`. 2605 * @return {string} Normalized style value with dimensions applied. 2606 */ 2607 2608 function dangerousStyleValue(name, value, isCustomProperty) { 2609 // Note that we've removed escapeTextForBrowser() calls here since the 2610 // whole string will be escaped when the attribute is injected into 2611 // the markup. If you provide unsafe user data here they can inject 2612 // arbitrary CSS which may be problematic (I couldn't repro this): 2613 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet 2614 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/ 2615 // This is not an XSS hole but instead a potential CSS injection issue 2616 // which has lead to a greater discussion about how we're going to 2617 // trust URLs moving forward. See #2115901 2618 var isEmpty = value == null || typeof value === 'boolean' || value === ''; 2619 2620 if (isEmpty) { 2621 return ''; 2622 } 2623 2624 if (!isCustomProperty && typeof value === 'number' && value !== 0 && !(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])) { 2625 return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers 2626 } 2627 2628 { 2629 checkCSSPropertyStringCoercion(value, name); 2630 } 2631 2632 return ('' + value).trim(); 2633 } 2634 2635 var uppercasePattern = /([A-Z])/g; 2636 var msPattern = /^ms-/; 2637 /** 2638 * Hyphenates a camelcased CSS property name, for example: 2639 * 2640 * > hyphenateStyleName('backgroundColor') 2641 * < "background-color" 2642 * > hyphenateStyleName('MozTransition') 2643 * < "-moz-transition" 2644 * > hyphenateStyleName('msTransition') 2645 * < "-ms-transition" 2646 * 2647 * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix 2648 * is converted to `-ms-`. 2649 */ 2650 2651 function hyphenateStyleName(name) { 2652 return name.replace(uppercasePattern, '-$1').toLowerCase().replace(msPattern, '-ms-'); 2653 } 2654 2655 var warnValidStyle = function () {}; 2656 2657 { 2658 // 'msTransform' is correct, but the other prefixes should be capitalized 2659 var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/; 2660 var msPattern$1 = /^-ms-/; 2661 var hyphenPattern = /-(.)/g; // style values shouldn't contain a semicolon 2662 2663 var badStyleValueWithSemicolonPattern = /;\s*$/; 2664 var warnedStyleNames = {}; 2665 var warnedStyleValues = {}; 2666 var warnedForNaNValue = false; 2667 var warnedForInfinityValue = false; 2668 2669 var camelize = function (string) { 2670 return string.replace(hyphenPattern, function (_, character) { 2671 return character.toUpperCase(); 2672 }); 2673 }; 2674 2675 var warnHyphenatedStyleName = function (name) { 2676 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { 2677 return; 2678 } 2679 2680 warnedStyleNames[name] = true; 2681 2682 error('Unsupported style property %s. Did you mean %s?', name, // As Andi Smith suggests 2683 // (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix 2684 // is converted to lowercase `ms`. 2685 camelize(name.replace(msPattern$1, 'ms-'))); 2686 }; 2687 2688 var warnBadVendoredStyleName = function (name) { 2689 if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { 2690 return; 2691 } 2692 2693 warnedStyleNames[name] = true; 2694 2695 error('Unsupported vendor-prefixed style property %s. Did you mean %s?', name, name.charAt(0).toUpperCase() + name.slice(1)); 2696 }; 2697 2698 var warnStyleValueWithSemicolon = function (name, value) { 2699 if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) { 2700 return; 2701 } 2702 2703 warnedStyleValues[value] = true; 2704 2705 error("Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.', name, value.replace(badStyleValueWithSemicolonPattern, '')); 2706 }; 2707 2708 var warnStyleValueIsNaN = function (name, value) { 2709 if (warnedForNaNValue) { 2710 return; 2711 } 2712 2713 warnedForNaNValue = true; 2714 2715 error('`NaN` is an invalid value for the `%s` css style property.', name); 2716 }; 2717 2718 var warnStyleValueIsInfinity = function (name, value) { 2719 if (warnedForInfinityValue) { 2720 return; 2721 } 2722 2723 warnedForInfinityValue = true; 2724 2725 error('`Infinity` is an invalid value for the `%s` css style property.', name); 2726 }; 2727 2728 warnValidStyle = function (name, value) { 2729 if (name.indexOf('-') > -1) { 2730 warnHyphenatedStyleName(name); 2731 } else if (badVendoredStyleNamePattern.test(name)) { 2732 warnBadVendoredStyleName(name); 2733 } else if (badStyleValueWithSemicolonPattern.test(value)) { 2734 warnStyleValueWithSemicolon(name, value); 2735 } 2736 2737 if (typeof value === 'number') { 2738 if (isNaN(value)) { 2739 warnStyleValueIsNaN(name, value); 2740 } else if (!isFinite(value)) { 2741 warnStyleValueIsInfinity(name, value); 2742 } 2743 } 2744 }; 2745 } 2746 2747 var warnValidStyle$1 = warnValidStyle; 2748 2749 /** 2750 * Operations for dealing with CSS properties. 2751 */ 2752 2753 /** 2754 * This creates a string that is expected to be equivalent to the style 2755 * attribute generated by server-side rendering. It by-passes warnings and 2756 * security checks so it's not safe to use this value for anything other than 2757 * comparison. It is only used in DEV for SSR validation. 2758 */ 2759 2760 function createDangerousStringForStyles(styles) { 2761 { 2762 var serialized = ''; 2763 var delimiter = ''; 2764 2765 for (var styleName in styles) { 2766 if (!styles.hasOwnProperty(styleName)) { 2767 continue; 2768 } 2769 2770 var styleValue = styles[styleName]; 2771 2772 if (styleValue != null) { 2773 var isCustomProperty = styleName.indexOf('--') === 0; 2774 serialized += delimiter + (isCustomProperty ? styleName : hyphenateStyleName(styleName)) + ':'; 2775 serialized += dangerousStyleValue(styleName, styleValue, isCustomProperty); 2776 delimiter = ';'; 2777 } 2778 } 2779 2780 return serialized || null; 2781 } 2782 } 2783 /** 2784 * Sets the value for multiple styles on a node. If a value is specified as 2785 * '' (empty string), the corresponding style property will be unset. 2786 * 2787 * @param {DOMElement} node 2788 * @param {object} styles 2789 */ 2790 2791 function setValueForStyles(node, styles) { 2792 var style = node.style; 2793 2794 for (var styleName in styles) { 2795 if (!styles.hasOwnProperty(styleName)) { 2796 continue; 2797 } 2798 2799 var isCustomProperty = styleName.indexOf('--') === 0; 2800 2801 { 2802 if (!isCustomProperty) { 2803 warnValidStyle$1(styleName, styles[styleName]); 2804 } 2805 } 2806 2807 var styleValue = dangerousStyleValue(styleName, styles[styleName], isCustomProperty); 2808 2809 if (styleName === 'float') { 2810 styleName = 'cssFloat'; 2811 } 2812 2813 if (isCustomProperty) { 2814 style.setProperty(styleName, styleValue); 2815 } else { 2816 style[styleName] = styleValue; 2817 } 2818 } 2819 } 2820 2821 function isValueEmpty(value) { 2822 return value == null || typeof value === 'boolean' || value === ''; 2823 } 2824 /** 2825 * Given {color: 'red', overflow: 'hidden'} returns { 2826 * color: 'color', 2827 * overflowX: 'overflow', 2828 * overflowY: 'overflow', 2829 * }. This can be read as "the overflowY property was set by the overflow 2830 * shorthand". That is, the values are the property that each was derived from. 2831 */ 2832 2833 2834 function expandShorthandMap(styles) { 2835 var expanded = {}; 2836 2837 for (var key in styles) { 2838 var longhands = shorthandToLonghand[key] || [key]; 2839 2840 for (var i = 0; i < longhands.length; i++) { 2841 expanded[longhands[i]] = key; 2842 } 2843 } 2844 2845 return expanded; 2846 } 2847 /** 2848 * When mixing shorthand and longhand property names, we warn during updates if 2849 * we expect an incorrect result to occur. In particular, we warn for: 2850 * 2851 * Updating a shorthand property (longhand gets overwritten): 2852 * {font: 'foo', fontVariant: 'bar'} -> {font: 'baz', fontVariant: 'bar'} 2853 * becomes .style.font = 'baz' 2854 * Removing a shorthand property (longhand gets lost too): 2855 * {font: 'foo', fontVariant: 'bar'} -> {fontVariant: 'bar'} 2856 * becomes .style.font = '' 2857 * Removing a longhand property (should revert to shorthand; doesn't): 2858 * {font: 'foo', fontVariant: 'bar'} -> {font: 'foo'} 2859 * becomes .style.fontVariant = '' 2860 */ 2861 2862 2863 function validateShorthandPropertyCollisionInDev(styleUpdates, nextStyles) { 2864 { 2865 if (!nextStyles) { 2866 return; 2867 } 2868 2869 var expandedUpdates = expandShorthandMap(styleUpdates); 2870 var expandedStyles = expandShorthandMap(nextStyles); 2871 var warnedAbout = {}; 2872 2873 for (var key in expandedUpdates) { 2874 var originalKey = expandedUpdates[key]; 2875 var correctOriginalKey = expandedStyles[key]; 2876 2877 if (correctOriginalKey && originalKey !== correctOriginalKey) { 2878 var warningKey = originalKey + ',' + correctOriginalKey; 2879 2880 if (warnedAbout[warningKey]) { 2881 continue; 2882 } 2883 2884 warnedAbout[warningKey] = true; 2885 2886 error('%s a style property during rerender (%s) when a ' + 'conflicting property is set (%s) can lead to styling bugs. To ' + "avoid this, don't mix shorthand and non-shorthand properties " + 'for the same value; instead, replace the shorthand with ' + 'separate values.', isValueEmpty(styleUpdates[originalKey]) ? 'Removing' : 'Updating', originalKey, correctOriginalKey); 2887 } 2888 } 2889 } 2890 } 2891 2892 // For HTML, certain tags should omit their close tag. We keep a list for 2893 // those special-case tags. 2894 var omittedCloseTags = { 2895 area: true, 2896 base: true, 2897 br: true, 2898 col: true, 2899 embed: true, 2900 hr: true, 2901 img: true, 2902 input: true, 2903 keygen: true, 2904 link: true, 2905 meta: true, 2906 param: true, 2907 source: true, 2908 track: true, 2909 wbr: true // NOTE: menuitem's close tag should be omitted, but that causes problems. 2910 2911 }; 2912 2913 // `omittedCloseTags` except that `menuitem` should still have its closing tag. 2914 2915 var voidElementTags = assign({ 2916 menuitem: true 2917 }, omittedCloseTags); 2918 2919 var HTML = '__html'; 2920 2921 function assertValidProps(tag, props) { 2922 if (!props) { 2923 return; 2924 } // Note the use of `==` which checks for null or undefined. 2925 2926 2927 if (voidElementTags[tag]) { 2928 if (props.children != null || props.dangerouslySetInnerHTML != null) { 2929 throw new Error(tag + " is a void element tag and must neither have `children` nor " + 'use `dangerouslySetInnerHTML`.'); 2930 } 2931 } 2932 2933 if (props.dangerouslySetInnerHTML != null) { 2934 if (props.children != null) { 2935 throw new Error('Can only set one of `children` or `props.dangerouslySetInnerHTML`.'); 2936 } 2937 2938 if (typeof props.dangerouslySetInnerHTML !== 'object' || !(HTML in props.dangerouslySetInnerHTML)) { 2939 throw new Error('`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://reactjs.org/link/dangerously-set-inner-html ' + 'for more information.'); 2940 } 2941 } 2942 2943 { 2944 if (!props.suppressContentEditableWarning && props.contentEditable && props.children != null) { 2945 error('A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.'); 2946 } 2947 } 2948 2949 if (props.style != null && typeof props.style !== 'object') { 2950 throw new Error('The `style` prop expects a mapping from style properties to values, ' + "not a string. For example, style={{marginRight: spacing + 'em'}} when " + 'using JSX.'); 2951 } 2952 } 2953 2954 function isCustomComponent(tagName, props) { 2955 if (tagName.indexOf('-') === -1) { 2956 return typeof props.is === 'string'; 2957 } 2958 2959 switch (tagName) { 2960 // These are reserved SVG and MathML elements. 2961 // We don't mind this list too much because we expect it to never grow. 2962 // The alternative is to track the namespace in a few places which is convoluted. 2963 // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts 2964 case 'annotation-xml': 2965 case 'color-profile': 2966 case 'font-face': 2967 case 'font-face-src': 2968 case 'font-face-uri': 2969 case 'font-face-format': 2970 case 'font-face-name': 2971 case 'missing-glyph': 2972 return false; 2973 2974 default: 2975 return true; 2976 } 2977 } 2978 2979 // When adding attributes to the HTML or SVG allowed attribute list, be sure to 2980 // also add them to this module to ensure casing and incorrect name 2981 // warnings. 2982 var possibleStandardNames = { 2983 // HTML 2984 accept: 'accept', 2985 acceptcharset: 'acceptCharset', 2986 'accept-charset': 'acceptCharset', 2987 accesskey: 'accessKey', 2988 action: 'action', 2989 allowfullscreen: 'allowFullScreen', 2990 alt: 'alt', 2991 as: 'as', 2992 async: 'async', 2993 autocapitalize: 'autoCapitalize', 2994 autocomplete: 'autoComplete', 2995 autocorrect: 'autoCorrect', 2996 autofocus: 'autoFocus', 2997 autoplay: 'autoPlay', 2998 autosave: 'autoSave', 2999 capture: 'capture', 3000 cellpadding: 'cellPadding', 3001 cellspacing: 'cellSpacing', 3002 challenge: 'challenge', 3003 charset: 'charSet', 3004 checked: 'checked', 3005 children: 'children', 3006 cite: 'cite', 3007 class: 'className', 3008 classid: 'classID', 3009 classname: 'className', 3010 cols: 'cols', 3011 colspan: 'colSpan', 3012 content: 'content', 3013 contenteditable: 'contentEditable', 3014 contextmenu: 'contextMenu', 3015 controls: 'controls', 3016 controlslist: 'controlsList', 3017 coords: 'coords', 3018 crossorigin: 'crossOrigin', 3019 dangerouslysetinnerhtml: 'dangerouslySetInnerHTML', 3020 data: 'data', 3021 datetime: 'dateTime', 3022 default: 'default', 3023 defaultchecked: 'defaultChecked', 3024 defaultvalue: 'defaultValue', 3025 defer: 'defer', 3026 dir: 'dir', 3027 disabled: 'disabled', 3028 disablepictureinpicture: 'disablePictureInPicture', 3029 disableremoteplayback: 'disableRemotePlayback', 3030 download: 'download', 3031 draggable: 'draggable', 3032 enctype: 'encType', 3033 enterkeyhint: 'enterKeyHint', 3034 for: 'htmlFor', 3035 form: 'form', 3036 formmethod: 'formMethod', 3037 formaction: 'formAction', 3038 formenctype: 'formEncType', 3039 formnovalidate: 'formNoValidate', 3040 formtarget: 'formTarget', 3041 frameborder: 'frameBorder', 3042 headers: 'headers', 3043 height: 'height', 3044 hidden: 'hidden', 3045 high: 'high', 3046 href: 'href', 3047 hreflang: 'hrefLang', 3048 htmlfor: 'htmlFor', 3049 httpequiv: 'httpEquiv', 3050 'http-equiv': 'httpEquiv', 3051 icon: 'icon', 3052 id: 'id', 3053 imagesizes: 'imageSizes', 3054 imagesrcset: 'imageSrcSet', 3055 innerhtml: 'innerHTML', 3056 inputmode: 'inputMode', 3057 integrity: 'integrity', 3058 is: 'is', 3059 itemid: 'itemID', 3060 itemprop: 'itemProp', 3061 itemref: 'itemRef', 3062 itemscope: 'itemScope', 3063 itemtype: 'itemType', 3064 keyparams: 'keyParams', 3065 keytype: 'keyType', 3066 kind: 'kind', 3067 label: 'label', 3068 lang: 'lang', 3069 list: 'list', 3070 loop: 'loop', 3071 low: 'low', 3072 manifest: 'manifest', 3073 marginwidth: 'marginWidth', 3074 marginheight: 'marginHeight', 3075 max: 'max', 3076 maxlength: 'maxLength', 3077 media: 'media', 3078 mediagroup: 'mediaGroup', 3079 method: 'method', 3080 min: 'min', 3081 minlength: 'minLength', 3082 multiple: 'multiple', 3083 muted: 'muted', 3084 name: 'name', 3085 nomodule: 'noModule', 3086 nonce: 'nonce', 3087 novalidate: 'noValidate', 3088 open: 'open', 3089 optimum: 'optimum', 3090 pattern: 'pattern', 3091 placeholder: 'placeholder', 3092 playsinline: 'playsInline', 3093 poster: 'poster', 3094 preload: 'preload', 3095 profile: 'profile', 3096 radiogroup: 'radioGroup', 3097 readonly: 'readOnly', 3098 referrerpolicy: 'referrerPolicy', 3099 rel: 'rel', 3100 required: 'required', 3101 reversed: 'reversed', 3102 role: 'role', 3103 rows: 'rows', 3104 rowspan: 'rowSpan', 3105 sandbox: 'sandbox', 3106 scope: 'scope', 3107 scoped: 'scoped', 3108 scrolling: 'scrolling', 3109 seamless: 'seamless', 3110 selected: 'selected', 3111 shape: 'shape', 3112 size: 'size', 3113 sizes: 'sizes', 3114 span: 'span', 3115 spellcheck: 'spellCheck', 3116 src: 'src', 3117 srcdoc: 'srcDoc', 3118 srclang: 'srcLang', 3119 srcset: 'srcSet', 3120 start: 'start', 3121 step: 'step', 3122 style: 'style', 3123 summary: 'summary', 3124 tabindex: 'tabIndex', 3125 target: 'target', 3126 title: 'title', 3127 type: 'type', 3128 usemap: 'useMap', 3129 value: 'value', 3130 width: 'width', 3131 wmode: 'wmode', 3132 wrap: 'wrap', 3133 // SVG 3134 about: 'about', 3135 accentheight: 'accentHeight', 3136 'accent-height': 'accentHeight', 3137 accumulate: 'accumulate', 3138 additive: 'additive', 3139 alignmentbaseline: 'alignmentBaseline', 3140 'alignment-baseline': 'alignmentBaseline', 3141 allowreorder: 'allowReorder', 3142 alphabetic: 'alphabetic', 3143 amplitude: 'amplitude', 3144 arabicform: 'arabicForm', 3145 'arabic-form': 'arabicForm', 3146 ascent: 'ascent', 3147 attributename: 'attributeName', 3148 attributetype: 'attributeType', 3149 autoreverse: 'autoReverse', 3150 azimuth: 'azimuth', 3151 basefrequency: 'baseFrequency', 3152 baselineshift: 'baselineShift', 3153 'baseline-shift': 'baselineShift', 3154 baseprofile: 'baseProfile', 3155 bbox: 'bbox', 3156 begin: 'begin', 3157 bias: 'bias', 3158 by: 'by', 3159 calcmode: 'calcMode', 3160 capheight: 'capHeight', 3161 'cap-height': 'capHeight', 3162 clip: 'clip', 3163 clippath: 'clipPath', 3164 'clip-path': 'clipPath', 3165 clippathunits: 'clipPathUnits', 3166 cliprule: 'clipRule', 3167 'clip-rule': 'clipRule', 3168 color: 'color', 3169 colorinterpolation: 'colorInterpolation', 3170 'color-interpolation': 'colorInterpolation', 3171 colorinterpolationfilters: 'colorInterpolationFilters', 3172 'color-interpolation-filters': 'colorInterpolationFilters', 3173 colorprofile: 'colorProfile', 3174 'color-profile': 'colorProfile', 3175 colorrendering: 'colorRendering', 3176 'color-rendering': 'colorRendering', 3177 contentscripttype: 'contentScriptType', 3178 contentstyletype: 'contentStyleType', 3179 cursor: 'cursor', 3180 cx: 'cx', 3181 cy: 'cy', 3182 d: 'd', 3183 datatype: 'datatype', 3184 decelerate: 'decelerate', 3185 descent: 'descent', 3186 diffuseconstant: 'diffuseConstant', 3187 direction: 'direction', 3188 display: 'display', 3189 divisor: 'divisor', 3190 dominantbaseline: 'dominantBaseline', 3191 'dominant-baseline': 'dominantBaseline', 3192 dur: 'dur', 3193 dx: 'dx', 3194 dy: 'dy', 3195 edgemode: 'edgeMode', 3196 elevation: 'elevation', 3197 enablebackground: 'enableBackground', 3198 'enable-background': 'enableBackground', 3199 end: 'end', 3200 exponent: 'exponent', 3201 externalresourcesrequired: 'externalResourcesRequired', 3202 fill: 'fill', 3203 fillopacity: 'fillOpacity', 3204 'fill-opacity': 'fillOpacity', 3205 fillrule: 'fillRule', 3206 'fill-rule': 'fillRule', 3207 filter: 'filter', 3208 filterres: 'filterRes', 3209 filterunits: 'filterUnits', 3210 floodopacity: 'floodOpacity', 3211 'flood-opacity': 'floodOpacity', 3212 floodcolor: 'floodColor', 3213 'flood-color': 'floodColor', 3214 focusable: 'focusable', 3215 fontfamily: 'fontFamily', 3216 'font-family': 'fontFamily', 3217 fontsize: 'fontSize', 3218 'font-size': 'fontSize', 3219 fontsizeadjust: 'fontSizeAdjust', 3220 'font-size-adjust': 'fontSizeAdjust', 3221 fontstretch: 'fontStretch', 3222 'font-stretch': 'fontStretch', 3223 fontstyle: 'fontStyle', 3224 'font-style': 'fontStyle', 3225 fontvariant: 'fontVariant', 3226 'font-variant': 'fontVariant', 3227 fontweight: 'fontWeight', 3228 'font-weight': 'fontWeight', 3229 format: 'format', 3230 from: 'from', 3231 fx: 'fx', 3232 fy: 'fy', 3233 g1: 'g1', 3234 g2: 'g2', 3235 glyphname: 'glyphName', 3236 'glyph-name': 'glyphName', 3237 glyphorientationhorizontal: 'glyphOrientationHorizontal', 3238 'glyph-orientation-horizontal': 'glyphOrientationHorizontal', 3239 glyphorientationvertical: 'glyphOrientationVertical', 3240 'glyph-orientation-vertical': 'glyphOrientationVertical', 3241 glyphref: 'glyphRef', 3242 gradienttransform: 'gradientTransform', 3243 gradientunits: 'gradientUnits', 3244 hanging: 'hanging', 3245 horizadvx: 'horizAdvX', 3246 'horiz-adv-x': 'horizAdvX', 3247 horizoriginx: 'horizOriginX', 3248 'horiz-origin-x': 'horizOriginX', 3249 ideographic: 'ideographic', 3250 imagerendering: 'imageRendering', 3251 'image-rendering': 'imageRendering', 3252 in2: 'in2', 3253 in: 'in', 3254 inlist: 'inlist', 3255 intercept: 'intercept', 3256 k1: 'k1', 3257 k2: 'k2', 3258 k3: 'k3', 3259 k4: 'k4', 3260 k: 'k', 3261 kernelmatrix: 'kernelMatrix', 3262 kernelunitlength: 'kernelUnitLength', 3263 kerning: 'kerning', 3264 keypoints: 'keyPoints', 3265 keysplines: 'keySplines', 3266 keytimes: 'keyTimes', 3267 lengthadjust: 'lengthAdjust', 3268 letterspacing: 'letterSpacing', 3269 'letter-spacing': 'letterSpacing', 3270 lightingcolor: 'lightingColor', 3271 'lighting-color': 'lightingColor', 3272 limitingconeangle: 'limitingConeAngle', 3273 local: 'local', 3274 markerend: 'markerEnd', 3275 'marker-end': 'markerEnd', 3276 markerheight: 'markerHeight', 3277 markermid: 'markerMid', 3278 'marker-mid': 'markerMid', 3279 markerstart: 'markerStart', 3280 'marker-start': 'markerStart', 3281 markerunits: 'markerUnits', 3282 markerwidth: 'markerWidth', 3283 mask: 'mask', 3284 maskcontentunits: 'maskContentUnits', 3285 maskunits: 'maskUnits', 3286 mathematical: 'mathematical', 3287 mode: 'mode', 3288 numoctaves: 'numOctaves', 3289 offset: 'offset', 3290 opacity: 'opacity', 3291 operator: 'operator', 3292 order: 'order', 3293 orient: 'orient', 3294 orientation: 'orientation', 3295 origin: 'origin', 3296 overflow: 'overflow', 3297 overlineposition: 'overlinePosition', 3298 'overline-position': 'overlinePosition', 3299 overlinethickness: 'overlineThickness', 3300 'overline-thickness': 'overlineThickness', 3301 paintorder: 'paintOrder', 3302 'paint-order': 'paintOrder', 3303 panose1: 'panose1', 3304 'panose-1': 'panose1', 3305 pathlength: 'pathLength', 3306 patterncontentunits: 'patternContentUnits', 3307 patterntransform: 'patternTransform', 3308 patternunits: 'patternUnits', 3309 pointerevents: 'pointerEvents', 3310 'pointer-events': 'pointerEvents', 3311 points: 'points', 3312 pointsatx: 'pointsAtX', 3313 pointsaty: 'pointsAtY', 3314 pointsatz: 'pointsAtZ', 3315 prefix: 'prefix', 3316 preservealpha: 'preserveAlpha', 3317 preserveaspectratio: 'preserveAspectRatio', 3318 primitiveunits: 'primitiveUnits', 3319 property: 'property', 3320 r: 'r', 3321 radius: 'radius', 3322 refx: 'refX', 3323 refy: 'refY', 3324 renderingintent: 'renderingIntent', 3325 'rendering-intent': 'renderingIntent', 3326 repeatcount: 'repeatCount', 3327 repeatdur: 'repeatDur', 3328 requiredextensions: 'requiredExtensions', 3329 requiredfeatures: 'requiredFeatures', 3330 resource: 'resource', 3331 restart: 'restart', 3332 result: 'result', 3333 results: 'results', 3334 rotate: 'rotate', 3335 rx: 'rx', 3336 ry: 'ry', 3337 scale: 'scale', 3338 security: 'security', 3339 seed: 'seed', 3340 shaperendering: 'shapeRendering', 3341 'shape-rendering': 'shapeRendering', 3342 slope: 'slope', 3343 spacing: 'spacing', 3344 specularconstant: 'specularConstant', 3345 specularexponent: 'specularExponent', 3346 speed: 'speed', 3347 spreadmethod: 'spreadMethod', 3348 startoffset: 'startOffset', 3349 stddeviation: 'stdDeviation', 3350 stemh: 'stemh', 3351 stemv: 'stemv', 3352 stitchtiles: 'stitchTiles', 3353 stopcolor: 'stopColor', 3354 'stop-color': 'stopColor', 3355 stopopacity: 'stopOpacity', 3356 'stop-opacity': 'stopOpacity', 3357 strikethroughposition: 'strikethroughPosition', 3358 'strikethrough-position': 'strikethroughPosition', 3359 strikethroughthickness: 'strikethroughThickness', 3360 'strikethrough-thickness': 'strikethroughThickness', 3361 string: 'string', 3362 stroke: 'stroke', 3363 strokedasharray: 'strokeDasharray', 3364 'stroke-dasharray': 'strokeDasharray', 3365 strokedashoffset: 'strokeDashoffset', 3366 'stroke-dashoffset': 'strokeDashoffset', 3367 strokelinecap: 'strokeLinecap', 3368 'stroke-linecap': 'strokeLinecap', 3369 strokelinejoin: 'strokeLinejoin', 3370 'stroke-linejoin': 'strokeLinejoin', 3371 strokemiterlimit: 'strokeMiterlimit', 3372 'stroke-miterlimit': 'strokeMiterlimit', 3373 strokewidth: 'strokeWidth', 3374 'stroke-width': 'strokeWidth', 3375 strokeopacity: 'strokeOpacity', 3376 'stroke-opacity': 'strokeOpacity', 3377 suppresscontenteditablewarning: 'suppressContentEditableWarning', 3378 suppresshydrationwarning: 'suppressHydrationWarning', 3379 surfacescale: 'surfaceScale', 3380 systemlanguage: 'systemLanguage', 3381 tablevalues: 'tableValues', 3382 targetx: 'targetX', 3383 targety: 'targetY', 3384 textanchor: 'textAnchor', 3385 'text-anchor': 'textAnchor', 3386 textdecoration: 'textDecoration', 3387 'text-decoration': 'textDecoration', 3388 textlength: 'textLength', 3389 textrendering: 'textRendering', 3390 'text-rendering': 'textRendering', 3391 to: 'to', 3392 transform: 'transform', 3393 typeof: 'typeof', 3394 u1: 'u1', 3395 u2: 'u2', 3396 underlineposition: 'underlinePosition', 3397 'underline-position': 'underlinePosition', 3398 underlinethickness: 'underlineThickness', 3399 'underline-thickness': 'underlineThickness', 3400 unicode: 'unicode', 3401 unicodebidi: 'unicodeBidi', 3402 'unicode-bidi': 'unicodeBidi', 3403 unicoderange: 'unicodeRange', 3404 'unicode-range': 'unicodeRange', 3405 unitsperem: 'unitsPerEm', 3406 'units-per-em': 'unitsPerEm', 3407 unselectable: 'unselectable', 3408 valphabetic: 'vAlphabetic', 3409 'v-alphabetic': 'vAlphabetic', 3410 values: 'values', 3411 vectoreffect: 'vectorEffect', 3412 'vector-effect': 'vectorEffect', 3413 version: 'version', 3414 vertadvy: 'vertAdvY', 3415 'vert-adv-y': 'vertAdvY', 3416 vertoriginx: 'vertOriginX', 3417 'vert-origin-x': 'vertOriginX', 3418 vertoriginy: 'vertOriginY', 3419 'vert-origin-y': 'vertOriginY', 3420 vhanging: 'vHanging', 3421 'v-hanging': 'vHanging', 3422 videographic: 'vIdeographic', 3423 'v-ideographic': 'vIdeographic', 3424 viewbox: 'viewBox', 3425 viewtarget: 'viewTarget', 3426 visibility: 'visibility', 3427 vmathematical: 'vMathematical', 3428 'v-mathematical': 'vMathematical', 3429 vocab: 'vocab', 3430 widths: 'widths', 3431 wordspacing: 'wordSpacing', 3432 'word-spacing': 'wordSpacing', 3433 writingmode: 'writingMode', 3434 'writing-mode': 'writingMode', 3435 x1: 'x1', 3436 x2: 'x2', 3437 x: 'x', 3438 xchannelselector: 'xChannelSelector', 3439 xheight: 'xHeight', 3440 'x-height': 'xHeight', 3441 xlinkactuate: 'xlinkActuate', 3442 'xlink:actuate': 'xlinkActuate', 3443 xlinkarcrole: 'xlinkArcrole', 3444 'xlink:arcrole': 'xlinkArcrole', 3445 xlinkhref: 'xlinkHref', 3446 'xlink:href': 'xlinkHref', 3447 xlinkrole: 'xlinkRole', 3448 'xlink:role': 'xlinkRole', 3449 xlinkshow: 'xlinkShow', 3450 'xlink:show': 'xlinkShow', 3451 xlinktitle: 'xlinkTitle', 3452 'xlink:title': 'xlinkTitle', 3453 xlinktype: 'xlinkType', 3454 'xlink:type': 'xlinkType', 3455 xmlbase: 'xmlBase', 3456 'xml:base': 'xmlBase', 3457 xmllang: 'xmlLang', 3458 'xml:lang': 'xmlLang', 3459 xmlns: 'xmlns', 3460 'xml:space': 'xmlSpace', 3461 xmlnsxlink: 'xmlnsXlink', 3462 'xmlns:xlink': 'xmlnsXlink', 3463 xmlspace: 'xmlSpace', 3464 y1: 'y1', 3465 y2: 'y2', 3466 y: 'y', 3467 ychannelselector: 'yChannelSelector', 3468 z: 'z', 3469 zoomandpan: 'zoomAndPan' 3470 }; 3471 3472 var ariaProperties = { 3473 'aria-current': 0, 3474 // state 3475 'aria-description': 0, 3476 'aria-details': 0, 3477 'aria-disabled': 0, 3478 // state 3479 'aria-hidden': 0, 3480 // state 3481 'aria-invalid': 0, 3482 // state 3483 'aria-keyshortcuts': 0, 3484 'aria-label': 0, 3485 'aria-roledescription': 0, 3486 // Widget Attributes 3487 'aria-autocomplete': 0, 3488 'aria-checked': 0, 3489 'aria-expanded': 0, 3490 'aria-haspopup': 0, 3491 'aria-level': 0, 3492 'aria-modal': 0, 3493 'aria-multiline': 0, 3494 'aria-multiselectable': 0, 3495 'aria-orientation': 0, 3496 'aria-placeholder': 0, 3497 'aria-pressed': 0, 3498 'aria-readonly': 0, 3499 'aria-required': 0, 3500 'aria-selected': 0, 3501 'aria-sort': 0, 3502 'aria-valuemax': 0, 3503 'aria-valuemin': 0, 3504 'aria-valuenow': 0, 3505 'aria-valuetext': 0, 3506 // Live Region Attributes 3507 'aria-atomic': 0, 3508 'aria-busy': 0, 3509 'aria-live': 0, 3510 'aria-relevant': 0, 3511 // Drag-and-Drop Attributes 3512 'aria-dropeffect': 0, 3513 'aria-grabbed': 0, 3514 // Relationship Attributes 3515 'aria-activedescendant': 0, 3516 'aria-colcount': 0, 3517 'aria-colindex': 0, 3518 'aria-colspan': 0, 3519 'aria-controls': 0, 3520 'aria-describedby': 0, 3521 'aria-errormessage': 0, 3522 'aria-flowto': 0, 3523 'aria-labelledby': 0, 3524 'aria-owns': 0, 3525 'aria-posinset': 0, 3526 'aria-rowcount': 0, 3527 'aria-rowindex': 0, 3528 'aria-rowspan': 0, 3529 'aria-setsize': 0 3530 }; 3531 3532 var warnedProperties = {}; 3533 var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); 3534 var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); 3535 3536 function validateProperty(tagName, name) { 3537 { 3538 if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) { 3539 return true; 3540 } 3541 3542 if (rARIACamel.test(name)) { 3543 var ariaName = 'aria-' + name.slice(4).toLowerCase(); 3544 var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null; // If this is an aria-* attribute, but is not listed in the known DOM 3545 // DOM properties, then it is an invalid aria-* attribute. 3546 3547 if (correctName == null) { 3548 error('Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.', name); 3549 3550 warnedProperties[name] = true; 3551 return true; 3552 } // aria-* attributes should be lowercase; suggest the lowercase version. 3553 3554 3555 if (name !== correctName) { 3556 error('Invalid ARIA attribute `%s`. Did you mean `%s`?', name, correctName); 3557 3558 warnedProperties[name] = true; 3559 return true; 3560 } 3561 } 3562 3563 if (rARIA.test(name)) { 3564 var lowerCasedName = name.toLowerCase(); 3565 var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null; // If this is an aria-* attribute, but is not listed in the known DOM 3566 // DOM properties, then it is an invalid aria-* attribute. 3567 3568 if (standardName == null) { 3569 warnedProperties[name] = true; 3570 return false; 3571 } // aria-* attributes should be lowercase; suggest the lowercase version. 3572 3573 3574 if (name !== standardName) { 3575 error('Unknown ARIA attribute `%s`. Did you mean `%s`?', name, standardName); 3576 3577 warnedProperties[name] = true; 3578 return true; 3579 } 3580 } 3581 } 3582 3583 return true; 3584 } 3585 3586 function warnInvalidARIAProps(type, props) { 3587 { 3588 var invalidProps = []; 3589 3590 for (var key in props) { 3591 var isValid = validateProperty(type, key); 3592 3593 if (!isValid) { 3594 invalidProps.push(key); 3595 } 3596 } 3597 3598 var unknownPropString = invalidProps.map(function (prop) { 3599 return '`' + prop + '`'; 3600 }).join(', '); 3601 3602 if (invalidProps.length === 1) { 3603 error('Invalid aria prop %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type); 3604 } else if (invalidProps.length > 1) { 3605 error('Invalid aria props %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type); 3606 } 3607 } 3608 } 3609 3610 function validateProperties(type, props) { 3611 if (isCustomComponent(type, props)) { 3612 return; 3613 } 3614 3615 warnInvalidARIAProps(type, props); 3616 } 3617 3618 var didWarnValueNull = false; 3619 function validateProperties$1(type, props) { 3620 { 3621 if (type !== 'input' && type !== 'textarea' && type !== 'select') { 3622 return; 3623 } 3624 3625 if (props != null && props.value === null && !didWarnValueNull) { 3626 didWarnValueNull = true; 3627 3628 if (type === 'select' && props.multiple) { 3629 error('`value` prop on `%s` should not be null. ' + 'Consider using an empty array when `multiple` is set to `true` ' + 'to clear the component or `undefined` for uncontrolled components.', type); 3630 } else { 3631 error('`value` prop on `%s` should not be null. ' + 'Consider using an empty string to clear the component or `undefined` ' + 'for uncontrolled components.', type); 3632 } 3633 } 3634 } 3635 } 3636 3637 var validateProperty$1 = function () {}; 3638 3639 { 3640 var warnedProperties$1 = {}; 3641 var EVENT_NAME_REGEX = /^on./; 3642 var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/; 3643 var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); 3644 var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); 3645 3646 validateProperty$1 = function (tagName, name, value, eventRegistry) { 3647 if (hasOwnProperty.call(warnedProperties$1, name) && warnedProperties$1[name]) { 3648 return true; 3649 } 3650 3651 var lowerCasedName = name.toLowerCase(); 3652 3653 if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') { 3654 error('React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.'); 3655 3656 warnedProperties$1[name] = true; 3657 return true; 3658 } // We can't rely on the event system being injected on the server. 3659 3660 3661 if (eventRegistry != null) { 3662 var registrationNameDependencies = eventRegistry.registrationNameDependencies, 3663 possibleRegistrationNames = eventRegistry.possibleRegistrationNames; 3664 3665 if (registrationNameDependencies.hasOwnProperty(name)) { 3666 return true; 3667 } 3668 3669 var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null; 3670 3671 if (registrationName != null) { 3672 error('Invalid event handler property `%s`. Did you mean `%s`?', name, registrationName); 3673 3674 warnedProperties$1[name] = true; 3675 return true; 3676 } 3677 3678 if (EVENT_NAME_REGEX.test(name)) { 3679 error('Unknown event handler property `%s`. It will be ignored.', name); 3680 3681 warnedProperties$1[name] = true; 3682 return true; 3683 } 3684 } else if (EVENT_NAME_REGEX.test(name)) { 3685 // If no event plugins have been injected, we are in a server environment. 3686 // So we can't tell if the event name is correct for sure, but we can filter 3687 // out known bad ones like `onclick`. We can't suggest a specific replacement though. 3688 if (INVALID_EVENT_NAME_REGEX.test(name)) { 3689 error('Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.', name); 3690 } 3691 3692 warnedProperties$1[name] = true; 3693 return true; 3694 } // Let the ARIA attribute hook validate ARIA attributes 3695 3696 3697 if (rARIA$1.test(name) || rARIACamel$1.test(name)) { 3698 return true; 3699 } 3700 3701 if (lowerCasedName === 'innerhtml') { 3702 error('Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.'); 3703 3704 warnedProperties$1[name] = true; 3705 return true; 3706 } 3707 3708 if (lowerCasedName === 'aria') { 3709 error('The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.'); 3710 3711 warnedProperties$1[name] = true; 3712 return true; 3713 } 3714 3715 if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') { 3716 error('Received a `%s` for a string attribute `is`. If this is expected, cast ' + 'the value to a string.', typeof value); 3717 3718 warnedProperties$1[name] = true; 3719 return true; 3720 } 3721 3722 if (typeof value === 'number' && isNaN(value)) { 3723 error('Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.', name); 3724 3725 warnedProperties$1[name] = true; 3726 return true; 3727 } 3728 3729 var propertyInfo = getPropertyInfo(name); 3730 var isReserved = propertyInfo !== null && propertyInfo.type === RESERVED; // Known attributes should match the casing specified in the property config. 3731 3732 if (possibleStandardNames.hasOwnProperty(lowerCasedName)) { 3733 var standardName = possibleStandardNames[lowerCasedName]; 3734 3735 if (standardName !== name) { 3736 error('Invalid DOM property `%s`. Did you mean `%s`?', name, standardName); 3737 3738 warnedProperties$1[name] = true; 3739 return true; 3740 } 3741 } else if (!isReserved && name !== lowerCasedName) { 3742 // Unknown attributes should have lowercase casing since that's how they 3743 // will be cased anyway with server rendering. 3744 error('React does not recognize the `%s` prop on a DOM element. If you ' + 'intentionally want it to appear in the DOM as a custom ' + 'attribute, spell it as lowercase `%s` instead. ' + 'If you accidentally passed it from a parent component, remove ' + 'it from the DOM element.', name, lowerCasedName); 3745 3746 warnedProperties$1[name] = true; 3747 return true; 3748 } 3749 3750 if (typeof value === 'boolean' && shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) { 3751 if (value) { 3752 error('Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.', value, name, name, value, name); 3753 } else { 3754 error('Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.', value, name, name, value, name, name, name); 3755 } 3756 3757 warnedProperties$1[name] = true; 3758 return true; 3759 } // Now that we've validated casing, do not validate 3760 // data types for reserved props 3761 3762 3763 if (isReserved) { 3764 return true; 3765 } // Warn when a known attribute is a bad type 3766 3767 3768 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) { 3769 warnedProperties$1[name] = true; 3770 return false; 3771 } // Warn when passing the strings 'false' or 'true' into a boolean prop 3772 3773 3774 if ((value === 'false' || value === 'true') && propertyInfo !== null && propertyInfo.type === BOOLEAN) { 3775 error('Received the string `%s` for the boolean attribute `%s`. ' + '%s ' + 'Did you mean %s={%s}?', value, name, value === 'false' ? 'The browser will interpret it as a truthy value.' : 'Although this works, it will not work as expected if you pass the string "false".', name, value); 3776 3777 warnedProperties$1[name] = true; 3778 return true; 3779 } 3780 3781 return true; 3782 }; 3783 } 3784 3785 var warnUnknownProperties = function (type, props, eventRegistry) { 3786 { 3787 var unknownProps = []; 3788 3789 for (var key in props) { 3790 var isValid = validateProperty$1(type, key, props[key], eventRegistry); 3791 3792 if (!isValid) { 3793 unknownProps.push(key); 3794 } 3795 } 3796 3797 var unknownPropString = unknownProps.map(function (prop) { 3798 return '`' + prop + '`'; 3799 }).join(', '); 3800 3801 if (unknownProps.length === 1) { 3802 error('Invalid value for prop %s on <%s> tag. Either remove it from the element, ' + 'or pass a string or number value to keep it in the DOM. ' + 'For details, see https://reactjs.org/link/attribute-behavior ', unknownPropString, type); 3803 } else if (unknownProps.length > 1) { 3804 error('Invalid values for props %s on <%s> tag. Either remove them from the element, ' + 'or pass a string or number value to keep them in the DOM. ' + 'For details, see https://reactjs.org/link/attribute-behavior ', unknownPropString, type); 3805 } 3806 } 3807 }; 3808 3809 function validateProperties$2(type, props, eventRegistry) { 3810 if (isCustomComponent(type, props)) { 3811 return; 3812 } 3813 3814 warnUnknownProperties(type, props, eventRegistry); 3815 } 3816 3817 var IS_EVENT_HANDLE_NON_MANAGED_NODE = 1; 3818 var IS_NON_DELEGATED = 1 << 1; 3819 var IS_CAPTURE_PHASE = 1 << 2; 3820 // set to LEGACY_FB_SUPPORT. LEGACY_FB_SUPPORT only gets set when 3821 // we call willDeferLaterForLegacyFBSupport, thus not bailing out 3822 // will result in endless cycles like an infinite loop. 3823 // We also don't want to defer during event replaying. 3824 3825 var SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS = IS_EVENT_HANDLE_NON_MANAGED_NODE | IS_NON_DELEGATED | IS_CAPTURE_PHASE; 3826 3827 // This exists to avoid circular dependency between ReactDOMEventReplaying 3828 // and DOMPluginEventSystem. 3829 var currentReplayingEvent = null; 3830 function setReplayingEvent(event) { 3831 { 3832 if (currentReplayingEvent !== null) { 3833 error('Expected currently replaying event to be null. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 3834 } 3835 } 3836 3837 currentReplayingEvent = event; 3838 } 3839 function resetReplayingEvent() { 3840 { 3841 if (currentReplayingEvent === null) { 3842 error('Expected currently replaying event to not be null. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 3843 } 3844 } 3845 3846 currentReplayingEvent = null; 3847 } 3848 function isReplayingEvent(event) { 3849 return event === currentReplayingEvent; 3850 } 3851 3852 /** 3853 * Gets the target node from a native browser event by accounting for 3854 * inconsistencies in browser DOM APIs. 3855 * 3856 * @param {object} nativeEvent Native browser event. 3857 * @return {DOMEventTarget} Target node. 3858 */ 3859 3860 function getEventTarget(nativeEvent) { 3861 // Fallback to nativeEvent.srcElement for IE9 3862 // https://github.com/facebook/react/issues/12506 3863 var target = nativeEvent.target || nativeEvent.srcElement || window; // Normalize SVG <use> element events #4963 3864 3865 if (target.correspondingUseElement) { 3866 target = target.correspondingUseElement; 3867 } // Safari may fire events on text nodes (Node.TEXT_NODE is 3). 3868 // @see http://www.quirksmode.org/js/events_properties.html 3869 3870 3871 return target.nodeType === TEXT_NODE ? target.parentNode : target; 3872 } 3873 3874 var restoreImpl = null; 3875 var restoreTarget = null; 3876 var restoreQueue = null; 3877 3878 function restoreStateOfTarget(target) { 3879 // We perform this translation at the end of the event loop so that we 3880 // always receive the correct fiber here 3881 var internalInstance = getInstanceFromNode(target); 3882 3883 if (!internalInstance) { 3884 // Unmounted 3885 return; 3886 } 3887 3888 if (typeof restoreImpl !== 'function') { 3889 throw new Error('setRestoreImplementation() needs to be called to handle a target for controlled ' + 'events. This error is likely caused by a bug in React. Please file an issue.'); 3890 } 3891 3892 var stateNode = internalInstance.stateNode; // Guard against Fiber being unmounted. 3893 3894 if (stateNode) { 3895 var _props = getFiberCurrentPropsFromNode(stateNode); 3896 3897 restoreImpl(internalInstance.stateNode, internalInstance.type, _props); 3898 } 3899 } 3900 3901 function setRestoreImplementation(impl) { 3902 restoreImpl = impl; 3903 } 3904 function enqueueStateRestore(target) { 3905 if (restoreTarget) { 3906 if (restoreQueue) { 3907 restoreQueue.push(target); 3908 } else { 3909 restoreQueue = [target]; 3910 } 3911 } else { 3912 restoreTarget = target; 3913 } 3914 } 3915 function needsStateRestore() { 3916 return restoreTarget !== null || restoreQueue !== null; 3917 } 3918 function restoreStateIfNeeded() { 3919 if (!restoreTarget) { 3920 return; 3921 } 3922 3923 var target = restoreTarget; 3924 var queuedTargets = restoreQueue; 3925 restoreTarget = null; 3926 restoreQueue = null; 3927 restoreStateOfTarget(target); 3928 3929 if (queuedTargets) { 3930 for (var i = 0; i < queuedTargets.length; i++) { 3931 restoreStateOfTarget(queuedTargets[i]); 3932 } 3933 } 3934 } 3935 3936 // the renderer. Such as when we're dispatching events or if third party 3937 // libraries need to call batchedUpdates. Eventually, this API will go away when 3938 // everything is batched by default. We'll then have a similar API to opt-out of 3939 // scheduled work and instead do synchronous work. 3940 // Defaults 3941 3942 var batchedUpdatesImpl = function (fn, bookkeeping) { 3943 return fn(bookkeeping); 3944 }; 3945 3946 var flushSyncImpl = function () {}; 3947 3948 var isInsideEventHandler = false; 3949 3950 function finishEventHandler() { 3951 // Here we wait until all updates have propagated, which is important 3952 // when using controlled components within layers: 3953 // https://github.com/facebook/react/issues/1698 3954 // Then we restore state of any controlled component. 3955 var controlledComponentsHavePendingUpdates = needsStateRestore(); 3956 3957 if (controlledComponentsHavePendingUpdates) { 3958 // If a controlled event was fired, we may need to restore the state of 3959 // the DOM node back to the controlled value. This is necessary when React 3960 // bails out of the update without touching the DOM. 3961 // TODO: Restore state in the microtask, after the discrete updates flush, 3962 // instead of early flushing them here. 3963 flushSyncImpl(); 3964 restoreStateIfNeeded(); 3965 } 3966 } 3967 3968 function batchedUpdates(fn, a, b) { 3969 if (isInsideEventHandler) { 3970 // If we are currently inside another batch, we need to wait until it 3971 // fully completes before restoring state. 3972 return fn(a, b); 3973 } 3974 3975 isInsideEventHandler = true; 3976 3977 try { 3978 return batchedUpdatesImpl(fn, a, b); 3979 } finally { 3980 isInsideEventHandler = false; 3981 finishEventHandler(); 3982 } 3983 } // TODO: Replace with flushSync 3984 function setBatchingImplementation(_batchedUpdatesImpl, _discreteUpdatesImpl, _flushSyncImpl) { 3985 batchedUpdatesImpl = _batchedUpdatesImpl; 3986 flushSyncImpl = _flushSyncImpl; 3987 } 3988 3989 function isInteractive(tag) { 3990 return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea'; 3991 } 3992 3993 function shouldPreventMouseEvent(name, type, props) { 3994 switch (name) { 3995 case 'onClick': 3996 case 'onClickCapture': 3997 case 'onDoubleClick': 3998 case 'onDoubleClickCapture': 3999 case 'onMouseDown': 4000 case 'onMouseDownCapture': 4001 case 'onMouseMove': 4002 case 'onMouseMoveCapture': 4003 case 'onMouseUp': 4004 case 'onMouseUpCapture': 4005 case 'onMouseEnter': 4006 return !!(props.disabled && isInteractive(type)); 4007 4008 default: 4009 return false; 4010 } 4011 } 4012 /** 4013 * @param {object} inst The instance, which is the source of events. 4014 * @param {string} registrationName Name of listener (e.g. `onClick`). 4015 * @return {?function} The stored callback. 4016 */ 4017 4018 4019 function getListener(inst, registrationName) { 4020 var stateNode = inst.stateNode; 4021 4022 if (stateNode === null) { 4023 // Work in progress (ex: onload events in incremental mode). 4024 return null; 4025 } 4026 4027 var props = getFiberCurrentPropsFromNode(stateNode); 4028 4029 if (props === null) { 4030 // Work in progress. 4031 return null; 4032 } 4033 4034 var listener = props[registrationName]; 4035 4036 if (shouldPreventMouseEvent(registrationName, inst.type, props)) { 4037 return null; 4038 } 4039 4040 if (listener && typeof listener !== 'function') { 4041 throw new Error("Expected `" + registrationName + "` listener to be a function, instead got a value of `" + typeof listener + "` type."); 4042 } 4043 4044 return listener; 4045 } 4046 4047 var passiveBrowserEventsSupported = false; // Check if browser support events with passive listeners 4048 // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support 4049 4050 if (canUseDOM) { 4051 try { 4052 var options = {}; // $FlowFixMe: Ignore Flow complaining about needing a value 4053 4054 Object.defineProperty(options, 'passive', { 4055 get: function () { 4056 passiveBrowserEventsSupported = true; 4057 } 4058 }); 4059 window.addEventListener('test', options, options); 4060 window.removeEventListener('test', options, options); 4061 } catch (e) { 4062 passiveBrowserEventsSupported = false; 4063 } 4064 } 4065 4066 function invokeGuardedCallbackProd(name, func, context, a, b, c, d, e, f) { 4067 var funcArgs = Array.prototype.slice.call(arguments, 3); 4068 4069 try { 4070 func.apply(context, funcArgs); 4071 } catch (error) { 4072 this.onError(error); 4073 } 4074 } 4075 4076 var invokeGuardedCallbackImpl = invokeGuardedCallbackProd; 4077 4078 { 4079 // In DEV mode, we swap out invokeGuardedCallback for a special version 4080 // that plays more nicely with the browser's DevTools. The idea is to preserve 4081 // "Pause on exceptions" behavior. Because React wraps all user-provided 4082 // functions in invokeGuardedCallback, and the production version of 4083 // invokeGuardedCallback uses a try-catch, all user exceptions are treated 4084 // like caught exceptions, and the DevTools won't pause unless the developer 4085 // takes the extra step of enabling pause on caught exceptions. This is 4086 // unintuitive, though, because even though React has caught the error, from 4087 // the developer's perspective, the error is uncaught. 4088 // 4089 // To preserve the expected "Pause on exceptions" behavior, we don't use a 4090 // try-catch in DEV. Instead, we synchronously dispatch a fake event to a fake 4091 // DOM node, and call the user-provided callback from inside an event handler 4092 // for that fake event. If the callback throws, the error is "captured" using 4093 // a global event handler. But because the error happens in a different 4094 // event loop context, it does not interrupt the normal program flow. 4095 // Effectively, this gives us try-catch behavior without actually using 4096 // try-catch. Neat! 4097 // Check that the browser supports the APIs we need to implement our special 4098 // DEV version of invokeGuardedCallback 4099 if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') { 4100 var fakeNode = document.createElement('react'); 4101 4102 invokeGuardedCallbackImpl = function invokeGuardedCallbackDev(name, func, context, a, b, c, d, e, f) { 4103 // If document doesn't exist we know for sure we will crash in this method 4104 // when we call document.createEvent(). However this can cause confusing 4105 // errors: https://github.com/facebook/create-react-app/issues/3482 4106 // So we preemptively throw with a better message instead. 4107 if (typeof document === 'undefined' || document === null) { 4108 throw new Error('The `document` global was defined when React was initialized, but is not ' + 'defined anymore. This can happen in a test environment if a component ' + 'schedules an update from an asynchronous callback, but the test has already ' + 'finished running. To solve this, you can either unmount the component at ' + 'the end of your test (and ensure that any asynchronous operations get ' + 'canceled in `componentWillUnmount`), or you can change the test itself ' + 'to be asynchronous.'); 4109 } 4110 4111 var evt = document.createEvent('Event'); 4112 var didCall = false; // Keeps track of whether the user-provided callback threw an error. We 4113 // set this to true at the beginning, then set it to false right after 4114 // calling the function. If the function errors, `didError` will never be 4115 // set to false. This strategy works even if the browser is flaky and 4116 // fails to call our global error handler, because it doesn't rely on 4117 // the error event at all. 4118 4119 var didError = true; // Keeps track of the value of window.event so that we can reset it 4120 // during the callback to let user code access window.event in the 4121 // browsers that support it. 4122 4123 var windowEvent = window.event; // Keeps track of the descriptor of window.event to restore it after event 4124 // dispatching: https://github.com/facebook/react/issues/13688 4125 4126 var windowEventDescriptor = Object.getOwnPropertyDescriptor(window, 'event'); 4127 4128 function restoreAfterDispatch() { 4129 // We immediately remove the callback from event listeners so that 4130 // nested `invokeGuardedCallback` calls do not clash. Otherwise, a 4131 // nested call would trigger the fake event handlers of any call higher 4132 // in the stack. 4133 fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the 4134 // window.event assignment in both IE <= 10 as they throw an error 4135 // "Member not found" in strict mode, and in Firefox which does not 4136 // support window.event. 4137 4138 if (typeof window.event !== 'undefined' && window.hasOwnProperty('event')) { 4139 window.event = windowEvent; 4140 } 4141 } // Create an event handler for our fake event. We will synchronously 4142 // dispatch our fake event using `dispatchEvent`. Inside the handler, we 4143 // call the user-provided callback. 4144 4145 4146 var funcArgs = Array.prototype.slice.call(arguments, 3); 4147 4148 function callCallback() { 4149 didCall = true; 4150 restoreAfterDispatch(); 4151 func.apply(context, funcArgs); 4152 didError = false; 4153 } // Create a global error event handler. We use this to capture the value 4154 // that was thrown. It's possible that this error handler will fire more 4155 // than once; for example, if non-React code also calls `dispatchEvent` 4156 // and a handler for that event throws. We should be resilient to most of 4157 // those cases. Even if our error event handler fires more than once, the 4158 // last error event is always used. If the callback actually does error, 4159 // we know that the last error event is the correct one, because it's not 4160 // possible for anything else to have happened in between our callback 4161 // erroring and the code that follows the `dispatchEvent` call below. If 4162 // the callback doesn't error, but the error event was fired, we know to 4163 // ignore it because `didError` will be false, as described above. 4164 4165 4166 var error; // Use this to track whether the error event is ever called. 4167 4168 var didSetError = false; 4169 var isCrossOriginError = false; 4170 4171 function handleWindowError(event) { 4172 error = event.error; 4173 didSetError = true; 4174 4175 if (error === null && event.colno === 0 && event.lineno === 0) { 4176 isCrossOriginError = true; 4177 } 4178 4179 if (event.defaultPrevented) { 4180 // Some other error handler has prevented default. 4181 // Browsers silence the error report if this happens. 4182 // We'll remember this to later decide whether to log it or not. 4183 if (error != null && typeof error === 'object') { 4184 try { 4185 error._suppressLogging = true; 4186 } catch (inner) {// Ignore. 4187 } 4188 } 4189 } 4190 } // Create a fake event type. 4191 4192 4193 var evtType = "react-" + (name ? name : 'invokeguardedcallback'); // Attach our event handlers 4194 4195 window.addEventListener('error', handleWindowError); 4196 fakeNode.addEventListener(evtType, callCallback, false); // Synchronously dispatch our fake event. If the user-provided function 4197 // errors, it will trigger our global error handler. 4198 4199 evt.initEvent(evtType, false, false); 4200 fakeNode.dispatchEvent(evt); 4201 4202 if (windowEventDescriptor) { 4203 Object.defineProperty(window, 'event', windowEventDescriptor); 4204 } 4205 4206 if (didCall && didError) { 4207 if (!didSetError) { 4208 // The callback errored, but the error event never fired. 4209 // eslint-disable-next-line react-internal/prod-error-codes 4210 error = new Error('An error was thrown inside one of your components, but React ' + "doesn't know what it was. This is likely due to browser " + 'flakiness. React does its best to preserve the "Pause on ' + 'exceptions" behavior of the DevTools, which requires some ' + "DEV-mode only tricks. It's possible that these don't work in " + 'your browser. Try triggering the error in production mode, ' + 'or switching to a modern browser. If you suspect that this is ' + 'actually an issue with React, please file an issue.'); 4211 } else if (isCrossOriginError) { 4212 // eslint-disable-next-line react-internal/prod-error-codes 4213 error = new Error("A cross-origin error was thrown. React doesn't have access to " + 'the actual error object in development. ' + 'See https://reactjs.org/link/crossorigin-error for more information.'); 4214 } 4215 4216 this.onError(error); 4217 } // Remove our event listeners 4218 4219 4220 window.removeEventListener('error', handleWindowError); 4221 4222 if (!didCall) { 4223 // Something went really wrong, and our event was not dispatched. 4224 // https://github.com/facebook/react/issues/16734 4225 // https://github.com/facebook/react/issues/16585 4226 // Fall back to the production implementation. 4227 restoreAfterDispatch(); 4228 return invokeGuardedCallbackProd.apply(this, arguments); 4229 } 4230 }; 4231 } 4232 } 4233 4234 var invokeGuardedCallbackImpl$1 = invokeGuardedCallbackImpl; 4235 4236 var hasError = false; 4237 var caughtError = null; // Used by event system to capture/rethrow the first error. 4238 4239 var hasRethrowError = false; 4240 var rethrowError = null; 4241 var reporter = { 4242 onError: function (error) { 4243 hasError = true; 4244 caughtError = error; 4245 } 4246 }; 4247 /** 4248 * Call a function while guarding against errors that happens within it. 4249 * Returns an error if it throws, otherwise null. 4250 * 4251 * In production, this is implemented using a try-catch. The reason we don't 4252 * use a try-catch directly is so that we can swap out a different 4253 * implementation in DEV mode. 4254 * 4255 * @param {String} name of the guard to use for logging or debugging 4256 * @param {Function} func The function to invoke 4257 * @param {*} context The context to use when calling the function 4258 * @param {...*} args Arguments for function 4259 */ 4260 4261 function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { 4262 hasError = false; 4263 caughtError = null; 4264 invokeGuardedCallbackImpl$1.apply(reporter, arguments); 4265 } 4266 /** 4267 * Same as invokeGuardedCallback, but instead of returning an error, it stores 4268 * it in a global so it can be rethrown by `rethrowCaughtError` later. 4269 * TODO: See if caughtError and rethrowError can be unified. 4270 * 4271 * @param {String} name of the guard to use for logging or debugging 4272 * @param {Function} func The function to invoke 4273 * @param {*} context The context to use when calling the function 4274 * @param {...*} args Arguments for function 4275 */ 4276 4277 function invokeGuardedCallbackAndCatchFirstError(name, func, context, a, b, c, d, e, f) { 4278 invokeGuardedCallback.apply(this, arguments); 4279 4280 if (hasError) { 4281 var error = clearCaughtError(); 4282 4283 if (!hasRethrowError) { 4284 hasRethrowError = true; 4285 rethrowError = error; 4286 } 4287 } 4288 } 4289 /** 4290 * During execution of guarded functions we will capture the first error which 4291 * we will rethrow to be handled by the top level error handler. 4292 */ 4293 4294 function rethrowCaughtError() { 4295 if (hasRethrowError) { 4296 var error = rethrowError; 4297 hasRethrowError = false; 4298 rethrowError = null; 4299 throw error; 4300 } 4301 } 4302 function hasCaughtError() { 4303 return hasError; 4304 } 4305 function clearCaughtError() { 4306 if (hasError) { 4307 var error = caughtError; 4308 hasError = false; 4309 caughtError = null; 4310 return error; 4311 } else { 4312 throw new Error('clearCaughtError was called but no error was captured. This error ' + 'is likely caused by a bug in React. Please file an issue.'); 4313 } 4314 } 4315 4316 var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; 4317 var _ReactInternals$Sched = ReactInternals.Scheduler, 4318 unstable_cancelCallback = _ReactInternals$Sched.unstable_cancelCallback, 4319 unstable_now = _ReactInternals$Sched.unstable_now, 4320 unstable_scheduleCallback = _ReactInternals$Sched.unstable_scheduleCallback, 4321 unstable_shouldYield = _ReactInternals$Sched.unstable_shouldYield, 4322 unstable_requestPaint = _ReactInternals$Sched.unstable_requestPaint, 4323 unstable_getFirstCallbackNode = _ReactInternals$Sched.unstable_getFirstCallbackNode, 4324 unstable_runWithPriority = _ReactInternals$Sched.unstable_runWithPriority, 4325 unstable_next = _ReactInternals$Sched.unstable_next, 4326 unstable_continueExecution = _ReactInternals$Sched.unstable_continueExecution, 4327 unstable_pauseExecution = _ReactInternals$Sched.unstable_pauseExecution, 4328 unstable_getCurrentPriorityLevel = _ReactInternals$Sched.unstable_getCurrentPriorityLevel, 4329 unstable_ImmediatePriority = _ReactInternals$Sched.unstable_ImmediatePriority, 4330 unstable_UserBlockingPriority = _ReactInternals$Sched.unstable_UserBlockingPriority, 4331 unstable_NormalPriority = _ReactInternals$Sched.unstable_NormalPriority, 4332 unstable_LowPriority = _ReactInternals$Sched.unstable_LowPriority, 4333 unstable_IdlePriority = _ReactInternals$Sched.unstable_IdlePriority, 4334 unstable_forceFrameRate = _ReactInternals$Sched.unstable_forceFrameRate, 4335 unstable_flushAllWithoutAsserting = _ReactInternals$Sched.unstable_flushAllWithoutAsserting, 4336 unstable_yieldValue = _ReactInternals$Sched.unstable_yieldValue, 4337 unstable_setDisableYieldValue = _ReactInternals$Sched.unstable_setDisableYieldValue; 4338 4339 /** 4340 * `ReactInstanceMap` maintains a mapping from a public facing stateful 4341 * instance (key) and the internal representation (value). This allows public 4342 * methods to accept the user facing instance as an argument and map them back 4343 * to internal methods. 4344 * 4345 * Note that this module is currently shared and assumed to be stateless. 4346 * If this becomes an actual Map, that will break. 4347 */ 4348 function get(key) { 4349 return key._reactInternals; 4350 } 4351 function has(key) { 4352 return key._reactInternals !== undefined; 4353 } 4354 function set(key, value) { 4355 key._reactInternals = value; 4356 } 4357 4358 // Don't change these two values. They're used by React Dev Tools. 4359 var NoFlags = 4360 /* */ 4361 0; 4362 var PerformedWork = 4363 /* */ 4364 1; // You can change the rest (and add more). 4365 4366 var Placement = 4367 /* */ 4368 2; 4369 var Update = 4370 /* */ 4371 4; 4372 var ChildDeletion = 4373 /* */ 4374 16; 4375 var ContentReset = 4376 /* */ 4377 32; 4378 var Callback = 4379 /* */ 4380 64; 4381 var DidCapture = 4382 /* */ 4383 128; 4384 var ForceClientRender = 4385 /* */ 4386 256; 4387 var Ref = 4388 /* */ 4389 512; 4390 var Snapshot = 4391 /* */ 4392 1024; 4393 var Passive = 4394 /* */ 4395 2048; 4396 var Hydrating = 4397 /* */ 4398 4096; 4399 var Visibility = 4400 /* */ 4401 8192; 4402 var StoreConsistency = 4403 /* */ 4404 16384; 4405 var LifecycleEffectMask = Passive | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) 4406 4407 var HostEffectMask = 4408 /* */ 4409 32767; // These are not really side effects, but we still reuse this field. 4410 4411 var Incomplete = 4412 /* */ 4413 32768; 4414 var ShouldCapture = 4415 /* */ 4416 65536; 4417 var ForceUpdateForLegacySuspense = 4418 /* */ 4419 131072; 4420 var Forked = 4421 /* */ 4422 1048576; // Static tags describe aspects of a fiber that are not specific to a render, 4423 // e.g. a fiber uses a passive effect (even if there are no updates on this particular render). 4424 // This enables us to defer more work in the unmount case, 4425 // since we can defer traversing the tree during layout to look for Passive effects, 4426 // and instead rely on the static flag as a signal that there may be cleanup work. 4427 4428 var RefStatic = 4429 /* */ 4430 2097152; 4431 var LayoutStatic = 4432 /* */ 4433 4194304; 4434 var PassiveStatic = 4435 /* */ 4436 8388608; // These flags allow us to traverse to fibers that have effects on mount 4437 // without traversing the entire tree after every commit for 4438 // double invoking 4439 4440 var MountLayoutDev = 4441 /* */ 4442 16777216; 4443 var MountPassiveDev = 4444 /* */ 4445 33554432; // Groups of flags that are used in the commit phase to skip over trees that 4446 // don't contain effects, by checking subtreeFlags. 4447 4448 var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility 4449 // flag logic (see #20043) 4450 Update | Snapshot | ( 0); 4451 var MutationMask = Placement | Update | ChildDeletion | ContentReset | Ref | Hydrating | Visibility; 4452 var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask 4453 4454 var PassiveMask = Passive | ChildDeletion; // Union of tags that don't get reset on clones. 4455 // This allows certain concepts to persist without recalculating them, 4456 // e.g. whether a subtree contains passive effects or portals. 4457 4458 var StaticMask = LayoutStatic | PassiveStatic | RefStatic; 4459 4460 var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; 4461 function getNearestMountedFiber(fiber) { 4462 var node = fiber; 4463 var nearestMounted = fiber; 4464 4465 if (!fiber.alternate) { 4466 // If there is no alternate, this might be a new tree that isn't inserted 4467 // yet. If it is, then it will have a pending insertion effect on it. 4468 var nextNode = node; 4469 4470 do { 4471 node = nextNode; 4472 4473 if ((node.flags & (Placement | Hydrating)) !== NoFlags) { 4474 // This is an insertion or in-progress hydration. The nearest possible 4475 // mounted fiber is the parent but we need to continue to figure out 4476 // if that one is still mounted. 4477 nearestMounted = node.return; 4478 } 4479 4480 nextNode = node.return; 4481 } while (nextNode); 4482 } else { 4483 while (node.return) { 4484 node = node.return; 4485 } 4486 } 4487 4488 if (node.tag === HostRoot) { 4489 // TODO: Check if this was a nested HostRoot when used with 4490 // renderContainerIntoSubtree. 4491 return nearestMounted; 4492 } // If we didn't hit the root, that means that we're in an disconnected tree 4493 // that has been unmounted. 4494 4495 4496 return null; 4497 } 4498 function getSuspenseInstanceFromFiber(fiber) { 4499 if (fiber.tag === SuspenseComponent) { 4500 var suspenseState = fiber.memoizedState; 4501 4502 if (suspenseState === null) { 4503 var current = fiber.alternate; 4504 4505 if (current !== null) { 4506 suspenseState = current.memoizedState; 4507 } 4508 } 4509 4510 if (suspenseState !== null) { 4511 return suspenseState.dehydrated; 4512 } 4513 } 4514 4515 return null; 4516 } 4517 function getContainerFromFiber(fiber) { 4518 return fiber.tag === HostRoot ? fiber.stateNode.containerInfo : null; 4519 } 4520 function isFiberMounted(fiber) { 4521 return getNearestMountedFiber(fiber) === fiber; 4522 } 4523 function isMounted(component) { 4524 { 4525 var owner = ReactCurrentOwner.current; 4526 4527 if (owner !== null && owner.tag === ClassComponent) { 4528 var ownerFiber = owner; 4529 var instance = ownerFiber.stateNode; 4530 4531 if (!instance._warnedAboutRefsInRender) { 4532 error('%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', getComponentNameFromFiber(ownerFiber) || 'A component'); 4533 } 4534 4535 instance._warnedAboutRefsInRender = true; 4536 } 4537 } 4538 4539 var fiber = get(component); 4540 4541 if (!fiber) { 4542 return false; 4543 } 4544 4545 return getNearestMountedFiber(fiber) === fiber; 4546 } 4547 4548 function assertIsMounted(fiber) { 4549 if (getNearestMountedFiber(fiber) !== fiber) { 4550 throw new Error('Unable to find node on an unmounted component.'); 4551 } 4552 } 4553 4554 function findCurrentFiberUsingSlowPath(fiber) { 4555 var alternate = fiber.alternate; 4556 4557 if (!alternate) { 4558 // If there is no alternate, then we only need to check if it is mounted. 4559 var nearestMounted = getNearestMountedFiber(fiber); 4560 4561 if (nearestMounted === null) { 4562 throw new Error('Unable to find node on an unmounted component.'); 4563 } 4564 4565 if (nearestMounted !== fiber) { 4566 return null; 4567 } 4568 4569 return fiber; 4570 } // If we have two possible branches, we'll walk backwards up to the root 4571 // to see what path the root points to. On the way we may hit one of the 4572 // special cases and we'll deal with them. 4573 4574 4575 var a = fiber; 4576 var b = alternate; 4577 4578 while (true) { 4579 var parentA = a.return; 4580 4581 if (parentA === null) { 4582 // We're at the root. 4583 break; 4584 } 4585 4586 var parentB = parentA.alternate; 4587 4588 if (parentB === null) { 4589 // There is no alternate. This is an unusual case. Currently, it only 4590 // happens when a Suspense component is hidden. An extra fragment fiber 4591 // is inserted in between the Suspense fiber and its children. Skip 4592 // over this extra fragment fiber and proceed to the next parent. 4593 var nextParent = parentA.return; 4594 4595 if (nextParent !== null) { 4596 a = b = nextParent; 4597 continue; 4598 } // If there's no parent, we're at the root. 4599 4600 4601 break; 4602 } // If both copies of the parent fiber point to the same child, we can 4603 // assume that the child is current. This happens when we bailout on low 4604 // priority: the bailed out fiber's child reuses the current child. 4605 4606 4607 if (parentA.child === parentB.child) { 4608 var child = parentA.child; 4609 4610 while (child) { 4611 if (child === a) { 4612 // We've determined that A is the current branch. 4613 assertIsMounted(parentA); 4614 return fiber; 4615 } 4616 4617 if (child === b) { 4618 // We've determined that B is the current branch. 4619 assertIsMounted(parentA); 4620 return alternate; 4621 } 4622 4623 child = child.sibling; 4624 } // We should never have an alternate for any mounting node. So the only 4625 // way this could possibly happen is if this was unmounted, if at all. 4626 4627 4628 throw new Error('Unable to find node on an unmounted component.'); 4629 } 4630 4631 if (a.return !== b.return) { 4632 // The return pointer of A and the return pointer of B point to different 4633 // fibers. We assume that return pointers never criss-cross, so A must 4634 // belong to the child set of A.return, and B must belong to the child 4635 // set of B.return. 4636 a = parentA; 4637 b = parentB; 4638 } else { 4639 // The return pointers point to the same fiber. We'll have to use the 4640 // default, slow path: scan the child sets of each parent alternate to see 4641 // which child belongs to which set. 4642 // 4643 // Search parent A's child set 4644 var didFindChild = false; 4645 var _child = parentA.child; 4646 4647 while (_child) { 4648 if (_child === a) { 4649 didFindChild = true; 4650 a = parentA; 4651 b = parentB; 4652 break; 4653 } 4654 4655 if (_child === b) { 4656 didFindChild = true; 4657 b = parentA; 4658 a = parentB; 4659 break; 4660 } 4661 4662 _child = _child.sibling; 4663 } 4664 4665 if (!didFindChild) { 4666 // Search parent B's child set 4667 _child = parentB.child; 4668 4669 while (_child) { 4670 if (_child === a) { 4671 didFindChild = true; 4672 a = parentB; 4673 b = parentA; 4674 break; 4675 } 4676 4677 if (_child === b) { 4678 didFindChild = true; 4679 b = parentB; 4680 a = parentA; 4681 break; 4682 } 4683 4684 _child = _child.sibling; 4685 } 4686 4687 if (!didFindChild) { 4688 throw new Error('Child was not found in either parent set. This indicates a bug ' + 'in React related to the return pointer. Please file an issue.'); 4689 } 4690 } 4691 } 4692 4693 if (a.alternate !== b) { 4694 throw new Error("Return fibers should always be each others' alternates. " + 'This error is likely caused by a bug in React. Please file an issue.'); 4695 } 4696 } // If the root is not a host container, we're in a disconnected tree. I.e. 4697 // unmounted. 4698 4699 4700 if (a.tag !== HostRoot) { 4701 throw new Error('Unable to find node on an unmounted component.'); 4702 } 4703 4704 if (a.stateNode.current === a) { 4705 // We've determined that A is the current branch. 4706 return fiber; 4707 } // Otherwise B has to be current branch. 4708 4709 4710 return alternate; 4711 } 4712 function findCurrentHostFiber(parent) { 4713 var currentParent = findCurrentFiberUsingSlowPath(parent); 4714 return currentParent !== null ? findCurrentHostFiberImpl(currentParent) : null; 4715 } 4716 4717 function findCurrentHostFiberImpl(node) { 4718 // Next we'll drill down this component to find the first HostComponent/Text. 4719 if (node.tag === HostComponent || node.tag === HostText) { 4720 return node; 4721 } 4722 4723 var child = node.child; 4724 4725 while (child !== null) { 4726 var match = findCurrentHostFiberImpl(child); 4727 4728 if (match !== null) { 4729 return match; 4730 } 4731 4732 child = child.sibling; 4733 } 4734 4735 return null; 4736 } 4737 4738 function findCurrentHostFiberWithNoPortals(parent) { 4739 var currentParent = findCurrentFiberUsingSlowPath(parent); 4740 return currentParent !== null ? findCurrentHostFiberWithNoPortalsImpl(currentParent) : null; 4741 } 4742 4743 function findCurrentHostFiberWithNoPortalsImpl(node) { 4744 // Next we'll drill down this component to find the first HostComponent/Text. 4745 if (node.tag === HostComponent || node.tag === HostText) { 4746 return node; 4747 } 4748 4749 var child = node.child; 4750 4751 while (child !== null) { 4752 if (child.tag !== HostPortal) { 4753 var match = findCurrentHostFiberWithNoPortalsImpl(child); 4754 4755 if (match !== null) { 4756 return match; 4757 } 4758 } 4759 4760 child = child.sibling; 4761 } 4762 4763 return null; 4764 } 4765 4766 // This module only exists as an ESM wrapper around the external CommonJS 4767 var scheduleCallback = unstable_scheduleCallback; 4768 var cancelCallback = unstable_cancelCallback; 4769 var shouldYield = unstable_shouldYield; 4770 var requestPaint = unstable_requestPaint; 4771 var now = unstable_now; 4772 var getCurrentPriorityLevel = unstable_getCurrentPriorityLevel; 4773 var ImmediatePriority = unstable_ImmediatePriority; 4774 var UserBlockingPriority = unstable_UserBlockingPriority; 4775 var NormalPriority = unstable_NormalPriority; 4776 var LowPriority = unstable_LowPriority; 4777 var IdlePriority = unstable_IdlePriority; 4778 // this doesn't actually exist on the scheduler, but it *does* 4779 // on scheduler/unstable_mock, which we'll need for internal testing 4780 var unstable_yieldValue$1 = unstable_yieldValue; 4781 var unstable_setDisableYieldValue$1 = unstable_setDisableYieldValue; 4782 4783 var rendererID = null; 4784 var injectedHook = null; 4785 var injectedProfilingHooks = null; 4786 var hasLoggedError = false; 4787 var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined'; 4788 function injectInternals(internals) { 4789 if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { 4790 // No DevTools 4791 return false; 4792 } 4793 4794 var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; 4795 4796 if (hook.isDisabled) { 4797 // This isn't a real property on the hook, but it can be set to opt out 4798 // of DevTools integration and associated warnings and logs. 4799 // https://github.com/facebook/react/issues/3877 4800 return true; 4801 } 4802 4803 if (!hook.supportsFiber) { 4804 { 4805 error('The installed version of React DevTools is too old and will not work ' + 'with the current version of React. Please update React DevTools. ' + 'https://reactjs.org/link/react-devtools'); 4806 } // DevTools exists, even though it doesn't support Fiber. 4807 4808 4809 return true; 4810 } 4811 4812 try { 4813 if (enableSchedulingProfiler) { 4814 // Conditionally inject these hooks only if Timeline profiler is supported by this build. 4815 // This gives DevTools a way to feature detect that isn't tied to version number 4816 // (since profiling and timeline are controlled by different feature flags). 4817 internals = assign({}, internals, { 4818 getLaneLabelMap: getLaneLabelMap, 4819 injectProfilingHooks: injectProfilingHooks 4820 }); 4821 } 4822 4823 rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. 4824 4825 injectedHook = hook; 4826 } catch (err) { 4827 // Catch all errors because it is unsafe to throw during initialization. 4828 { 4829 error('React instrumentation encountered an error: %s.', err); 4830 } 4831 } 4832 4833 if (hook.checkDCE) { 4834 // This is the real DevTools. 4835 return true; 4836 } else { 4837 // This is likely a hook installed by Fast Refresh runtime. 4838 return false; 4839 } 4840 } 4841 function onScheduleRoot(root, children) { 4842 { 4843 if (injectedHook && typeof injectedHook.onScheduleFiberRoot === 'function') { 4844 try { 4845 injectedHook.onScheduleFiberRoot(rendererID, root, children); 4846 } catch (err) { 4847 if ( !hasLoggedError) { 4848 hasLoggedError = true; 4849 4850 error('React instrumentation encountered an error: %s', err); 4851 } 4852 } 4853 } 4854 } 4855 } 4856 function onCommitRoot(root, eventPriority) { 4857 if (injectedHook && typeof injectedHook.onCommitFiberRoot === 'function') { 4858 try { 4859 var didError = (root.current.flags & DidCapture) === DidCapture; 4860 4861 if (enableProfilerTimer) { 4862 var schedulerPriority; 4863 4864 switch (eventPriority) { 4865 case DiscreteEventPriority: 4866 schedulerPriority = ImmediatePriority; 4867 break; 4868 4869 case ContinuousEventPriority: 4870 schedulerPriority = UserBlockingPriority; 4871 break; 4872 4873 case DefaultEventPriority: 4874 schedulerPriority = NormalPriority; 4875 break; 4876 4877 case IdleEventPriority: 4878 schedulerPriority = IdlePriority; 4879 break; 4880 4881 default: 4882 schedulerPriority = NormalPriority; 4883 break; 4884 } 4885 4886 injectedHook.onCommitFiberRoot(rendererID, root, schedulerPriority, didError); 4887 } else { 4888 injectedHook.onCommitFiberRoot(rendererID, root, undefined, didError); 4889 } 4890 } catch (err) { 4891 { 4892 if (!hasLoggedError) { 4893 hasLoggedError = true; 4894 4895 error('React instrumentation encountered an error: %s', err); 4896 } 4897 } 4898 } 4899 } 4900 } 4901 function onPostCommitRoot(root) { 4902 if (injectedHook && typeof injectedHook.onPostCommitFiberRoot === 'function') { 4903 try { 4904 injectedHook.onPostCommitFiberRoot(rendererID, root); 4905 } catch (err) { 4906 { 4907 if (!hasLoggedError) { 4908 hasLoggedError = true; 4909 4910 error('React instrumentation encountered an error: %s', err); 4911 } 4912 } 4913 } 4914 } 4915 } 4916 function onCommitUnmount(fiber) { 4917 if (injectedHook && typeof injectedHook.onCommitFiberUnmount === 'function') { 4918 try { 4919 injectedHook.onCommitFiberUnmount(rendererID, fiber); 4920 } catch (err) { 4921 { 4922 if (!hasLoggedError) { 4923 hasLoggedError = true; 4924 4925 error('React instrumentation encountered an error: %s', err); 4926 } 4927 } 4928 } 4929 } 4930 } 4931 function setIsStrictModeForDevtools(newIsStrictMode) { 4932 { 4933 if (typeof unstable_yieldValue$1 === 'function') { 4934 // We're in a test because Scheduler.unstable_yieldValue only exists 4935 // in SchedulerMock. To reduce the noise in strict mode tests, 4936 // suppress warnings and disable scheduler yielding during the double render 4937 unstable_setDisableYieldValue$1(newIsStrictMode); 4938 setSuppressWarning(newIsStrictMode); 4939 } 4940 4941 if (injectedHook && typeof injectedHook.setStrictMode === 'function') { 4942 try { 4943 injectedHook.setStrictMode(rendererID, newIsStrictMode); 4944 } catch (err) { 4945 { 4946 if (!hasLoggedError) { 4947 hasLoggedError = true; 4948 4949 error('React instrumentation encountered an error: %s', err); 4950 } 4951 } 4952 } 4953 } 4954 } 4955 } // Profiler API hooks 4956 4957 function injectProfilingHooks(profilingHooks) { 4958 injectedProfilingHooks = profilingHooks; 4959 } 4960 4961 function getLaneLabelMap() { 4962 { 4963 var map = new Map(); 4964 var lane = 1; 4965 4966 for (var index = 0; index < TotalLanes; index++) { 4967 var label = getLabelForLane(lane); 4968 map.set(lane, label); 4969 lane *= 2; 4970 } 4971 4972 return map; 4973 } 4974 } 4975 4976 function markCommitStarted(lanes) { 4977 { 4978 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStarted === 'function') { 4979 injectedProfilingHooks.markCommitStarted(lanes); 4980 } 4981 } 4982 } 4983 function markCommitStopped() { 4984 { 4985 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStopped === 'function') { 4986 injectedProfilingHooks.markCommitStopped(); 4987 } 4988 } 4989 } 4990 function markComponentRenderStarted(fiber) { 4991 { 4992 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStarted === 'function') { 4993 injectedProfilingHooks.markComponentRenderStarted(fiber); 4994 } 4995 } 4996 } 4997 function markComponentRenderStopped() { 4998 { 4999 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStopped === 'function') { 5000 injectedProfilingHooks.markComponentRenderStopped(); 5001 } 5002 } 5003 } 5004 function markComponentPassiveEffectMountStarted(fiber) { 5005 { 5006 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === 'function') { 5007 injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); 5008 } 5009 } 5010 } 5011 function markComponentPassiveEffectMountStopped() { 5012 { 5013 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === 'function') { 5014 injectedProfilingHooks.markComponentPassiveEffectMountStopped(); 5015 } 5016 } 5017 } 5018 function markComponentPassiveEffectUnmountStarted(fiber) { 5019 { 5020 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === 'function') { 5021 injectedProfilingHooks.markComponentPassiveEffectUnmountStarted(fiber); 5022 } 5023 } 5024 } 5025 function markComponentPassiveEffectUnmountStopped() { 5026 { 5027 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === 'function') { 5028 injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); 5029 } 5030 } 5031 } 5032 function markComponentLayoutEffectMountStarted(fiber) { 5033 { 5034 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === 'function') { 5035 injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); 5036 } 5037 } 5038 } 5039 function markComponentLayoutEffectMountStopped() { 5040 { 5041 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === 'function') { 5042 injectedProfilingHooks.markComponentLayoutEffectMountStopped(); 5043 } 5044 } 5045 } 5046 function markComponentLayoutEffectUnmountStarted(fiber) { 5047 { 5048 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === 'function') { 5049 injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); 5050 } 5051 } 5052 } 5053 function markComponentLayoutEffectUnmountStopped() { 5054 { 5055 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === 'function') { 5056 injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); 5057 } 5058 } 5059 } 5060 function markComponentErrored(fiber, thrownValue, lanes) { 5061 { 5062 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentErrored === 'function') { 5063 injectedProfilingHooks.markComponentErrored(fiber, thrownValue, lanes); 5064 } 5065 } 5066 } 5067 function markComponentSuspended(fiber, wakeable, lanes) { 5068 { 5069 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentSuspended === 'function') { 5070 injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); 5071 } 5072 } 5073 } 5074 function markLayoutEffectsStarted(lanes) { 5075 { 5076 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStarted === 'function') { 5077 injectedProfilingHooks.markLayoutEffectsStarted(lanes); 5078 } 5079 } 5080 } 5081 function markLayoutEffectsStopped() { 5082 { 5083 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStopped === 'function') { 5084 injectedProfilingHooks.markLayoutEffectsStopped(); 5085 } 5086 } 5087 } 5088 function markPassiveEffectsStarted(lanes) { 5089 { 5090 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStarted === 'function') { 5091 injectedProfilingHooks.markPassiveEffectsStarted(lanes); 5092 } 5093 } 5094 } 5095 function markPassiveEffectsStopped() { 5096 { 5097 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStopped === 'function') { 5098 injectedProfilingHooks.markPassiveEffectsStopped(); 5099 } 5100 } 5101 } 5102 function markRenderStarted(lanes) { 5103 { 5104 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStarted === 'function') { 5105 injectedProfilingHooks.markRenderStarted(lanes); 5106 } 5107 } 5108 } 5109 function markRenderYielded() { 5110 { 5111 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderYielded === 'function') { 5112 injectedProfilingHooks.markRenderYielded(); 5113 } 5114 } 5115 } 5116 function markRenderStopped() { 5117 { 5118 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStopped === 'function') { 5119 injectedProfilingHooks.markRenderStopped(); 5120 } 5121 } 5122 } 5123 function markRenderScheduled(lane) { 5124 { 5125 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderScheduled === 'function') { 5126 injectedProfilingHooks.markRenderScheduled(lane); 5127 } 5128 } 5129 } 5130 function markForceUpdateScheduled(fiber, lane) { 5131 { 5132 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markForceUpdateScheduled === 'function') { 5133 injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); 5134 } 5135 } 5136 } 5137 function markStateUpdateScheduled(fiber, lane) { 5138 { 5139 if (injectedProfilingHooks !== null && typeof injectedProfilingHooks.markStateUpdateScheduled === 'function') { 5140 injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); 5141 } 5142 } 5143 } 5144 5145 var NoMode = 5146 /* */ 5147 0; // TODO: Remove ConcurrentMode by reading from the root tag instead 5148 5149 var ConcurrentMode = 5150 /* */ 5151 1; 5152 var ProfileMode = 5153 /* */ 5154 2; 5155 var StrictLegacyMode = 5156 /* */ 5157 8; 5158 var StrictEffectsMode = 5159 /* */ 5160 16; 5161 5162 // TODO: This is pretty well supported by browsers. Maybe we can drop it. 5163 var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. 5164 // Based on: 5165 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 5166 5167 var log = Math.log; 5168 var LN2 = Math.LN2; 5169 5170 function clz32Fallback(x) { 5171 var asUint = x >>> 0; 5172 5173 if (asUint === 0) { 5174 return 32; 5175 } 5176 5177 return 31 - (log(asUint) / LN2 | 0) | 0; 5178 } 5179 5180 // If those values are changed that package should be rebuilt and redeployed. 5181 5182 var TotalLanes = 31; 5183 var NoLanes = 5184 /* */ 5185 0; 5186 var NoLane = 5187 /* */ 5188 0; 5189 var SyncLane = 5190 /* */ 5191 1; 5192 var InputContinuousHydrationLane = 5193 /* */ 5194 2; 5195 var InputContinuousLane = 5196 /* */ 5197 4; 5198 var DefaultHydrationLane = 5199 /* */ 5200 8; 5201 var DefaultLane = 5202 /* */ 5203 16; 5204 var TransitionHydrationLane = 5205 /* */ 5206 32; 5207 var TransitionLanes = 5208 /* */ 5209 4194240; 5210 var TransitionLane1 = 5211 /* */ 5212 64; 5213 var TransitionLane2 = 5214 /* */ 5215 128; 5216 var TransitionLane3 = 5217 /* */ 5218 256; 5219 var TransitionLane4 = 5220 /* */ 5221 512; 5222 var TransitionLane5 = 5223 /* */ 5224 1024; 5225 var TransitionLane6 = 5226 /* */ 5227 2048; 5228 var TransitionLane7 = 5229 /* */ 5230 4096; 5231 var TransitionLane8 = 5232 /* */ 5233 8192; 5234 var TransitionLane9 = 5235 /* */ 5236 16384; 5237 var TransitionLane10 = 5238 /* */ 5239 32768; 5240 var TransitionLane11 = 5241 /* */ 5242 65536; 5243 var TransitionLane12 = 5244 /* */ 5245 131072; 5246 var TransitionLane13 = 5247 /* */ 5248 262144; 5249 var TransitionLane14 = 5250 /* */ 5251 524288; 5252 var TransitionLane15 = 5253 /* */ 5254 1048576; 5255 var TransitionLane16 = 5256 /* */ 5257 2097152; 5258 var RetryLanes = 5259 /* */ 5260 130023424; 5261 var RetryLane1 = 5262 /* */ 5263 4194304; 5264 var RetryLane2 = 5265 /* */ 5266 8388608; 5267 var RetryLane3 = 5268 /* */ 5269 16777216; 5270 var RetryLane4 = 5271 /* */ 5272 33554432; 5273 var RetryLane5 = 5274 /* */ 5275 67108864; 5276 var SomeRetryLane = RetryLane1; 5277 var SelectiveHydrationLane = 5278 /* */ 5279 134217728; 5280 var NonIdleLanes = 5281 /* */ 5282 268435455; 5283 var IdleHydrationLane = 5284 /* */ 5285 268435456; 5286 var IdleLane = 5287 /* */ 5288 536870912; 5289 var OffscreenLane = 5290 /* */ 5291 1073741824; // This function is used for the experimental timeline (react-devtools-timeline) 5292 // It should be kept in sync with the Lanes values above. 5293 5294 function getLabelForLane(lane) { 5295 { 5296 if (lane & SyncLane) { 5297 return 'Sync'; 5298 } 5299 5300 if (lane & InputContinuousHydrationLane) { 5301 return 'InputContinuousHydration'; 5302 } 5303 5304 if (lane & InputContinuousLane) { 5305 return 'InputContinuous'; 5306 } 5307 5308 if (lane & DefaultHydrationLane) { 5309 return 'DefaultHydration'; 5310 } 5311 5312 if (lane & DefaultLane) { 5313 return 'Default'; 5314 } 5315 5316 if (lane & TransitionHydrationLane) { 5317 return 'TransitionHydration'; 5318 } 5319 5320 if (lane & TransitionLanes) { 5321 return 'Transition'; 5322 } 5323 5324 if (lane & RetryLanes) { 5325 return 'Retry'; 5326 } 5327 5328 if (lane & SelectiveHydrationLane) { 5329 return 'SelectiveHydration'; 5330 } 5331 5332 if (lane & IdleHydrationLane) { 5333 return 'IdleHydration'; 5334 } 5335 5336 if (lane & IdleLane) { 5337 return 'Idle'; 5338 } 5339 5340 if (lane & OffscreenLane) { 5341 return 'Offscreen'; 5342 } 5343 } 5344 } 5345 var NoTimestamp = -1; 5346 var nextTransitionLane = TransitionLane1; 5347 var nextRetryLane = RetryLane1; 5348 5349 function getHighestPriorityLanes(lanes) { 5350 switch (getHighestPriorityLane(lanes)) { 5351 case SyncLane: 5352 return SyncLane; 5353 5354 case InputContinuousHydrationLane: 5355 return InputContinuousHydrationLane; 5356 5357 case InputContinuousLane: 5358 return InputContinuousLane; 5359 5360 case DefaultHydrationLane: 5361 return DefaultHydrationLane; 5362 5363 case DefaultLane: 5364 return DefaultLane; 5365 5366 case TransitionHydrationLane: 5367 return TransitionHydrationLane; 5368 5369 case TransitionLane1: 5370 case TransitionLane2: 5371 case TransitionLane3: 5372 case TransitionLane4: 5373 case TransitionLane5: 5374 case TransitionLane6: 5375 case TransitionLane7: 5376 case TransitionLane8: 5377 case TransitionLane9: 5378 case TransitionLane10: 5379 case TransitionLane11: 5380 case TransitionLane12: 5381 case TransitionLane13: 5382 case TransitionLane14: 5383 case TransitionLane15: 5384 case TransitionLane16: 5385 return lanes & TransitionLanes; 5386 5387 case RetryLane1: 5388 case RetryLane2: 5389 case RetryLane3: 5390 case RetryLane4: 5391 case RetryLane5: 5392 return lanes & RetryLanes; 5393 5394 case SelectiveHydrationLane: 5395 return SelectiveHydrationLane; 5396 5397 case IdleHydrationLane: 5398 return IdleHydrationLane; 5399 5400 case IdleLane: 5401 return IdleLane; 5402 5403 case OffscreenLane: 5404 return OffscreenLane; 5405 5406 default: 5407 { 5408 error('Should have found matching lanes. This is a bug in React.'); 5409 } // This shouldn't be reachable, but as a fallback, return the entire bitmask. 5410 5411 5412 return lanes; 5413 } 5414 } 5415 5416 function getNextLanes(root, wipLanes) { 5417 // Early bailout if there's no pending work left. 5418 var pendingLanes = root.pendingLanes; 5419 5420 if (pendingLanes === NoLanes) { 5421 return NoLanes; 5422 } 5423 5424 var nextLanes = NoLanes; 5425 var suspendedLanes = root.suspendedLanes; 5426 var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, 5427 // even if the work is suspended. 5428 5429 var nonIdlePendingLanes = pendingLanes & NonIdleLanes; 5430 5431 if (nonIdlePendingLanes !== NoLanes) { 5432 var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; 5433 5434 if (nonIdleUnblockedLanes !== NoLanes) { 5435 nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); 5436 } else { 5437 var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; 5438 5439 if (nonIdlePingedLanes !== NoLanes) { 5440 nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); 5441 } 5442 } 5443 } else { 5444 // The only remaining work is Idle. 5445 var unblockedLanes = pendingLanes & ~suspendedLanes; 5446 5447 if (unblockedLanes !== NoLanes) { 5448 nextLanes = getHighestPriorityLanes(unblockedLanes); 5449 } else { 5450 if (pingedLanes !== NoLanes) { 5451 nextLanes = getHighestPriorityLanes(pingedLanes); 5452 } 5453 } 5454 } 5455 5456 if (nextLanes === NoLanes) { 5457 // This should only be reachable if we're suspended 5458 // TODO: Consider warning in this path if a fallback timer is not scheduled. 5459 return NoLanes; 5460 } // If we're already in the middle of a render, switching lanes will interrupt 5461 // it and we'll lose our progress. We should only do this if the new lanes are 5462 // higher priority. 5463 5464 5465 if (wipLanes !== NoLanes && wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't 5466 // bother waiting until the root is complete. 5467 (wipLanes & suspendedLanes) === NoLanes) { 5468 var nextLane = getHighestPriorityLane(nextLanes); 5469 var wipLane = getHighestPriorityLane(wipLanes); 5470 5471 if ( // Tests whether the next lane is equal or lower priority than the wip 5472 // one. This works because the bits decrease in priority as you go left. 5473 nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The 5474 // only difference between default updates and transition updates is that 5475 // default updates do not support refresh transitions. 5476 nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) { 5477 // Keep working on the existing in-progress tree. Do not interrupt. 5478 return wipLanes; 5479 } 5480 } 5481 5482 if ((nextLanes & InputContinuousLane) !== NoLanes) { 5483 // When updates are sync by default, we entangle continuous priority updates 5484 // and default updates, so they render in the same batch. The only reason 5485 // they use separate lanes is because continuous updates should interrupt 5486 // transitions, but default updates should not. 5487 nextLanes |= pendingLanes & DefaultLane; 5488 } // Check for entangled lanes and add them to the batch. 5489 // 5490 // A lane is said to be entangled with another when it's not allowed to render 5491 // in a batch that does not also include the other lane. Typically we do this 5492 // when multiple updates have the same source, and we only want to respond to 5493 // the most recent event from that source. 5494 // 5495 // Note that we apply entanglements *after* checking for partial work above. 5496 // This means that if a lane is entangled during an interleaved event while 5497 // it's already rendering, we won't interrupt it. This is intentional, since 5498 // entanglement is usually "best effort": we'll try our best to render the 5499 // lanes in the same batch, but it's not worth throwing out partially 5500 // completed work in order to do it. 5501 // TODO: Reconsider this. The counter-argument is that the partial work 5502 // represents an intermediate state, which we don't want to show to the user. 5503 // And by spending extra time finishing it, we're increasing the amount of 5504 // time it takes to show the final state, which is what they are actually 5505 // waiting for. 5506 // 5507 // For those exceptions where entanglement is semantically important, like 5508 // useMutableSource, we should ensure that there is no partial work at the 5509 // time we apply the entanglement. 5510 5511 5512 var entangledLanes = root.entangledLanes; 5513 5514 if (entangledLanes !== NoLanes) { 5515 var entanglements = root.entanglements; 5516 var lanes = nextLanes & entangledLanes; 5517 5518 while (lanes > 0) { 5519 var index = pickArbitraryLaneIndex(lanes); 5520 var lane = 1 << index; 5521 nextLanes |= entanglements[index]; 5522 lanes &= ~lane; 5523 } 5524 } 5525 5526 return nextLanes; 5527 } 5528 function getMostRecentEventTime(root, lanes) { 5529 var eventTimes = root.eventTimes; 5530 var mostRecentEventTime = NoTimestamp; 5531 5532 while (lanes > 0) { 5533 var index = pickArbitraryLaneIndex(lanes); 5534 var lane = 1 << index; 5535 var eventTime = eventTimes[index]; 5536 5537 if (eventTime > mostRecentEventTime) { 5538 mostRecentEventTime = eventTime; 5539 } 5540 5541 lanes &= ~lane; 5542 } 5543 5544 return mostRecentEventTime; 5545 } 5546 5547 function computeExpirationTime(lane, currentTime) { 5548 switch (lane) { 5549 case SyncLane: 5550 case InputContinuousHydrationLane: 5551 case InputContinuousLane: 5552 // User interactions should expire slightly more quickly. 5553 // 5554 // NOTE: This is set to the corresponding constant as in Scheduler.js. 5555 // When we made it larger, a product metric in www regressed, suggesting 5556 // there's a user interaction that's being starved by a series of 5557 // synchronous updates. If that theory is correct, the proper solution is 5558 // to fix the starvation. However, this scenario supports the idea that 5559 // expiration times are an important safeguard when starvation 5560 // does happen. 5561 return currentTime + 250; 5562 5563 case DefaultHydrationLane: 5564 case DefaultLane: 5565 case TransitionHydrationLane: 5566 case TransitionLane1: 5567 case TransitionLane2: 5568 case TransitionLane3: 5569 case TransitionLane4: 5570 case TransitionLane5: 5571 case TransitionLane6: 5572 case TransitionLane7: 5573 case TransitionLane8: 5574 case TransitionLane9: 5575 case TransitionLane10: 5576 case TransitionLane11: 5577 case TransitionLane12: 5578 case TransitionLane13: 5579 case TransitionLane14: 5580 case TransitionLane15: 5581 case TransitionLane16: 5582 return currentTime + 5000; 5583 5584 case RetryLane1: 5585 case RetryLane2: 5586 case RetryLane3: 5587 case RetryLane4: 5588 case RetryLane5: 5589 // TODO: Retries should be allowed to expire if they are CPU bound for 5590 // too long, but when I made this change it caused a spike in browser 5591 // crashes. There must be some other underlying bug; not super urgent but 5592 // ideally should figure out why and fix it. Unfortunately we don't have 5593 // a repro for the crashes, only detected via production metrics. 5594 return NoTimestamp; 5595 5596 case SelectiveHydrationLane: 5597 case IdleHydrationLane: 5598 case IdleLane: 5599 case OffscreenLane: 5600 // Anything idle priority or lower should never expire. 5601 return NoTimestamp; 5602 5603 default: 5604 { 5605 error('Should have found matching lanes. This is a bug in React.'); 5606 } 5607 5608 return NoTimestamp; 5609 } 5610 } 5611 5612 function markStarvedLanesAsExpired(root, currentTime) { 5613 // TODO: This gets called every time we yield. We can optimize by storing 5614 // the earliest expiration time on the root. Then use that to quickly bail out 5615 // of this function. 5616 var pendingLanes = root.pendingLanes; 5617 var suspendedLanes = root.suspendedLanes; 5618 var pingedLanes = root.pingedLanes; 5619 var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their 5620 // expiration time. If so, we'll assume the update is being starved and mark 5621 // it as expired to force it to finish. 5622 5623 var lanes = pendingLanes; 5624 5625 while (lanes > 0) { 5626 var index = pickArbitraryLaneIndex(lanes); 5627 var lane = 1 << index; 5628 var expirationTime = expirationTimes[index]; 5629 5630 if (expirationTime === NoTimestamp) { 5631 // Found a pending lane with no expiration time. If it's not suspended, or 5632 // if it's pinged, assume it's CPU-bound. Compute a new expiration time 5633 // using the current time. 5634 if ((lane & suspendedLanes) === NoLanes || (lane & pingedLanes) !== NoLanes) { 5635 // Assumes timestamps are monotonically increasing. 5636 expirationTimes[index] = computeExpirationTime(lane, currentTime); 5637 } 5638 } else if (expirationTime <= currentTime) { 5639 // This lane expired 5640 root.expiredLanes |= lane; 5641 } 5642 5643 lanes &= ~lane; 5644 } 5645 } // This returns the highest priority pending lanes regardless of whether they 5646 // are suspended. 5647 5648 function getHighestPriorityPendingLanes(root) { 5649 return getHighestPriorityLanes(root.pendingLanes); 5650 } 5651 function getLanesToRetrySynchronouslyOnError(root) { 5652 var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; 5653 5654 if (everythingButOffscreen !== NoLanes) { 5655 return everythingButOffscreen; 5656 } 5657 5658 if (everythingButOffscreen & OffscreenLane) { 5659 return OffscreenLane; 5660 } 5661 5662 return NoLanes; 5663 } 5664 function includesSyncLane(lanes) { 5665 return (lanes & SyncLane) !== NoLanes; 5666 } 5667 function includesNonIdleWork(lanes) { 5668 return (lanes & NonIdleLanes) !== NoLanes; 5669 } 5670 function includesOnlyRetries(lanes) { 5671 return (lanes & RetryLanes) === lanes; 5672 } 5673 function includesOnlyNonUrgentLanes(lanes) { 5674 var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; 5675 return (lanes & UrgentLanes) === NoLanes; 5676 } 5677 function includesOnlyTransitions(lanes) { 5678 return (lanes & TransitionLanes) === lanes; 5679 } 5680 function includesBlockingLane(root, lanes) { 5681 5682 var SyncDefaultLanes = InputContinuousHydrationLane | InputContinuousLane | DefaultHydrationLane | DefaultLane; 5683 return (lanes & SyncDefaultLanes) !== NoLanes; 5684 } 5685 function includesExpiredLane(root, lanes) { 5686 // This is a separate check from includesBlockingLane because a lane can 5687 // expire after a render has already started. 5688 return (lanes & root.expiredLanes) !== NoLanes; 5689 } 5690 function isTransitionLane(lane) { 5691 return (lane & TransitionLanes) !== NoLanes; 5692 } 5693 function claimNextTransitionLane() { 5694 // Cycle through the lanes, assigning each new transition to the next lane. 5695 // In most cases, this means every transition gets its own lane, until we 5696 // run out of lanes and cycle back to the beginning. 5697 var lane = nextTransitionLane; 5698 nextTransitionLane <<= 1; 5699 5700 if ((nextTransitionLane & TransitionLanes) === NoLanes) { 5701 nextTransitionLane = TransitionLane1; 5702 } 5703 5704 return lane; 5705 } 5706 function claimNextRetryLane() { 5707 var lane = nextRetryLane; 5708 nextRetryLane <<= 1; 5709 5710 if ((nextRetryLane & RetryLanes) === NoLanes) { 5711 nextRetryLane = RetryLane1; 5712 } 5713 5714 return lane; 5715 } 5716 function getHighestPriorityLane(lanes) { 5717 return lanes & -lanes; 5718 } 5719 function pickArbitraryLane(lanes) { 5720 // This wrapper function gets inlined. Only exists so to communicate that it 5721 // doesn't matter which bit is selected; you can pick any bit without 5722 // affecting the algorithms where its used. Here I'm using 5723 // getHighestPriorityLane because it requires the fewest operations. 5724 return getHighestPriorityLane(lanes); 5725 } 5726 5727 function pickArbitraryLaneIndex(lanes) { 5728 return 31 - clz32(lanes); 5729 } 5730 5731 function laneToIndex(lane) { 5732 return pickArbitraryLaneIndex(lane); 5733 } 5734 5735 function includesSomeLane(a, b) { 5736 return (a & b) !== NoLanes; 5737 } 5738 function isSubsetOfLanes(set, subset) { 5739 return (set & subset) === subset; 5740 } 5741 function mergeLanes(a, b) { 5742 return a | b; 5743 } 5744 function removeLanes(set, subset) { 5745 return set & ~subset; 5746 } 5747 function intersectLanes(a, b) { 5748 return a & b; 5749 } // Seems redundant, but it changes the type from a single lane (used for 5750 // updates) to a group of lanes (used for flushing work). 5751 5752 function laneToLanes(lane) { 5753 return lane; 5754 } 5755 function higherPriorityLane(a, b) { 5756 // This works because the bit ranges decrease in priority as you go left. 5757 return a !== NoLane && a < b ? a : b; 5758 } 5759 function createLaneMap(initial) { 5760 // Intentionally pushing one by one. 5761 // https://v8.dev/blog/elements-kinds#avoid-creating-holes 5762 var laneMap = []; 5763 5764 for (var i = 0; i < TotalLanes; i++) { 5765 laneMap.push(initial); 5766 } 5767 5768 return laneMap; 5769 } 5770 function markRootUpdated(root, updateLane, eventTime) { 5771 root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update 5772 // could unblock them. Clear the suspended lanes so that we can try rendering 5773 // them again. 5774 // 5775 // TODO: We really only need to unsuspend only lanes that are in the 5776 // `subtreeLanes` of the updated fiber, or the update lanes of the return 5777 // path. This would exclude suspended updates in an unrelated sibling tree, 5778 // since there's no way for this update to unblock it. 5779 // 5780 // We don't do this if the incoming update is idle, because we never process 5781 // idle updates until after all the regular updates have finished; there's no 5782 // way it could unblock a transition. 5783 5784 if (updateLane !== IdleLane) { 5785 root.suspendedLanes = NoLanes; 5786 root.pingedLanes = NoLanes; 5787 } 5788 5789 var eventTimes = root.eventTimes; 5790 var index = laneToIndex(updateLane); // We can always overwrite an existing timestamp because we prefer the most 5791 // recent event, and we assume time is monotonically increasing. 5792 5793 eventTimes[index] = eventTime; 5794 } 5795 function markRootSuspended(root, suspendedLanes) { 5796 root.suspendedLanes |= suspendedLanes; 5797 root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. 5798 5799 var expirationTimes = root.expirationTimes; 5800 var lanes = suspendedLanes; 5801 5802 while (lanes > 0) { 5803 var index = pickArbitraryLaneIndex(lanes); 5804 var lane = 1 << index; 5805 expirationTimes[index] = NoTimestamp; 5806 lanes &= ~lane; 5807 } 5808 } 5809 function markRootPinged(root, pingedLanes, eventTime) { 5810 root.pingedLanes |= root.suspendedLanes & pingedLanes; 5811 } 5812 function markRootFinished(root, remainingLanes) { 5813 var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; 5814 root.pendingLanes = remainingLanes; // Let's try everything again 5815 5816 root.suspendedLanes = NoLanes; 5817 root.pingedLanes = NoLanes; 5818 root.expiredLanes &= remainingLanes; 5819 root.mutableReadLanes &= remainingLanes; 5820 root.entangledLanes &= remainingLanes; 5821 var entanglements = root.entanglements; 5822 var eventTimes = root.eventTimes; 5823 var expirationTimes = root.expirationTimes; // Clear the lanes that no longer have pending work 5824 5825 var lanes = noLongerPendingLanes; 5826 5827 while (lanes > 0) { 5828 var index = pickArbitraryLaneIndex(lanes); 5829 var lane = 1 << index; 5830 entanglements[index] = NoLanes; 5831 eventTimes[index] = NoTimestamp; 5832 expirationTimes[index] = NoTimestamp; 5833 lanes &= ~lane; 5834 } 5835 } 5836 function markRootEntangled(root, entangledLanes) { 5837 // In addition to entangling each of the given lanes with each other, we also 5838 // have to consider _transitive_ entanglements. For each lane that is already 5839 // entangled with *any* of the given lanes, that lane is now transitively 5840 // entangled with *all* the given lanes. 5841 // 5842 // Translated: If C is entangled with A, then entangling A with B also 5843 // entangles C with B. 5844 // 5845 // If this is hard to grasp, it might help to intentionally break this 5846 // function and look at the tests that fail in ReactTransition-test.js. Try 5847 // commenting out one of the conditions below. 5848 var rootEntangledLanes = root.entangledLanes |= entangledLanes; 5849 var entanglements = root.entanglements; 5850 var lanes = rootEntangledLanes; 5851 5852 while (lanes) { 5853 var index = pickArbitraryLaneIndex(lanes); 5854 var lane = 1 << index; 5855 5856 if ( // Is this one of the newly entangled lanes? 5857 lane & entangledLanes | // Is this lane transitively entangled with the newly entangled lanes? 5858 entanglements[index] & entangledLanes) { 5859 entanglements[index] |= entangledLanes; 5860 } 5861 5862 lanes &= ~lane; 5863 } 5864 } 5865 function getBumpedLaneForHydration(root, renderLanes) { 5866 var renderLane = getHighestPriorityLane(renderLanes); 5867 var lane; 5868 5869 switch (renderLane) { 5870 case InputContinuousLane: 5871 lane = InputContinuousHydrationLane; 5872 break; 5873 5874 case DefaultLane: 5875 lane = DefaultHydrationLane; 5876 break; 5877 5878 case TransitionLane1: 5879 case TransitionLane2: 5880 case TransitionLane3: 5881 case TransitionLane4: 5882 case TransitionLane5: 5883 case TransitionLane6: 5884 case TransitionLane7: 5885 case TransitionLane8: 5886 case TransitionLane9: 5887 case TransitionLane10: 5888 case TransitionLane11: 5889 case TransitionLane12: 5890 case TransitionLane13: 5891 case TransitionLane14: 5892 case TransitionLane15: 5893 case TransitionLane16: 5894 case RetryLane1: 5895 case RetryLane2: 5896 case RetryLane3: 5897 case RetryLane4: 5898 case RetryLane5: 5899 lane = TransitionHydrationLane; 5900 break; 5901 5902 case IdleLane: 5903 lane = IdleHydrationLane; 5904 break; 5905 5906 default: 5907 // Everything else is already either a hydration lane, or shouldn't 5908 // be retried at a hydration lane. 5909 lane = NoLane; 5910 break; 5911 } // Check if the lane we chose is suspended. If so, that indicates that we 5912 // already attempted and failed to hydrate at that level. Also check if we're 5913 // already rendering that lane, which is rare but could happen. 5914 5915 5916 if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { 5917 // Give up trying to hydrate and fall back to client render. 5918 return NoLane; 5919 } 5920 5921 return lane; 5922 } 5923 function addFiberToLanesMap(root, fiber, lanes) { 5924 5925 if (!isDevToolsPresent) { 5926 return; 5927 } 5928 5929 var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; 5930 5931 while (lanes > 0) { 5932 var index = laneToIndex(lanes); 5933 var lane = 1 << index; 5934 var updaters = pendingUpdatersLaneMap[index]; 5935 updaters.add(fiber); 5936 lanes &= ~lane; 5937 } 5938 } 5939 function movePendingFibersToMemoized(root, lanes) { 5940 5941 if (!isDevToolsPresent) { 5942 return; 5943 } 5944 5945 var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; 5946 var memoizedUpdaters = root.memoizedUpdaters; 5947 5948 while (lanes > 0) { 5949 var index = laneToIndex(lanes); 5950 var lane = 1 << index; 5951 var updaters = pendingUpdatersLaneMap[index]; 5952 5953 if (updaters.size > 0) { 5954 updaters.forEach(function (fiber) { 5955 var alternate = fiber.alternate; 5956 5957 if (alternate === null || !memoizedUpdaters.has(alternate)) { 5958 memoizedUpdaters.add(fiber); 5959 } 5960 }); 5961 updaters.clear(); 5962 } 5963 5964 lanes &= ~lane; 5965 } 5966 } 5967 function getTransitionsForLanes(root, lanes) { 5968 { 5969 return null; 5970 } 5971 } 5972 5973 var DiscreteEventPriority = SyncLane; 5974 var ContinuousEventPriority = InputContinuousLane; 5975 var DefaultEventPriority = DefaultLane; 5976 var IdleEventPriority = IdleLane; 5977 var currentUpdatePriority = NoLane; 5978 function getCurrentUpdatePriority() { 5979 return currentUpdatePriority; 5980 } 5981 function setCurrentUpdatePriority(newPriority) { 5982 currentUpdatePriority = newPriority; 5983 } 5984 function runWithPriority(priority, fn) { 5985 var previousPriority = currentUpdatePriority; 5986 5987 try { 5988 currentUpdatePriority = priority; 5989 return fn(); 5990 } finally { 5991 currentUpdatePriority = previousPriority; 5992 } 5993 } 5994 function higherEventPriority(a, b) { 5995 return a !== 0 && a < b ? a : b; 5996 } 5997 function lowerEventPriority(a, b) { 5998 return a === 0 || a > b ? a : b; 5999 } 6000 function isHigherEventPriority(a, b) { 6001 return a !== 0 && a < b; 6002 } 6003 function lanesToEventPriority(lanes) { 6004 var lane = getHighestPriorityLane(lanes); 6005 6006 if (!isHigherEventPriority(DiscreteEventPriority, lane)) { 6007 return DiscreteEventPriority; 6008 } 6009 6010 if (!isHigherEventPriority(ContinuousEventPriority, lane)) { 6011 return ContinuousEventPriority; 6012 } 6013 6014 if (includesNonIdleWork(lane)) { 6015 return DefaultEventPriority; 6016 } 6017 6018 return IdleEventPriority; 6019 } 6020 6021 // This is imported by the event replaying implementation in React DOM. It's 6022 // in a separate file to break a circular dependency between the renderer and 6023 // the reconciler. 6024 function isRootDehydrated(root) { 6025 var currentState = root.current.memoizedState; 6026 return currentState.isDehydrated; 6027 } 6028 6029 var _attemptSynchronousHydration; 6030 6031 function setAttemptSynchronousHydration(fn) { 6032 _attemptSynchronousHydration = fn; 6033 } 6034 function attemptSynchronousHydration(fiber) { 6035 _attemptSynchronousHydration(fiber); 6036 } 6037 var attemptContinuousHydration; 6038 function setAttemptContinuousHydration(fn) { 6039 attemptContinuousHydration = fn; 6040 } 6041 var attemptHydrationAtCurrentPriority; 6042 function setAttemptHydrationAtCurrentPriority(fn) { 6043 attemptHydrationAtCurrentPriority = fn; 6044 } 6045 var getCurrentUpdatePriority$1; 6046 function setGetCurrentUpdatePriority(fn) { 6047 getCurrentUpdatePriority$1 = fn; 6048 } 6049 var attemptHydrationAtPriority; 6050 function setAttemptHydrationAtPriority(fn) { 6051 attemptHydrationAtPriority = fn; 6052 } // TODO: Upgrade this definition once we're on a newer version of Flow that 6053 // has this definition built-in. 6054 6055 var hasScheduledReplayAttempt = false; // The queue of discrete events to be replayed. 6056 6057 var queuedDiscreteEvents = []; // Indicates if any continuous event targets are non-null for early bailout. 6058 // if the last target was dehydrated. 6059 6060 var queuedFocus = null; 6061 var queuedDrag = null; 6062 var queuedMouse = null; // For pointer events there can be one latest event per pointerId. 6063 6064 var queuedPointers = new Map(); 6065 var queuedPointerCaptures = new Map(); // We could consider replaying selectionchange and touchmoves too. 6066 6067 var queuedExplicitHydrationTargets = []; 6068 var discreteReplayableEvents = ['mousedown', 'mouseup', 'touchcancel', 'touchend', 'touchstart', 'auxclick', 'dblclick', 'pointercancel', 'pointerdown', 'pointerup', 'dragend', 'dragstart', 'drop', 'compositionend', 'compositionstart', 'keydown', 'keypress', 'keyup', 'input', 'textInput', // Intentionally camelCase 6069 'copy', 'cut', 'paste', 'click', 'change', 'contextmenu', 'reset', 'submit']; 6070 function isDiscreteEventThatRequiresHydration(eventType) { 6071 return discreteReplayableEvents.indexOf(eventType) > -1; 6072 } 6073 6074 function createQueuedReplayableEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6075 return { 6076 blockedOn: blockedOn, 6077 domEventName: domEventName, 6078 eventSystemFlags: eventSystemFlags, 6079 nativeEvent: nativeEvent, 6080 targetContainers: [targetContainer] 6081 }; 6082 } 6083 6084 function clearIfContinuousEvent(domEventName, nativeEvent) { 6085 switch (domEventName) { 6086 case 'focusin': 6087 case 'focusout': 6088 queuedFocus = null; 6089 break; 6090 6091 case 'dragenter': 6092 case 'dragleave': 6093 queuedDrag = null; 6094 break; 6095 6096 case 'mouseover': 6097 case 'mouseout': 6098 queuedMouse = null; 6099 break; 6100 6101 case 'pointerover': 6102 case 'pointerout': 6103 { 6104 var pointerId = nativeEvent.pointerId; 6105 queuedPointers.delete(pointerId); 6106 break; 6107 } 6108 6109 case 'gotpointercapture': 6110 case 'lostpointercapture': 6111 { 6112 var _pointerId = nativeEvent.pointerId; 6113 queuedPointerCaptures.delete(_pointerId); 6114 break; 6115 } 6116 } 6117 } 6118 6119 function accumulateOrCreateContinuousQueuedReplayableEvent(existingQueuedEvent, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6120 if (existingQueuedEvent === null || existingQueuedEvent.nativeEvent !== nativeEvent) { 6121 var queuedEvent = createQueuedReplayableEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent); 6122 6123 if (blockedOn !== null) { 6124 var _fiber2 = getInstanceFromNode(blockedOn); 6125 6126 if (_fiber2 !== null) { 6127 // Attempt to increase the priority of this target. 6128 attemptContinuousHydration(_fiber2); 6129 } 6130 } 6131 6132 return queuedEvent; 6133 } // If we have already queued this exact event, then it's because 6134 // the different event systems have different DOM event listeners. 6135 // We can accumulate the flags, and the targetContainers, and 6136 // store a single event to be replayed. 6137 6138 6139 existingQueuedEvent.eventSystemFlags |= eventSystemFlags; 6140 var targetContainers = existingQueuedEvent.targetContainers; 6141 6142 if (targetContainer !== null && targetContainers.indexOf(targetContainer) === -1) { 6143 targetContainers.push(targetContainer); 6144 } 6145 6146 return existingQueuedEvent; 6147 } 6148 6149 function queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6150 // These set relatedTarget to null because the replayed event will be treated as if we 6151 // moved from outside the window (no target) onto the target once it hydrates. 6152 // Instead of mutating we could clone the event. 6153 switch (domEventName) { 6154 case 'focusin': 6155 { 6156 var focusEvent = nativeEvent; 6157 queuedFocus = accumulateOrCreateContinuousQueuedReplayableEvent(queuedFocus, blockedOn, domEventName, eventSystemFlags, targetContainer, focusEvent); 6158 return true; 6159 } 6160 6161 case 'dragenter': 6162 { 6163 var dragEvent = nativeEvent; 6164 queuedDrag = accumulateOrCreateContinuousQueuedReplayableEvent(queuedDrag, blockedOn, domEventName, eventSystemFlags, targetContainer, dragEvent); 6165 return true; 6166 } 6167 6168 case 'mouseover': 6169 { 6170 var mouseEvent = nativeEvent; 6171 queuedMouse = accumulateOrCreateContinuousQueuedReplayableEvent(queuedMouse, blockedOn, domEventName, eventSystemFlags, targetContainer, mouseEvent); 6172 return true; 6173 } 6174 6175 case 'pointerover': 6176 { 6177 var pointerEvent = nativeEvent; 6178 var pointerId = pointerEvent.pointerId; 6179 queuedPointers.set(pointerId, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointers.get(pointerId) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, pointerEvent)); 6180 return true; 6181 } 6182 6183 case 'gotpointercapture': 6184 { 6185 var _pointerEvent = nativeEvent; 6186 var _pointerId2 = _pointerEvent.pointerId; 6187 queuedPointerCaptures.set(_pointerId2, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointerCaptures.get(_pointerId2) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, _pointerEvent)); 6188 return true; 6189 } 6190 } 6191 6192 return false; 6193 } // Check if this target is unblocked. Returns true if it's unblocked. 6194 6195 function attemptExplicitHydrationTarget(queuedTarget) { 6196 // TODO: This function shares a lot of logic with findInstanceBlockingEvent. 6197 // Try to unify them. It's a bit tricky since it would require two return 6198 // values. 6199 var targetInst = getClosestInstanceFromNode(queuedTarget.target); 6200 6201 if (targetInst !== null) { 6202 var nearestMounted = getNearestMountedFiber(targetInst); 6203 6204 if (nearestMounted !== null) { 6205 var tag = nearestMounted.tag; 6206 6207 if (tag === SuspenseComponent) { 6208 var instance = getSuspenseInstanceFromFiber(nearestMounted); 6209 6210 if (instance !== null) { 6211 // We're blocked on hydrating this boundary. 6212 // Increase its priority. 6213 queuedTarget.blockedOn = instance; 6214 attemptHydrationAtPriority(queuedTarget.priority, function () { 6215 attemptHydrationAtCurrentPriority(nearestMounted); 6216 }); 6217 return; 6218 } 6219 } else if (tag === HostRoot) { 6220 var root = nearestMounted.stateNode; 6221 6222 if (isRootDehydrated(root)) { 6223 queuedTarget.blockedOn = getContainerFromFiber(nearestMounted); // We don't currently have a way to increase the priority of 6224 // a root other than sync. 6225 6226 return; 6227 } 6228 } 6229 } 6230 } 6231 6232 queuedTarget.blockedOn = null; 6233 } 6234 6235 function queueExplicitHydrationTarget(target) { 6236 // TODO: This will read the priority if it's dispatched by the React 6237 // event system but not native events. Should read window.event.type, like 6238 // we do for updates (getCurrentEventPriority). 6239 var updatePriority = getCurrentUpdatePriority$1(); 6240 var queuedTarget = { 6241 blockedOn: null, 6242 target: target, 6243 priority: updatePriority 6244 }; 6245 var i = 0; 6246 6247 for (; i < queuedExplicitHydrationTargets.length; i++) { 6248 // Stop once we hit the first target with lower priority than 6249 if (!isHigherEventPriority(updatePriority, queuedExplicitHydrationTargets[i].priority)) { 6250 break; 6251 } 6252 } 6253 6254 queuedExplicitHydrationTargets.splice(i, 0, queuedTarget); 6255 6256 if (i === 0) { 6257 attemptExplicitHydrationTarget(queuedTarget); 6258 } 6259 } 6260 6261 function attemptReplayContinuousQueuedEvent(queuedEvent) { 6262 if (queuedEvent.blockedOn !== null) { 6263 return false; 6264 } 6265 6266 var targetContainers = queuedEvent.targetContainers; 6267 6268 while (targetContainers.length > 0) { 6269 var targetContainer = targetContainers[0]; 6270 var nextBlockedOn = findInstanceBlockingEvent(queuedEvent.domEventName, queuedEvent.eventSystemFlags, targetContainer, queuedEvent.nativeEvent); 6271 6272 if (nextBlockedOn === null) { 6273 { 6274 var nativeEvent = queuedEvent.nativeEvent; 6275 var nativeEventClone = new nativeEvent.constructor(nativeEvent.type, nativeEvent); 6276 setReplayingEvent(nativeEventClone); 6277 nativeEvent.target.dispatchEvent(nativeEventClone); 6278 resetReplayingEvent(); 6279 } 6280 } else { 6281 // We're still blocked. Try again later. 6282 var _fiber3 = getInstanceFromNode(nextBlockedOn); 6283 6284 if (_fiber3 !== null) { 6285 attemptContinuousHydration(_fiber3); 6286 } 6287 6288 queuedEvent.blockedOn = nextBlockedOn; 6289 return false; 6290 } // This target container was successfully dispatched. Try the next. 6291 6292 6293 targetContainers.shift(); 6294 } 6295 6296 return true; 6297 } 6298 6299 function attemptReplayContinuousQueuedEventInMap(queuedEvent, key, map) { 6300 if (attemptReplayContinuousQueuedEvent(queuedEvent)) { 6301 map.delete(key); 6302 } 6303 } 6304 6305 function replayUnblockedEvents() { 6306 hasScheduledReplayAttempt = false; 6307 6308 6309 if (queuedFocus !== null && attemptReplayContinuousQueuedEvent(queuedFocus)) { 6310 queuedFocus = null; 6311 } 6312 6313 if (queuedDrag !== null && attemptReplayContinuousQueuedEvent(queuedDrag)) { 6314 queuedDrag = null; 6315 } 6316 6317 if (queuedMouse !== null && attemptReplayContinuousQueuedEvent(queuedMouse)) { 6318 queuedMouse = null; 6319 } 6320 6321 queuedPointers.forEach(attemptReplayContinuousQueuedEventInMap); 6322 queuedPointerCaptures.forEach(attemptReplayContinuousQueuedEventInMap); 6323 } 6324 6325 function scheduleCallbackIfUnblocked(queuedEvent, unblocked) { 6326 if (queuedEvent.blockedOn === unblocked) { 6327 queuedEvent.blockedOn = null; 6328 6329 if (!hasScheduledReplayAttempt) { 6330 hasScheduledReplayAttempt = true; // Schedule a callback to attempt replaying as many events as are 6331 // now unblocked. This first might not actually be unblocked yet. 6332 // We could check it early to avoid scheduling an unnecessary callback. 6333 6334 unstable_scheduleCallback(unstable_NormalPriority, replayUnblockedEvents); 6335 } 6336 } 6337 } 6338 6339 function retryIfBlockedOn(unblocked) { 6340 // Mark anything that was blocked on this as no longer blocked 6341 // and eligible for a replay. 6342 if (queuedDiscreteEvents.length > 0) { 6343 scheduleCallbackIfUnblocked(queuedDiscreteEvents[0], unblocked); // This is a exponential search for each boundary that commits. I think it's 6344 // worth it because we expect very few discrete events to queue up and once 6345 // we are actually fully unblocked it will be fast to replay them. 6346 6347 for (var i = 1; i < queuedDiscreteEvents.length; i++) { 6348 var queuedEvent = queuedDiscreteEvents[i]; 6349 6350 if (queuedEvent.blockedOn === unblocked) { 6351 queuedEvent.blockedOn = null; 6352 } 6353 } 6354 } 6355 6356 if (queuedFocus !== null) { 6357 scheduleCallbackIfUnblocked(queuedFocus, unblocked); 6358 } 6359 6360 if (queuedDrag !== null) { 6361 scheduleCallbackIfUnblocked(queuedDrag, unblocked); 6362 } 6363 6364 if (queuedMouse !== null) { 6365 scheduleCallbackIfUnblocked(queuedMouse, unblocked); 6366 } 6367 6368 var unblock = function (queuedEvent) { 6369 return scheduleCallbackIfUnblocked(queuedEvent, unblocked); 6370 }; 6371 6372 queuedPointers.forEach(unblock); 6373 queuedPointerCaptures.forEach(unblock); 6374 6375 for (var _i = 0; _i < queuedExplicitHydrationTargets.length; _i++) { 6376 var queuedTarget = queuedExplicitHydrationTargets[_i]; 6377 6378 if (queuedTarget.blockedOn === unblocked) { 6379 queuedTarget.blockedOn = null; 6380 } 6381 } 6382 6383 while (queuedExplicitHydrationTargets.length > 0) { 6384 var nextExplicitTarget = queuedExplicitHydrationTargets[0]; 6385 6386 if (nextExplicitTarget.blockedOn !== null) { 6387 // We're still blocked. 6388 break; 6389 } else { 6390 attemptExplicitHydrationTarget(nextExplicitTarget); 6391 6392 if (nextExplicitTarget.blockedOn === null) { 6393 // We're unblocked. 6394 queuedExplicitHydrationTargets.shift(); 6395 } 6396 } 6397 } 6398 } 6399 6400 var ReactCurrentBatchConfig = ReactSharedInternals.ReactCurrentBatchConfig; // TODO: can we stop exporting these? 6401 6402 var _enabled = true; // This is exported in FB builds for use by legacy FB layer infra. 6403 // We'd like to remove this but it's not clear if this is safe. 6404 6405 function setEnabled(enabled) { 6406 _enabled = !!enabled; 6407 } 6408 function isEnabled() { 6409 return _enabled; 6410 } 6411 function createEventListenerWrapperWithPriority(targetContainer, domEventName, eventSystemFlags) { 6412 var eventPriority = getEventPriority(domEventName); 6413 var listenerWrapper; 6414 6415 switch (eventPriority) { 6416 case DiscreteEventPriority: 6417 listenerWrapper = dispatchDiscreteEvent; 6418 break; 6419 6420 case ContinuousEventPriority: 6421 listenerWrapper = dispatchContinuousEvent; 6422 break; 6423 6424 case DefaultEventPriority: 6425 default: 6426 listenerWrapper = dispatchEvent; 6427 break; 6428 } 6429 6430 return listenerWrapper.bind(null, domEventName, eventSystemFlags, targetContainer); 6431 } 6432 6433 function dispatchDiscreteEvent(domEventName, eventSystemFlags, container, nativeEvent) { 6434 var previousPriority = getCurrentUpdatePriority(); 6435 var prevTransition = ReactCurrentBatchConfig.transition; 6436 ReactCurrentBatchConfig.transition = null; 6437 6438 try { 6439 setCurrentUpdatePriority(DiscreteEventPriority); 6440 dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); 6441 } finally { 6442 setCurrentUpdatePriority(previousPriority); 6443 ReactCurrentBatchConfig.transition = prevTransition; 6444 } 6445 } 6446 6447 function dispatchContinuousEvent(domEventName, eventSystemFlags, container, nativeEvent) { 6448 var previousPriority = getCurrentUpdatePriority(); 6449 var prevTransition = ReactCurrentBatchConfig.transition; 6450 ReactCurrentBatchConfig.transition = null; 6451 6452 try { 6453 setCurrentUpdatePriority(ContinuousEventPriority); 6454 dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); 6455 } finally { 6456 setCurrentUpdatePriority(previousPriority); 6457 ReactCurrentBatchConfig.transition = prevTransition; 6458 } 6459 } 6460 6461 function dispatchEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6462 if (!_enabled) { 6463 return; 6464 } 6465 6466 { 6467 dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6468 } 6469 } 6470 6471 function dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6472 var blockedOn = findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6473 6474 if (blockedOn === null) { 6475 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer); 6476 clearIfContinuousEvent(domEventName, nativeEvent); 6477 return; 6478 } 6479 6480 if (queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent)) { 6481 nativeEvent.stopPropagation(); 6482 return; 6483 } // We need to clear only if we didn't queue because 6484 // queueing is accumulative. 6485 6486 6487 clearIfContinuousEvent(domEventName, nativeEvent); 6488 6489 if (eventSystemFlags & IS_CAPTURE_PHASE && isDiscreteEventThatRequiresHydration(domEventName)) { 6490 while (blockedOn !== null) { 6491 var fiber = getInstanceFromNode(blockedOn); 6492 6493 if (fiber !== null) { 6494 attemptSynchronousHydration(fiber); 6495 } 6496 6497 var nextBlockedOn = findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent); 6498 6499 if (nextBlockedOn === null) { 6500 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer); 6501 } 6502 6503 if (nextBlockedOn === blockedOn) { 6504 break; 6505 } 6506 6507 blockedOn = nextBlockedOn; 6508 } 6509 6510 if (blockedOn !== null) { 6511 nativeEvent.stopPropagation(); 6512 } 6513 6514 return; 6515 } // This is not replayable so we'll invoke it but without a target, 6516 // in case the event system needs to trace it. 6517 6518 6519 dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, null, targetContainer); 6520 } 6521 6522 var return_targetInst = null; // Returns a SuspenseInstance or Container if it's blocked. 6523 // The return_targetInst field above is conceptually part of the return value. 6524 6525 function findInstanceBlockingEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) { 6526 // TODO: Warn if _enabled is false. 6527 return_targetInst = null; 6528 var nativeEventTarget = getEventTarget(nativeEvent); 6529 var targetInst = getClosestInstanceFromNode(nativeEventTarget); 6530 6531 if (targetInst !== null) { 6532 var nearestMounted = getNearestMountedFiber(targetInst); 6533 6534 if (nearestMounted === null) { 6535 // This tree has been unmounted already. Dispatch without a target. 6536 targetInst = null; 6537 } else { 6538 var tag = nearestMounted.tag; 6539 6540 if (tag === SuspenseComponent) { 6541 var instance = getSuspenseInstanceFromFiber(nearestMounted); 6542 6543 if (instance !== null) { 6544 // Queue the event to be replayed later. Abort dispatching since we 6545 // don't want this event dispatched twice through the event system. 6546 // TODO: If this is the first discrete event in the queue. Schedule an increased 6547 // priority for this boundary. 6548 return instance; 6549 } // This shouldn't happen, something went wrong but to avoid blocking 6550 // the whole system, dispatch the event without a target. 6551 // TODO: Warn. 6552 6553 6554 targetInst = null; 6555 } else if (tag === HostRoot) { 6556 var root = nearestMounted.stateNode; 6557 6558 if (isRootDehydrated(root)) { 6559 // If this happens during a replay something went wrong and it might block 6560 // the whole system. 6561 return getContainerFromFiber(nearestMounted); 6562 } 6563 6564 targetInst = null; 6565 } else if (nearestMounted !== targetInst) { 6566 // If we get an event (ex: img onload) before committing that 6567 // component's mount, ignore it for now (that is, treat it as if it was an 6568 // event on a non-React tree). We might also consider queueing events and 6569 // dispatching them after the mount. 6570 targetInst = null; 6571 } 6572 } 6573 } 6574 6575 return_targetInst = targetInst; // We're not blocked on anything. 6576 6577 return null; 6578 } 6579 function getEventPriority(domEventName) { 6580 switch (domEventName) { 6581 // Used by SimpleEventPlugin: 6582 case 'cancel': 6583 case 'click': 6584 case 'close': 6585 case 'contextmenu': 6586 case 'copy': 6587 case 'cut': 6588 case 'auxclick': 6589 case 'dblclick': 6590 case 'dragend': 6591 case 'dragstart': 6592 case 'drop': 6593 case 'focusin': 6594 case 'focusout': 6595 case 'input': 6596 case 'invalid': 6597 case 'keydown': 6598 case 'keypress': 6599 case 'keyup': 6600 case 'mousedown': 6601 case 'mouseup': 6602 case 'paste': 6603 case 'pause': 6604 case 'play': 6605 case 'pointercancel': 6606 case 'pointerdown': 6607 case 'pointerup': 6608 case 'ratechange': 6609 case 'reset': 6610 case 'resize': 6611 case 'seeked': 6612 case 'submit': 6613 case 'touchcancel': 6614 case 'touchend': 6615 case 'touchstart': 6616 case 'volumechange': // Used by polyfills: 6617 // eslint-disable-next-line no-fallthrough 6618 6619 case 'change': 6620 case 'selectionchange': 6621 case 'textInput': 6622 case 'compositionstart': 6623 case 'compositionend': 6624 case 'compositionupdate': // Only enableCreateEventHandleAPI: 6625 // eslint-disable-next-line no-fallthrough 6626 6627 case 'beforeblur': 6628 case 'afterblur': // Not used by React but could be by user code: 6629 // eslint-disable-next-line no-fallthrough 6630 6631 case 'beforeinput': 6632 case 'blur': 6633 case 'fullscreenchange': 6634 case 'focus': 6635 case 'hashchange': 6636 case 'popstate': 6637 case 'select': 6638 case 'selectstart': 6639 return DiscreteEventPriority; 6640 6641 case 'drag': 6642 case 'dragenter': 6643 case 'dragexit': 6644 case 'dragleave': 6645 case 'dragover': 6646 case 'mousemove': 6647 case 'mouseout': 6648 case 'mouseover': 6649 case 'pointermove': 6650 case 'pointerout': 6651 case 'pointerover': 6652 case 'scroll': 6653 case 'toggle': 6654 case 'touchmove': 6655 case 'wheel': // Not used by React but could be by user code: 6656 // eslint-disable-next-line no-fallthrough 6657 6658 case 'mouseenter': 6659 case 'mouseleave': 6660 case 'pointerenter': 6661 case 'pointerleave': 6662 return ContinuousEventPriority; 6663 6664 case 'message': 6665 { 6666 // We might be in the Scheduler callback. 6667 // Eventually this mechanism will be replaced by a check 6668 // of the current priority on the native scheduler. 6669 var schedulerPriority = getCurrentPriorityLevel(); 6670 6671 switch (schedulerPriority) { 6672 case ImmediatePriority: 6673 return DiscreteEventPriority; 6674 6675 case UserBlockingPriority: 6676 return ContinuousEventPriority; 6677 6678 case NormalPriority: 6679 case LowPriority: 6680 // TODO: Handle LowSchedulerPriority, somehow. Maybe the same lane as hydration. 6681 return DefaultEventPriority; 6682 6683 case IdlePriority: 6684 return IdleEventPriority; 6685 6686 default: 6687 return DefaultEventPriority; 6688 } 6689 } 6690 6691 default: 6692 return DefaultEventPriority; 6693 } 6694 } 6695 6696 function addEventBubbleListener(target, eventType, listener) { 6697 target.addEventListener(eventType, listener, false); 6698 return listener; 6699 } 6700 function addEventCaptureListener(target, eventType, listener) { 6701 target.addEventListener(eventType, listener, true); 6702 return listener; 6703 } 6704 function addEventCaptureListenerWithPassiveFlag(target, eventType, listener, passive) { 6705 target.addEventListener(eventType, listener, { 6706 capture: true, 6707 passive: passive 6708 }); 6709 return listener; 6710 } 6711 function addEventBubbleListenerWithPassiveFlag(target, eventType, listener, passive) { 6712 target.addEventListener(eventType, listener, { 6713 passive: passive 6714 }); 6715 return listener; 6716 } 6717 6718 /** 6719 * These variables store information about text content of a target node, 6720 * allowing comparison of content before and after a given event. 6721 * 6722 * Identify the node where selection currently begins, then observe 6723 * both its text content and its current position in the DOM. Since the 6724 * browser may natively replace the target node during composition, we can 6725 * use its position to find its replacement. 6726 * 6727 * 6728 */ 6729 var root = null; 6730 var startText = null; 6731 var fallbackText = null; 6732 function initialize(nativeEventTarget) { 6733 root = nativeEventTarget; 6734 startText = getText(); 6735 return true; 6736 } 6737 function reset() { 6738 root = null; 6739 startText = null; 6740 fallbackText = null; 6741 } 6742 function getData() { 6743 if (fallbackText) { 6744 return fallbackText; 6745 } 6746 6747 var start; 6748 var startValue = startText; 6749 var startLength = startValue.length; 6750 var end; 6751 var endValue = getText(); 6752 var endLength = endValue.length; 6753 6754 for (start = 0; start < startLength; start++) { 6755 if (startValue[start] !== endValue[start]) { 6756 break; 6757 } 6758 } 6759 6760 var minEnd = startLength - start; 6761 6762 for (end = 1; end <= minEnd; end++) { 6763 if (startValue[startLength - end] !== endValue[endLength - end]) { 6764 break; 6765 } 6766 } 6767 6768 var sliceTail = end > 1 ? 1 - end : undefined; 6769 fallbackText = endValue.slice(start, sliceTail); 6770 return fallbackText; 6771 } 6772 function getText() { 6773 if ('value' in root) { 6774 return root.value; 6775 } 6776 6777 return root.textContent; 6778 } 6779 6780 /** 6781 * `charCode` represents the actual "character code" and is safe to use with 6782 * `String.fromCharCode`. As such, only keys that correspond to printable 6783 * characters produce a valid `charCode`, the only exception to this is Enter. 6784 * The Tab-key is considered non-printable and does not have a `charCode`, 6785 * presumably because it does not produce a tab-character in browsers. 6786 * 6787 * @param {object} nativeEvent Native browser event. 6788 * @return {number} Normalized `charCode` property. 6789 */ 6790 function getEventCharCode(nativeEvent) { 6791 var charCode; 6792 var keyCode = nativeEvent.keyCode; 6793 6794 if ('charCode' in nativeEvent) { 6795 charCode = nativeEvent.charCode; // FF does not set `charCode` for the Enter-key, check against `keyCode`. 6796 6797 if (charCode === 0 && keyCode === 13) { 6798 charCode = 13; 6799 } 6800 } else { 6801 // IE8 does not implement `charCode`, but `keyCode` has the correct value. 6802 charCode = keyCode; 6803 } // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux) 6804 // report Enter as charCode 10 when ctrl is pressed. 6805 6806 6807 if (charCode === 10) { 6808 charCode = 13; 6809 } // Some non-printable keys are reported in `charCode`/`keyCode`, discard them. 6810 // Must not discard the (non-)printable Enter-key. 6811 6812 6813 if (charCode >= 32 || charCode === 13) { 6814 return charCode; 6815 } 6816 6817 return 0; 6818 } 6819 6820 function functionThatReturnsTrue() { 6821 return true; 6822 } 6823 6824 function functionThatReturnsFalse() { 6825 return false; 6826 } // This is intentionally a factory so that we have different returned constructors. 6827 // If we had a single constructor, it would be megamorphic and engines would deopt. 6828 6829 6830 function createSyntheticEvent(Interface) { 6831 /** 6832 * Synthetic events are dispatched by event plugins, typically in response to a 6833 * top-level event delegation handler. 6834 * 6835 * These systems should generally use pooling to reduce the frequency of garbage 6836 * collection. The system should check `isPersistent` to determine whether the 6837 * event should be released into the pool after being dispatched. Users that 6838 * need a persisted event should invoke `persist`. 6839 * 6840 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by 6841 * normalizing browser quirks. Subclasses do not necessarily have to implement a 6842 * DOM interface; custom application-specific events can also subclass this. 6843 */ 6844 function SyntheticBaseEvent(reactName, reactEventType, targetInst, nativeEvent, nativeEventTarget) { 6845 this._reactName = reactName; 6846 this._targetInst = targetInst; 6847 this.type = reactEventType; 6848 this.nativeEvent = nativeEvent; 6849 this.target = nativeEventTarget; 6850 this.currentTarget = null; 6851 6852 for (var _propName in Interface) { 6853 if (!Interface.hasOwnProperty(_propName)) { 6854 continue; 6855 } 6856 6857 var normalize = Interface[_propName]; 6858 6859 if (normalize) { 6860 this[_propName] = normalize(nativeEvent); 6861 } else { 6862 this[_propName] = nativeEvent[_propName]; 6863 } 6864 } 6865 6866 var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false; 6867 6868 if (defaultPrevented) { 6869 this.isDefaultPrevented = functionThatReturnsTrue; 6870 } else { 6871 this.isDefaultPrevented = functionThatReturnsFalse; 6872 } 6873 6874 this.isPropagationStopped = functionThatReturnsFalse; 6875 return this; 6876 } 6877 6878 assign(SyntheticBaseEvent.prototype, { 6879 preventDefault: function () { 6880 this.defaultPrevented = true; 6881 var event = this.nativeEvent; 6882 6883 if (!event) { 6884 return; 6885 } 6886 6887 if (event.preventDefault) { 6888 event.preventDefault(); // $FlowFixMe - flow is not aware of `unknown` in IE 6889 } else if (typeof event.returnValue !== 'unknown') { 6890 event.returnValue = false; 6891 } 6892 6893 this.isDefaultPrevented = functionThatReturnsTrue; 6894 }, 6895 stopPropagation: function () { 6896 var event = this.nativeEvent; 6897 6898 if (!event) { 6899 return; 6900 } 6901 6902 if (event.stopPropagation) { 6903 event.stopPropagation(); // $FlowFixMe - flow is not aware of `unknown` in IE 6904 } else if (typeof event.cancelBubble !== 'unknown') { 6905 // The ChangeEventPlugin registers a "propertychange" event for 6906 // IE. This event does not support bubbling or cancelling, and 6907 // any references to cancelBubble throw "Member not found". A 6908 // typeof check of "unknown" circumvents this issue (and is also 6909 // IE specific). 6910 event.cancelBubble = true; 6911 } 6912 6913 this.isPropagationStopped = functionThatReturnsTrue; 6914 }, 6915 6916 /** 6917 * We release all dispatched `SyntheticEvent`s after each event loop, adding 6918 * them back into the pool. This allows a way to hold onto a reference that 6919 * won't be added back into the pool. 6920 */ 6921 persist: function () {// Modern event system doesn't use pooling. 6922 }, 6923 6924 /** 6925 * Checks if this event should be released back into the pool. 6926 * 6927 * @return {boolean} True if this should not be released, false otherwise. 6928 */ 6929 isPersistent: functionThatReturnsTrue 6930 }); 6931 return SyntheticBaseEvent; 6932 } 6933 /** 6934 * @interface Event 6935 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 6936 */ 6937 6938 6939 var EventInterface = { 6940 eventPhase: 0, 6941 bubbles: 0, 6942 cancelable: 0, 6943 timeStamp: function (event) { 6944 return event.timeStamp || Date.now(); 6945 }, 6946 defaultPrevented: 0, 6947 isTrusted: 0 6948 }; 6949 var SyntheticEvent = createSyntheticEvent(EventInterface); 6950 6951 var UIEventInterface = assign({}, EventInterface, { 6952 view: 0, 6953 detail: 0 6954 }); 6955 6956 var SyntheticUIEvent = createSyntheticEvent(UIEventInterface); 6957 var lastMovementX; 6958 var lastMovementY; 6959 var lastMouseEvent; 6960 6961 function updateMouseMovementPolyfillState(event) { 6962 if (event !== lastMouseEvent) { 6963 if (lastMouseEvent && event.type === 'mousemove') { 6964 lastMovementX = event.screenX - lastMouseEvent.screenX; 6965 lastMovementY = event.screenY - lastMouseEvent.screenY; 6966 } else { 6967 lastMovementX = 0; 6968 lastMovementY = 0; 6969 } 6970 6971 lastMouseEvent = event; 6972 } 6973 } 6974 /** 6975 * @interface MouseEvent 6976 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 6977 */ 6978 6979 6980 var MouseEventInterface = assign({}, UIEventInterface, { 6981 screenX: 0, 6982 screenY: 0, 6983 clientX: 0, 6984 clientY: 0, 6985 pageX: 0, 6986 pageY: 0, 6987 ctrlKey: 0, 6988 shiftKey: 0, 6989 altKey: 0, 6990 metaKey: 0, 6991 getModifierState: getEventModifierState, 6992 button: 0, 6993 buttons: 0, 6994 relatedTarget: function (event) { 6995 if (event.relatedTarget === undefined) return event.fromElement === event.srcElement ? event.toElement : event.fromElement; 6996 return event.relatedTarget; 6997 }, 6998 movementX: function (event) { 6999 if ('movementX' in event) { 7000 return event.movementX; 7001 } 7002 7003 updateMouseMovementPolyfillState(event); 7004 return lastMovementX; 7005 }, 7006 movementY: function (event) { 7007 if ('movementY' in event) { 7008 return event.movementY; 7009 } // Don't need to call updateMouseMovementPolyfillState() here 7010 // because it's guaranteed to have already run when movementX 7011 // was copied. 7012 7013 7014 return lastMovementY; 7015 } 7016 }); 7017 7018 var SyntheticMouseEvent = createSyntheticEvent(MouseEventInterface); 7019 /** 7020 * @interface DragEvent 7021 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7022 */ 7023 7024 var DragEventInterface = assign({}, MouseEventInterface, { 7025 dataTransfer: 0 7026 }); 7027 7028 var SyntheticDragEvent = createSyntheticEvent(DragEventInterface); 7029 /** 7030 * @interface FocusEvent 7031 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7032 */ 7033 7034 var FocusEventInterface = assign({}, UIEventInterface, { 7035 relatedTarget: 0 7036 }); 7037 7038 var SyntheticFocusEvent = createSyntheticEvent(FocusEventInterface); 7039 /** 7040 * @interface Event 7041 * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface 7042 * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent 7043 */ 7044 7045 var AnimationEventInterface = assign({}, EventInterface, { 7046 animationName: 0, 7047 elapsedTime: 0, 7048 pseudoElement: 0 7049 }); 7050 7051 var SyntheticAnimationEvent = createSyntheticEvent(AnimationEventInterface); 7052 /** 7053 * @interface Event 7054 * @see http://www.w3.org/TR/clipboard-apis/ 7055 */ 7056 7057 var ClipboardEventInterface = assign({}, EventInterface, { 7058 clipboardData: function (event) { 7059 return 'clipboardData' in event ? event.clipboardData : window.clipboardData; 7060 } 7061 }); 7062 7063 var SyntheticClipboardEvent = createSyntheticEvent(ClipboardEventInterface); 7064 /** 7065 * @interface Event 7066 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents 7067 */ 7068 7069 var CompositionEventInterface = assign({}, EventInterface, { 7070 data: 0 7071 }); 7072 7073 var SyntheticCompositionEvent = createSyntheticEvent(CompositionEventInterface); 7074 /** 7075 * @interface Event 7076 * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105 7077 * /#events-inputevents 7078 */ 7079 // Happens to share the same list for now. 7080 7081 var SyntheticInputEvent = SyntheticCompositionEvent; 7082 /** 7083 * Normalization of deprecated HTML5 `key` values 7084 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 7085 */ 7086 7087 var normalizeKey = { 7088 Esc: 'Escape', 7089 Spacebar: ' ', 7090 Left: 'ArrowLeft', 7091 Up: 'ArrowUp', 7092 Right: 'ArrowRight', 7093 Down: 'ArrowDown', 7094 Del: 'Delete', 7095 Win: 'OS', 7096 Menu: 'ContextMenu', 7097 Apps: 'ContextMenu', 7098 Scroll: 'ScrollLock', 7099 MozPrintableKey: 'Unidentified' 7100 }; 7101 /** 7102 * Translation from legacy `keyCode` to HTML5 `key` 7103 * Only special keys supported, all others depend on keyboard layout or browser 7104 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 7105 */ 7106 7107 var translateToKey = { 7108 '8': 'Backspace', 7109 '9': 'Tab', 7110 '12': 'Clear', 7111 '13': 'Enter', 7112 '16': 'Shift', 7113 '17': 'Control', 7114 '18': 'Alt', 7115 '19': 'Pause', 7116 '20': 'CapsLock', 7117 '27': 'Escape', 7118 '32': ' ', 7119 '33': 'PageUp', 7120 '34': 'PageDown', 7121 '35': 'End', 7122 '36': 'Home', 7123 '37': 'ArrowLeft', 7124 '38': 'ArrowUp', 7125 '39': 'ArrowRight', 7126 '40': 'ArrowDown', 7127 '45': 'Insert', 7128 '46': 'Delete', 7129 '112': 'F1', 7130 '113': 'F2', 7131 '114': 'F3', 7132 '115': 'F4', 7133 '116': 'F5', 7134 '117': 'F6', 7135 '118': 'F7', 7136 '119': 'F8', 7137 '120': 'F9', 7138 '121': 'F10', 7139 '122': 'F11', 7140 '123': 'F12', 7141 '144': 'NumLock', 7142 '145': 'ScrollLock', 7143 '224': 'Meta' 7144 }; 7145 /** 7146 * @param {object} nativeEvent Native browser event. 7147 * @return {string} Normalized `key` property. 7148 */ 7149 7150 function getEventKey(nativeEvent) { 7151 if (nativeEvent.key) { 7152 // Normalize inconsistent values reported by browsers due to 7153 // implementations of a working draft specification. 7154 // FireFox implements `key` but returns `MozPrintableKey` for all 7155 // printable characters (normalized to `Unidentified`), ignore it. 7156 var key = normalizeKey[nativeEvent.key] || nativeEvent.key; 7157 7158 if (key !== 'Unidentified') { 7159 return key; 7160 } 7161 } // Browser does not implement `key`, polyfill as much of it as we can. 7162 7163 7164 if (nativeEvent.type === 'keypress') { 7165 var charCode = getEventCharCode(nativeEvent); // The enter-key is technically both printable and non-printable and can 7166 // thus be captured by `keypress`, no other non-printable key should. 7167 7168 return charCode === 13 ? 'Enter' : String.fromCharCode(charCode); 7169 } 7170 7171 if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') { 7172 // While user keyboard layout determines the actual meaning of each 7173 // `keyCode` value, almost all function keys have a universal value. 7174 return translateToKey[nativeEvent.keyCode] || 'Unidentified'; 7175 } 7176 7177 return ''; 7178 } 7179 /** 7180 * Translation from modifier key to the associated property in the event. 7181 * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers 7182 */ 7183 7184 7185 var modifierKeyToProp = { 7186 Alt: 'altKey', 7187 Control: 'ctrlKey', 7188 Meta: 'metaKey', 7189 Shift: 'shiftKey' 7190 }; // Older browsers (Safari <= 10, iOS Safari <= 10.2) do not support 7191 // getModifierState. If getModifierState is not supported, we map it to a set of 7192 // modifier keys exposed by the event. In this case, Lock-keys are not supported. 7193 7194 function modifierStateGetter(keyArg) { 7195 var syntheticEvent = this; 7196 var nativeEvent = syntheticEvent.nativeEvent; 7197 7198 if (nativeEvent.getModifierState) { 7199 return nativeEvent.getModifierState(keyArg); 7200 } 7201 7202 var keyProp = modifierKeyToProp[keyArg]; 7203 return keyProp ? !!nativeEvent[keyProp] : false; 7204 } 7205 7206 function getEventModifierState(nativeEvent) { 7207 return modifierStateGetter; 7208 } 7209 /** 7210 * @interface KeyboardEvent 7211 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7212 */ 7213 7214 7215 var KeyboardEventInterface = assign({}, UIEventInterface, { 7216 key: getEventKey, 7217 code: 0, 7218 location: 0, 7219 ctrlKey: 0, 7220 shiftKey: 0, 7221 altKey: 0, 7222 metaKey: 0, 7223 repeat: 0, 7224 locale: 0, 7225 getModifierState: getEventModifierState, 7226 // Legacy Interface 7227 charCode: function (event) { 7228 // `charCode` is the result of a KeyPress event and represents the value of 7229 // the actual printable character. 7230 // KeyPress is deprecated, but its replacement is not yet final and not 7231 // implemented in any major browser. Only KeyPress has charCode. 7232 if (event.type === 'keypress') { 7233 return getEventCharCode(event); 7234 } 7235 7236 return 0; 7237 }, 7238 keyCode: function (event) { 7239 // `keyCode` is the result of a KeyDown/Up event and represents the value of 7240 // physical keyboard key. 7241 // The actual meaning of the value depends on the users' keyboard layout 7242 // which cannot be detected. Assuming that it is a US keyboard layout 7243 // provides a surprisingly accurate mapping for US and European users. 7244 // Due to this, it is left to the user to implement at this time. 7245 if (event.type === 'keydown' || event.type === 'keyup') { 7246 return event.keyCode; 7247 } 7248 7249 return 0; 7250 }, 7251 which: function (event) { 7252 // `which` is an alias for either `keyCode` or `charCode` depending on the 7253 // type of the event. 7254 if (event.type === 'keypress') { 7255 return getEventCharCode(event); 7256 } 7257 7258 if (event.type === 'keydown' || event.type === 'keyup') { 7259 return event.keyCode; 7260 } 7261 7262 return 0; 7263 } 7264 }); 7265 7266 var SyntheticKeyboardEvent = createSyntheticEvent(KeyboardEventInterface); 7267 /** 7268 * @interface PointerEvent 7269 * @see http://www.w3.org/TR/pointerevents/ 7270 */ 7271 7272 var PointerEventInterface = assign({}, MouseEventInterface, { 7273 pointerId: 0, 7274 width: 0, 7275 height: 0, 7276 pressure: 0, 7277 tangentialPressure: 0, 7278 tiltX: 0, 7279 tiltY: 0, 7280 twist: 0, 7281 pointerType: 0, 7282 isPrimary: 0 7283 }); 7284 7285 var SyntheticPointerEvent = createSyntheticEvent(PointerEventInterface); 7286 /** 7287 * @interface TouchEvent 7288 * @see http://www.w3.org/TR/touch-events/ 7289 */ 7290 7291 var TouchEventInterface = assign({}, UIEventInterface, { 7292 touches: 0, 7293 targetTouches: 0, 7294 changedTouches: 0, 7295 altKey: 0, 7296 metaKey: 0, 7297 ctrlKey: 0, 7298 shiftKey: 0, 7299 getModifierState: getEventModifierState 7300 }); 7301 7302 var SyntheticTouchEvent = createSyntheticEvent(TouchEventInterface); 7303 /** 7304 * @interface Event 7305 * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events- 7306 * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent 7307 */ 7308 7309 var TransitionEventInterface = assign({}, EventInterface, { 7310 propertyName: 0, 7311 elapsedTime: 0, 7312 pseudoElement: 0 7313 }); 7314 7315 var SyntheticTransitionEvent = createSyntheticEvent(TransitionEventInterface); 7316 /** 7317 * @interface WheelEvent 7318 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 7319 */ 7320 7321 var WheelEventInterface = assign({}, MouseEventInterface, { 7322 deltaX: function (event) { 7323 return 'deltaX' in event ? event.deltaX : // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). 7324 'wheelDeltaX' in event ? -event.wheelDeltaX : 0; 7325 }, 7326 deltaY: function (event) { 7327 return 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). 7328 'wheelDeltaY' in event ? -event.wheelDeltaY : // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). 7329 'wheelDelta' in event ? -event.wheelDelta : 0; 7330 }, 7331 deltaZ: 0, 7332 // Browsers without "deltaMode" is reporting in raw wheel delta where one 7333 // notch on the scroll is always +/- 120, roughly equivalent to pixels. 7334 // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or 7335 // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size. 7336 deltaMode: 0 7337 }); 7338 7339 var SyntheticWheelEvent = createSyntheticEvent(WheelEventInterface); 7340 7341 var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space 7342 7343 var START_KEYCODE = 229; 7344 var canUseCompositionEvent = canUseDOM && 'CompositionEvent' in window; 7345 var documentMode = null; 7346 7347 if (canUseDOM && 'documentMode' in document) { 7348 documentMode = document.documentMode; 7349 } // Webkit offers a very useful `textInput` event that can be used to 7350 // directly represent `beforeInput`. The IE `textinput` event is not as 7351 // useful, so we don't use it. 7352 7353 7354 var canUseTextInputEvent = canUseDOM && 'TextEvent' in window && !documentMode; // In IE9+, we have access to composition events, but the data supplied 7355 // by the native compositionend event may be incorrect. Japanese ideographic 7356 // spaces, for instance (\u3000) are not recorded correctly. 7357 7358 var useFallbackCompositionData = canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11); 7359 var SPACEBAR_CODE = 32; 7360 var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE); 7361 7362 function registerEvents() { 7363 registerTwoPhaseEvent('onBeforeInput', ['compositionend', 'keypress', 'textInput', 'paste']); 7364 registerTwoPhaseEvent('onCompositionEnd', ['compositionend', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7365 registerTwoPhaseEvent('onCompositionStart', ['compositionstart', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7366 registerTwoPhaseEvent('onCompositionUpdate', ['compositionupdate', 'focusout', 'keydown', 'keypress', 'keyup', 'mousedown']); 7367 } // Track whether we've ever handled a keypress on the space key. 7368 7369 7370 var hasSpaceKeypress = false; 7371 /** 7372 * Return whether a native keypress event is assumed to be a command. 7373 * This is required because Firefox fires `keypress` events for key commands 7374 * (cut, copy, select-all, etc.) even though no character is inserted. 7375 */ 7376 7377 function isKeypressCommand(nativeEvent) { 7378 return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && // ctrlKey && altKey is equivalent to AltGr, and is not a command. 7379 !(nativeEvent.ctrlKey && nativeEvent.altKey); 7380 } 7381 /** 7382 * Translate native top level events into event types. 7383 */ 7384 7385 7386 function getCompositionEventType(domEventName) { 7387 switch (domEventName) { 7388 case 'compositionstart': 7389 return 'onCompositionStart'; 7390 7391 case 'compositionend': 7392 return 'onCompositionEnd'; 7393 7394 case 'compositionupdate': 7395 return 'onCompositionUpdate'; 7396 } 7397 } 7398 /** 7399 * Does our fallback best-guess model think this event signifies that 7400 * composition has begun? 7401 */ 7402 7403 7404 function isFallbackCompositionStart(domEventName, nativeEvent) { 7405 return domEventName === 'keydown' && nativeEvent.keyCode === START_KEYCODE; 7406 } 7407 /** 7408 * Does our fallback mode think that this event is the end of composition? 7409 */ 7410 7411 7412 function isFallbackCompositionEnd(domEventName, nativeEvent) { 7413 switch (domEventName) { 7414 case 'keyup': 7415 // Command keys insert or clear IME input. 7416 return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; 7417 7418 case 'keydown': 7419 // Expect IME keyCode on each keydown. If we get any other 7420 // code we must have exited earlier. 7421 return nativeEvent.keyCode !== START_KEYCODE; 7422 7423 case 'keypress': 7424 case 'mousedown': 7425 case 'focusout': 7426 // Events are not possible without cancelling IME. 7427 return true; 7428 7429 default: 7430 return false; 7431 } 7432 } 7433 /** 7434 * Google Input Tools provides composition data via a CustomEvent, 7435 * with the `data` property populated in the `detail` object. If this 7436 * is available on the event object, use it. If not, this is a plain 7437 * composition event and we have nothing special to extract. 7438 * 7439 * @param {object} nativeEvent 7440 * @return {?string} 7441 */ 7442 7443 7444 function getDataFromCustomEvent(nativeEvent) { 7445 var detail = nativeEvent.detail; 7446 7447 if (typeof detail === 'object' && 'data' in detail) { 7448 return detail.data; 7449 } 7450 7451 return null; 7452 } 7453 /** 7454 * Check if a composition event was triggered by Korean IME. 7455 * Our fallback mode does not work well with IE's Korean IME, 7456 * so just use native composition events when Korean IME is used. 7457 * Although CompositionEvent.locale property is deprecated, 7458 * it is available in IE, where our fallback mode is enabled. 7459 * 7460 * @param {object} nativeEvent 7461 * @return {boolean} 7462 */ 7463 7464 7465 function isUsingKoreanIME(nativeEvent) { 7466 return nativeEvent.locale === 'ko'; 7467 } // Track the current IME composition status, if any. 7468 7469 7470 var isComposing = false; 7471 /** 7472 * @return {?object} A SyntheticCompositionEvent. 7473 */ 7474 7475 function extractCompositionEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget) { 7476 var eventType; 7477 var fallbackData; 7478 7479 if (canUseCompositionEvent) { 7480 eventType = getCompositionEventType(domEventName); 7481 } else if (!isComposing) { 7482 if (isFallbackCompositionStart(domEventName, nativeEvent)) { 7483 eventType = 'onCompositionStart'; 7484 } 7485 } else if (isFallbackCompositionEnd(domEventName, nativeEvent)) { 7486 eventType = 'onCompositionEnd'; 7487 } 7488 7489 if (!eventType) { 7490 return null; 7491 } 7492 7493 if (useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)) { 7494 // The current composition is stored statically and must not be 7495 // overwritten while composition continues. 7496 if (!isComposing && eventType === 'onCompositionStart') { 7497 isComposing = initialize(nativeEventTarget); 7498 } else if (eventType === 'onCompositionEnd') { 7499 if (isComposing) { 7500 fallbackData = getData(); 7501 } 7502 } 7503 } 7504 7505 var listeners = accumulateTwoPhaseListeners(targetInst, eventType); 7506 7507 if (listeners.length > 0) { 7508 var event = new SyntheticCompositionEvent(eventType, domEventName, null, nativeEvent, nativeEventTarget); 7509 dispatchQueue.push({ 7510 event: event, 7511 listeners: listeners 7512 }); 7513 7514 if (fallbackData) { 7515 // Inject data generated from fallback path into the synthetic event. 7516 // This matches the property of native CompositionEventInterface. 7517 event.data = fallbackData; 7518 } else { 7519 var customData = getDataFromCustomEvent(nativeEvent); 7520 7521 if (customData !== null) { 7522 event.data = customData; 7523 } 7524 } 7525 } 7526 } 7527 7528 function getNativeBeforeInputChars(domEventName, nativeEvent) { 7529 switch (domEventName) { 7530 case 'compositionend': 7531 return getDataFromCustomEvent(nativeEvent); 7532 7533 case 'keypress': 7534 /** 7535 * If native `textInput` events are available, our goal is to make 7536 * use of them. However, there is a special case: the spacebar key. 7537 * In Webkit, preventing default on a spacebar `textInput` event 7538 * cancels character insertion, but it *also* causes the browser 7539 * to fall back to its default spacebar behavior of scrolling the 7540 * page. 7541 * 7542 * Tracking at: 7543 * https://code.google.com/p/chromium/issues/detail?id=355103 7544 * 7545 * To avoid this issue, use the keypress event as if no `textInput` 7546 * event is available. 7547 */ 7548 var which = nativeEvent.which; 7549 7550 if (which !== SPACEBAR_CODE) { 7551 return null; 7552 } 7553 7554 hasSpaceKeypress = true; 7555 return SPACEBAR_CHAR; 7556 7557 case 'textInput': 7558 // Record the characters to be added to the DOM. 7559 var chars = nativeEvent.data; // If it's a spacebar character, assume that we have already handled 7560 // it at the keypress level and bail immediately. Android Chrome 7561 // doesn't give us keycodes, so we need to ignore it. 7562 7563 if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { 7564 return null; 7565 } 7566 7567 return chars; 7568 7569 default: 7570 // For other native event types, do nothing. 7571 return null; 7572 } 7573 } 7574 /** 7575 * For browsers that do not provide the `textInput` event, extract the 7576 * appropriate string to use for SyntheticInputEvent. 7577 */ 7578 7579 7580 function getFallbackBeforeInputChars(domEventName, nativeEvent) { 7581 // If we are currently composing (IME) and using a fallback to do so, 7582 // try to extract the composed characters from the fallback object. 7583 // If composition event is available, we extract a string only at 7584 // compositionevent, otherwise extract it at fallback events. 7585 if (isComposing) { 7586 if (domEventName === 'compositionend' || !canUseCompositionEvent && isFallbackCompositionEnd(domEventName, nativeEvent)) { 7587 var chars = getData(); 7588 reset(); 7589 isComposing = false; 7590 return chars; 7591 } 7592 7593 return null; 7594 } 7595 7596 switch (domEventName) { 7597 case 'paste': 7598 // If a paste event occurs after a keypress, throw out the input 7599 // chars. Paste events should not lead to BeforeInput events. 7600 return null; 7601 7602 case 'keypress': 7603 /** 7604 * As of v27, Firefox may fire keypress events even when no character 7605 * will be inserted. A few possibilities: 7606 * 7607 * - `which` is `0`. Arrow keys, Esc key, etc. 7608 * 7609 * - `which` is the pressed key code, but no char is available. 7610 * Ex: 'AltGr + d` in Polish. There is no modified character for 7611 * this key combination and no character is inserted into the 7612 * document, but FF fires the keypress for char code `100` anyway. 7613 * No `input` event will occur. 7614 * 7615 * - `which` is the pressed key code, but a command combination is 7616 * being used. Ex: `Cmd+C`. No character is inserted, and no 7617 * `input` event will occur. 7618 */ 7619 if (!isKeypressCommand(nativeEvent)) { 7620 // IE fires the `keypress` event when a user types an emoji via 7621 // Touch keyboard of Windows. In such a case, the `char` property 7622 // holds an emoji character like `\uD83D\uDE0A`. Because its length 7623 // is 2, the property `which` does not represent an emoji correctly. 7624 // In such a case, we directly return the `char` property instead of 7625 // using `which`. 7626 if (nativeEvent.char && nativeEvent.char.length > 1) { 7627 return nativeEvent.char; 7628 } else if (nativeEvent.which) { 7629 return String.fromCharCode(nativeEvent.which); 7630 } 7631 } 7632 7633 return null; 7634 7635 case 'compositionend': 7636 return useFallbackCompositionData && !isUsingKoreanIME(nativeEvent) ? null : nativeEvent.data; 7637 7638 default: 7639 return null; 7640 } 7641 } 7642 /** 7643 * Extract a SyntheticInputEvent for `beforeInput`, based on either native 7644 * `textInput` or fallback behavior. 7645 * 7646 * @return {?object} A SyntheticInputEvent. 7647 */ 7648 7649 7650 function extractBeforeInputEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget) { 7651 var chars; 7652 7653 if (canUseTextInputEvent) { 7654 chars = getNativeBeforeInputChars(domEventName, nativeEvent); 7655 } else { 7656 chars = getFallbackBeforeInputChars(domEventName, nativeEvent); 7657 } // If no characters are being inserted, no BeforeInput event should 7658 // be fired. 7659 7660 7661 if (!chars) { 7662 return null; 7663 } 7664 7665 var listeners = accumulateTwoPhaseListeners(targetInst, 'onBeforeInput'); 7666 7667 if (listeners.length > 0) { 7668 var event = new SyntheticInputEvent('onBeforeInput', 'beforeinput', null, nativeEvent, nativeEventTarget); 7669 dispatchQueue.push({ 7670 event: event, 7671 listeners: listeners 7672 }); 7673 event.data = chars; 7674 } 7675 } 7676 /** 7677 * Create an `onBeforeInput` event to match 7678 * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. 7679 * 7680 * This event plugin is based on the native `textInput` event 7681 * available in Chrome, Safari, Opera, and IE. This event fires after 7682 * `onKeyPress` and `onCompositionEnd`, but before `onInput`. 7683 * 7684 * `beforeInput` is spec'd but not implemented in any browsers, and 7685 * the `input` event does not provide any useful information about what has 7686 * actually been added, contrary to the spec. Thus, `textInput` is the best 7687 * available event to identify the characters that have actually been inserted 7688 * into the target node. 7689 * 7690 * This plugin is also responsible for emitting `composition` events, thus 7691 * allowing us to share composition fallback code for both `beforeInput` and 7692 * `composition` event types. 7693 */ 7694 7695 7696 function extractEvents(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 7697 extractCompositionEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 7698 extractBeforeInputEvent(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 7699 } 7700 7701 /** 7702 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 7703 */ 7704 var supportedInputTypes = { 7705 color: true, 7706 date: true, 7707 datetime: true, 7708 'datetime-local': true, 7709 email: true, 7710 month: true, 7711 number: true, 7712 password: true, 7713 range: true, 7714 search: true, 7715 tel: true, 7716 text: true, 7717 time: true, 7718 url: true, 7719 week: true 7720 }; 7721 7722 function isTextInputElement(elem) { 7723 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); 7724 7725 if (nodeName === 'input') { 7726 return !!supportedInputTypes[elem.type]; 7727 } 7728 7729 if (nodeName === 'textarea') { 7730 return true; 7731 } 7732 7733 return false; 7734 } 7735 7736 /** 7737 * Checks if an event is supported in the current execution environment. 7738 * 7739 * NOTE: This will not work correctly for non-generic events such as `change`, 7740 * `reset`, `load`, `error`, and `select`. 7741 * 7742 * Borrows from Modernizr. 7743 * 7744 * @param {string} eventNameSuffix Event name, e.g. "click". 7745 * @return {boolean} True if the event is supported. 7746 * @internal 7747 * @license Modernizr 3.0.0pre (Custom Build) | MIT 7748 */ 7749 7750 function isEventSupported(eventNameSuffix) { 7751 if (!canUseDOM) { 7752 return false; 7753 } 7754 7755 var eventName = 'on' + eventNameSuffix; 7756 var isSupported = (eventName in document); 7757 7758 if (!isSupported) { 7759 var element = document.createElement('div'); 7760 element.setAttribute(eventName, 'return;'); 7761 isSupported = typeof element[eventName] === 'function'; 7762 } 7763 7764 return isSupported; 7765 } 7766 7767 function registerEvents$1() { 7768 registerTwoPhaseEvent('onChange', ['change', 'click', 'focusin', 'focusout', 'input', 'keydown', 'keyup', 'selectionchange']); 7769 } 7770 7771 function createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, target) { 7772 // Flag this event loop as needing state restore. 7773 enqueueStateRestore(target); 7774 var listeners = accumulateTwoPhaseListeners(inst, 'onChange'); 7775 7776 if (listeners.length > 0) { 7777 var event = new SyntheticEvent('onChange', 'change', null, nativeEvent, target); 7778 dispatchQueue.push({ 7779 event: event, 7780 listeners: listeners 7781 }); 7782 } 7783 } 7784 /** 7785 * For IE shims 7786 */ 7787 7788 7789 var activeElement = null; 7790 var activeElementInst = null; 7791 /** 7792 * SECTION: handle `change` event 7793 */ 7794 7795 function shouldUseChangeEvent(elem) { 7796 var nodeName = elem.nodeName && elem.nodeName.toLowerCase(); 7797 return nodeName === 'select' || nodeName === 'input' && elem.type === 'file'; 7798 } 7799 7800 function manualDispatchChangeEvent(nativeEvent) { 7801 var dispatchQueue = []; 7802 createAndAccumulateChangeEvent(dispatchQueue, activeElementInst, nativeEvent, getEventTarget(nativeEvent)); // If change and propertychange bubbled, we'd just bind to it like all the 7803 // other events and have it go through ReactBrowserEventEmitter. Since it 7804 // doesn't, we manually listen for the events and so we have to enqueue and 7805 // process the abstract event manually. 7806 // 7807 // Batching is necessary here in order to ensure that all event handlers run 7808 // before the next rerender (including event handlers attached to ancestor 7809 // elements instead of directly on the input). Without this, controlled 7810 // components don't work properly in conjunction with event bubbling because 7811 // the component is rerendered and the value reverted before all the event 7812 // handlers can run. See https://github.com/facebook/react/issues/708. 7813 7814 batchedUpdates(runEventInBatch, dispatchQueue); 7815 } 7816 7817 function runEventInBatch(dispatchQueue) { 7818 processDispatchQueue(dispatchQueue, 0); 7819 } 7820 7821 function getInstIfValueChanged(targetInst) { 7822 var targetNode = getNodeFromInstance(targetInst); 7823 7824 if (updateValueIfChanged(targetNode)) { 7825 return targetInst; 7826 } 7827 } 7828 7829 function getTargetInstForChangeEvent(domEventName, targetInst) { 7830 if (domEventName === 'change') { 7831 return targetInst; 7832 } 7833 } 7834 /** 7835 * SECTION: handle `input` event 7836 */ 7837 7838 7839 var isInputEventSupported = false; 7840 7841 if (canUseDOM) { 7842 // IE9 claims to support the input event but fails to trigger it when 7843 // deleting text, so we ignore its input events. 7844 isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 9); 7845 } 7846 /** 7847 * (For IE <=9) Starts tracking propertychange events on the passed-in element 7848 * and override the value property so that we can distinguish user events from 7849 * value changes in JS. 7850 */ 7851 7852 7853 function startWatchingForValueChange(target, targetInst) { 7854 activeElement = target; 7855 activeElementInst = targetInst; 7856 activeElement.attachEvent('onpropertychange', handlePropertyChange); 7857 } 7858 /** 7859 * (For IE <=9) Removes the event listeners from the currently-tracked element, 7860 * if any exists. 7861 */ 7862 7863 7864 function stopWatchingForValueChange() { 7865 if (!activeElement) { 7866 return; 7867 } 7868 7869 activeElement.detachEvent('onpropertychange', handlePropertyChange); 7870 activeElement = null; 7871 activeElementInst = null; 7872 } 7873 /** 7874 * (For IE <=9) Handles a propertychange event, sending a `change` event if 7875 * the value of the active element has changed. 7876 */ 7877 7878 7879 function handlePropertyChange(nativeEvent) { 7880 if (nativeEvent.propertyName !== 'value') { 7881 return; 7882 } 7883 7884 if (getInstIfValueChanged(activeElementInst)) { 7885 manualDispatchChangeEvent(nativeEvent); 7886 } 7887 } 7888 7889 function handleEventsForInputEventPolyfill(domEventName, target, targetInst) { 7890 if (domEventName === 'focusin') { 7891 // In IE9, propertychange fires for most input events but is buggy and 7892 // doesn't fire when text is deleted, but conveniently, selectionchange 7893 // appears to fire in all of the remaining cases so we catch those and 7894 // forward the event if the value has changed 7895 // In either case, we don't want to call the event handler if the value 7896 // is changed from JS so we redefine a setter for `.value` that updates 7897 // our activeElementValue variable, allowing us to ignore those changes 7898 // 7899 // stopWatching() should be a noop here but we call it just in case we 7900 // missed a blur event somehow. 7901 stopWatchingForValueChange(); 7902 startWatchingForValueChange(target, targetInst); 7903 } else if (domEventName === 'focusout') { 7904 stopWatchingForValueChange(); 7905 } 7906 } // For IE8 and IE9. 7907 7908 7909 function getTargetInstForInputEventPolyfill(domEventName, targetInst) { 7910 if (domEventName === 'selectionchange' || domEventName === 'keyup' || domEventName === 'keydown') { 7911 // On the selectionchange event, the target is just document which isn't 7912 // helpful for us so just check activeElement instead. 7913 // 7914 // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire 7915 // propertychange on the first input event after setting `value` from a 7916 // script and fires only keydown, keypress, keyup. Catching keyup usually 7917 // gets it and catching keydown lets us fire an event for the first 7918 // keystroke if user does a key repeat (it'll be a little delayed: right 7919 // before the second keystroke). Other input methods (e.g., paste) seem to 7920 // fire selectionchange normally. 7921 return getInstIfValueChanged(activeElementInst); 7922 } 7923 } 7924 /** 7925 * SECTION: handle `click` event 7926 */ 7927 7928 7929 function shouldUseClickEvent(elem) { 7930 // Use the `click` event to detect changes to checkbox and radio inputs. 7931 // This approach works across all browsers, whereas `change` does not fire 7932 // until `blur` in IE8. 7933 var nodeName = elem.nodeName; 7934 return nodeName && nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio'); 7935 } 7936 7937 function getTargetInstForClickEvent(domEventName, targetInst) { 7938 if (domEventName === 'click') { 7939 return getInstIfValueChanged(targetInst); 7940 } 7941 } 7942 7943 function getTargetInstForInputOrChangeEvent(domEventName, targetInst) { 7944 if (domEventName === 'input' || domEventName === 'change') { 7945 return getInstIfValueChanged(targetInst); 7946 } 7947 } 7948 7949 function handleControlledInputBlur(node) { 7950 var state = node._wrapperState; 7951 7952 if (!state || !state.controlled || node.type !== 'number') { 7953 return; 7954 } 7955 7956 { 7957 // If controlled, assign the value attribute to the current value on blur 7958 setDefaultValue(node, 'number', node.value); 7959 } 7960 } 7961 /** 7962 * This plugin creates an `onChange` event that normalizes change events 7963 * across form elements. This event fires at a time when it's possible to 7964 * change the element's value without seeing a flicker. 7965 * 7966 * Supported elements are: 7967 * - input (see `isTextInputElement`) 7968 * - textarea 7969 * - select 7970 */ 7971 7972 7973 function extractEvents$1(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 7974 var targetNode = targetInst ? getNodeFromInstance(targetInst) : window; 7975 var getTargetInstFunc, handleEventFunc; 7976 7977 if (shouldUseChangeEvent(targetNode)) { 7978 getTargetInstFunc = getTargetInstForChangeEvent; 7979 } else if (isTextInputElement(targetNode)) { 7980 if (isInputEventSupported) { 7981 getTargetInstFunc = getTargetInstForInputOrChangeEvent; 7982 } else { 7983 getTargetInstFunc = getTargetInstForInputEventPolyfill; 7984 handleEventFunc = handleEventsForInputEventPolyfill; 7985 } 7986 } else if (shouldUseClickEvent(targetNode)) { 7987 getTargetInstFunc = getTargetInstForClickEvent; 7988 } 7989 7990 if (getTargetInstFunc) { 7991 var inst = getTargetInstFunc(domEventName, targetInst); 7992 7993 if (inst) { 7994 createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, nativeEventTarget); 7995 return; 7996 } 7997 } 7998 7999 if (handleEventFunc) { 8000 handleEventFunc(domEventName, targetNode, targetInst); 8001 } // When blurring, set the value attribute for number inputs 8002 8003 8004 if (domEventName === 'focusout') { 8005 handleControlledInputBlur(targetNode); 8006 } 8007 } 8008 8009 function registerEvents$2() { 8010 registerDirectEvent('onMouseEnter', ['mouseout', 'mouseover']); 8011 registerDirectEvent('onMouseLeave', ['mouseout', 'mouseover']); 8012 registerDirectEvent('onPointerEnter', ['pointerout', 'pointerover']); 8013 registerDirectEvent('onPointerLeave', ['pointerout', 'pointerover']); 8014 } 8015 /** 8016 * For almost every interaction we care about, there will be both a top-level 8017 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that 8018 * we do not extract duplicate events. However, moving the mouse into the 8019 * browser from outside will not fire a `mouseout` event. In this case, we use 8020 * the `mouseover` top-level event. 8021 */ 8022 8023 8024 function extractEvents$2(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8025 var isOverEvent = domEventName === 'mouseover' || domEventName === 'pointerover'; 8026 var isOutEvent = domEventName === 'mouseout' || domEventName === 'pointerout'; 8027 8028 if (isOverEvent && !isReplayingEvent(nativeEvent)) { 8029 // If this is an over event with a target, we might have already dispatched 8030 // the event in the out event of the other target. If this is replayed, 8031 // then it's because we couldn't dispatch against this target previously 8032 // so we have to do it now instead. 8033 var related = nativeEvent.relatedTarget || nativeEvent.fromElement; 8034 8035 if (related) { 8036 // If the related node is managed by React, we can assume that we have 8037 // already dispatched the corresponding events during its mouseout. 8038 if (getClosestInstanceFromNode(related) || isContainerMarkedAsRoot(related)) { 8039 return; 8040 } 8041 } 8042 } 8043 8044 if (!isOutEvent && !isOverEvent) { 8045 // Must not be a mouse or pointer in or out - ignoring. 8046 return; 8047 } 8048 8049 var win; // TODO: why is this nullable in the types but we read from it? 8050 8051 if (nativeEventTarget.window === nativeEventTarget) { 8052 // `nativeEventTarget` is probably a window object. 8053 win = nativeEventTarget; 8054 } else { 8055 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. 8056 var doc = nativeEventTarget.ownerDocument; 8057 8058 if (doc) { 8059 win = doc.defaultView || doc.parentWindow; 8060 } else { 8061 win = window; 8062 } 8063 } 8064 8065 var from; 8066 var to; 8067 8068 if (isOutEvent) { 8069 var _related = nativeEvent.relatedTarget || nativeEvent.toElement; 8070 8071 from = targetInst; 8072 to = _related ? getClosestInstanceFromNode(_related) : null; 8073 8074 if (to !== null) { 8075 var nearestMounted = getNearestMountedFiber(to); 8076 8077 if (to !== nearestMounted || to.tag !== HostComponent && to.tag !== HostText) { 8078 to = null; 8079 } 8080 } 8081 } else { 8082 // Moving to a node from outside the window. 8083 from = null; 8084 to = targetInst; 8085 } 8086 8087 if (from === to) { 8088 // Nothing pertains to our managed components. 8089 return; 8090 } 8091 8092 var SyntheticEventCtor = SyntheticMouseEvent; 8093 var leaveEventType = 'onMouseLeave'; 8094 var enterEventType = 'onMouseEnter'; 8095 var eventTypePrefix = 'mouse'; 8096 8097 if (domEventName === 'pointerout' || domEventName === 'pointerover') { 8098 SyntheticEventCtor = SyntheticPointerEvent; 8099 leaveEventType = 'onPointerLeave'; 8100 enterEventType = 'onPointerEnter'; 8101 eventTypePrefix = 'pointer'; 8102 } 8103 8104 var fromNode = from == null ? win : getNodeFromInstance(from); 8105 var toNode = to == null ? win : getNodeFromInstance(to); 8106 var leave = new SyntheticEventCtor(leaveEventType, eventTypePrefix + 'leave', from, nativeEvent, nativeEventTarget); 8107 leave.target = fromNode; 8108 leave.relatedTarget = toNode; 8109 var enter = null; // We should only process this nativeEvent if we are processing 8110 // the first ancestor. Next time, we will ignore the event. 8111 8112 var nativeTargetInst = getClosestInstanceFromNode(nativeEventTarget); 8113 8114 if (nativeTargetInst === targetInst) { 8115 var enterEvent = new SyntheticEventCtor(enterEventType, eventTypePrefix + 'enter', to, nativeEvent, nativeEventTarget); 8116 enterEvent.target = toNode; 8117 enterEvent.relatedTarget = fromNode; 8118 enter = enterEvent; 8119 } 8120 8121 accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leave, enter, from, to); 8122 } 8123 8124 /** 8125 * inlined Object.is polyfill to avoid requiring consumers ship their own 8126 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 8127 */ 8128 function is(x, y) { 8129 return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare 8130 ; 8131 } 8132 8133 var objectIs = typeof Object.is === 'function' ? Object.is : is; 8134 8135 /** 8136 * Performs equality by iterating through keys on an object and returning false 8137 * when any key has values which are not strictly equal between the arguments. 8138 * Returns true when the values of all keys are strictly equal. 8139 */ 8140 8141 function shallowEqual(objA, objB) { 8142 if (objectIs(objA, objB)) { 8143 return true; 8144 } 8145 8146 if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { 8147 return false; 8148 } 8149 8150 var keysA = Object.keys(objA); 8151 var keysB = Object.keys(objB); 8152 8153 if (keysA.length !== keysB.length) { 8154 return false; 8155 } // Test for A's keys different from B. 8156 8157 8158 for (var i = 0; i < keysA.length; i++) { 8159 var currentKey = keysA[i]; 8160 8161 if (!hasOwnProperty.call(objB, currentKey) || !objectIs(objA[currentKey], objB[currentKey])) { 8162 return false; 8163 } 8164 } 8165 8166 return true; 8167 } 8168 8169 /** 8170 * Given any node return the first leaf node without children. 8171 * 8172 * @param {DOMElement|DOMTextNode} node 8173 * @return {DOMElement|DOMTextNode} 8174 */ 8175 8176 function getLeafNode(node) { 8177 while (node && node.firstChild) { 8178 node = node.firstChild; 8179 } 8180 8181 return node; 8182 } 8183 /** 8184 * Get the next sibling within a container. This will walk up the 8185 * DOM if a node's siblings have been exhausted. 8186 * 8187 * @param {DOMElement|DOMTextNode} node 8188 * @return {?DOMElement|DOMTextNode} 8189 */ 8190 8191 8192 function getSiblingNode(node) { 8193 while (node) { 8194 if (node.nextSibling) { 8195 return node.nextSibling; 8196 } 8197 8198 node = node.parentNode; 8199 } 8200 } 8201 /** 8202 * Get object describing the nodes which contain characters at offset. 8203 * 8204 * @param {DOMElement|DOMTextNode} root 8205 * @param {number} offset 8206 * @return {?object} 8207 */ 8208 8209 8210 function getNodeForCharacterOffset(root, offset) { 8211 var node = getLeafNode(root); 8212 var nodeStart = 0; 8213 var nodeEnd = 0; 8214 8215 while (node) { 8216 if (node.nodeType === TEXT_NODE) { 8217 nodeEnd = nodeStart + node.textContent.length; 8218 8219 if (nodeStart <= offset && nodeEnd >= offset) { 8220 return { 8221 node: node, 8222 offset: offset - nodeStart 8223 }; 8224 } 8225 8226 nodeStart = nodeEnd; 8227 } 8228 8229 node = getLeafNode(getSiblingNode(node)); 8230 } 8231 } 8232 8233 /** 8234 * @param {DOMElement} outerNode 8235 * @return {?object} 8236 */ 8237 8238 function getOffsets(outerNode) { 8239 var ownerDocument = outerNode.ownerDocument; 8240 var win = ownerDocument && ownerDocument.defaultView || window; 8241 var selection = win.getSelection && win.getSelection(); 8242 8243 if (!selection || selection.rangeCount === 0) { 8244 return null; 8245 } 8246 8247 var anchorNode = selection.anchorNode, 8248 anchorOffset = selection.anchorOffset, 8249 focusNode = selection.focusNode, 8250 focusOffset = selection.focusOffset; // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the 8251 // up/down buttons on an <input type="number">. Anonymous divs do not seem to 8252 // expose properties, triggering a "Permission denied error" if any of its 8253 // properties are accessed. The only seemingly possible way to avoid erroring 8254 // is to access a property that typically works for non-anonymous divs and 8255 // catch any error that may otherwise arise. See 8256 // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 8257 8258 try { 8259 /* eslint-disable no-unused-expressions */ 8260 anchorNode.nodeType; 8261 focusNode.nodeType; 8262 /* eslint-enable no-unused-expressions */ 8263 } catch (e) { 8264 return null; 8265 } 8266 8267 return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset); 8268 } 8269 /** 8270 * Returns {start, end} where `start` is the character/codepoint index of 8271 * (anchorNode, anchorOffset) within the textContent of `outerNode`, and 8272 * `end` is the index of (focusNode, focusOffset). 8273 * 8274 * Returns null if you pass in garbage input but we should probably just crash. 8275 * 8276 * Exported only for testing. 8277 */ 8278 8279 function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) { 8280 var length = 0; 8281 var start = -1; 8282 var end = -1; 8283 var indexWithinAnchor = 0; 8284 var indexWithinFocus = 0; 8285 var node = outerNode; 8286 var parentNode = null; 8287 8288 outer: while (true) { 8289 var next = null; 8290 8291 while (true) { 8292 if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) { 8293 start = length + anchorOffset; 8294 } 8295 8296 if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) { 8297 end = length + focusOffset; 8298 } 8299 8300 if (node.nodeType === TEXT_NODE) { 8301 length += node.nodeValue.length; 8302 } 8303 8304 if ((next = node.firstChild) === null) { 8305 break; 8306 } // Moving from `node` to its first child `next`. 8307 8308 8309 parentNode = node; 8310 node = next; 8311 } 8312 8313 while (true) { 8314 if (node === outerNode) { 8315 // If `outerNode` has children, this is always the second time visiting 8316 // it. If it has no children, this is still the first loop, and the only 8317 // valid selection is anchorNode and focusNode both equal to this node 8318 // and both offsets 0, in which case we will have handled above. 8319 break outer; 8320 } 8321 8322 if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) { 8323 start = length; 8324 } 8325 8326 if (parentNode === focusNode && ++indexWithinFocus === focusOffset) { 8327 end = length; 8328 } 8329 8330 if ((next = node.nextSibling) !== null) { 8331 break; 8332 } 8333 8334 node = parentNode; 8335 parentNode = node.parentNode; 8336 } // Moving from `node` to its next sibling `next`. 8337 8338 8339 node = next; 8340 } 8341 8342 if (start === -1 || end === -1) { 8343 // This should never happen. (Would happen if the anchor/focus nodes aren't 8344 // actually inside the passed-in node.) 8345 return null; 8346 } 8347 8348 return { 8349 start: start, 8350 end: end 8351 }; 8352 } 8353 /** 8354 * In modern non-IE browsers, we can support both forward and backward 8355 * selections. 8356 * 8357 * Note: IE10+ supports the Selection object, but it does not support 8358 * the `extend` method, which means that even in modern IE, it's not possible 8359 * to programmatically create a backward selection. Thus, for all IE 8360 * versions, we use the old IE API to create our selections. 8361 * 8362 * @param {DOMElement|DOMTextNode} node 8363 * @param {object} offsets 8364 */ 8365 8366 function setOffsets(node, offsets) { 8367 var doc = node.ownerDocument || document; 8368 var win = doc && doc.defaultView || window; // Edge fails with "Object expected" in some scenarios. 8369 // (For instance: TinyMCE editor used in a list component that supports pasting to add more, 8370 // fails when pasting 100+ items) 8371 8372 if (!win.getSelection) { 8373 return; 8374 } 8375 8376 var selection = win.getSelection(); 8377 var length = node.textContent.length; 8378 var start = Math.min(offsets.start, length); 8379 var end = offsets.end === undefined ? start : Math.min(offsets.end, length); // IE 11 uses modern selection, but doesn't support the extend method. 8380 // Flip backward selections, so we can set with a single range. 8381 8382 if (!selection.extend && start > end) { 8383 var temp = end; 8384 end = start; 8385 start = temp; 8386 } 8387 8388 var startMarker = getNodeForCharacterOffset(node, start); 8389 var endMarker = getNodeForCharacterOffset(node, end); 8390 8391 if (startMarker && endMarker) { 8392 if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) { 8393 return; 8394 } 8395 8396 var range = doc.createRange(); 8397 range.setStart(startMarker.node, startMarker.offset); 8398 selection.removeAllRanges(); 8399 8400 if (start > end) { 8401 selection.addRange(range); 8402 selection.extend(endMarker.node, endMarker.offset); 8403 } else { 8404 range.setEnd(endMarker.node, endMarker.offset); 8405 selection.addRange(range); 8406 } 8407 } 8408 } 8409 8410 function isTextNode(node) { 8411 return node && node.nodeType === TEXT_NODE; 8412 } 8413 8414 function containsNode(outerNode, innerNode) { 8415 if (!outerNode || !innerNode) { 8416 return false; 8417 } else if (outerNode === innerNode) { 8418 return true; 8419 } else if (isTextNode(outerNode)) { 8420 return false; 8421 } else if (isTextNode(innerNode)) { 8422 return containsNode(outerNode, innerNode.parentNode); 8423 } else if ('contains' in outerNode) { 8424 return outerNode.contains(innerNode); 8425 } else if (outerNode.compareDocumentPosition) { 8426 return !!(outerNode.compareDocumentPosition(innerNode) & 16); 8427 } else { 8428 return false; 8429 } 8430 } 8431 8432 function isInDocument(node) { 8433 return node && node.ownerDocument && containsNode(node.ownerDocument.documentElement, node); 8434 } 8435 8436 function isSameOriginFrame(iframe) { 8437 try { 8438 // Accessing the contentDocument of a HTMLIframeElement can cause the browser 8439 // to throw, e.g. if it has a cross-origin src attribute. 8440 // Safari will show an error in the console when the access results in "Blocked a frame with origin". e.g: 8441 // iframe.contentDocument.defaultView; 8442 // A safety way is to access one of the cross origin properties: Window or Location 8443 // Which might result in "SecurityError" DOM Exception and it is compatible to Safari. 8444 // https://html.spec.whatwg.org/multipage/browsers.html#integration-with-idl 8445 return typeof iframe.contentWindow.location.href === 'string'; 8446 } catch (err) { 8447 return false; 8448 } 8449 } 8450 8451 function getActiveElementDeep() { 8452 var win = window; 8453 var element = getActiveElement(); 8454 8455 while (element instanceof win.HTMLIFrameElement) { 8456 if (isSameOriginFrame(element)) { 8457 win = element.contentWindow; 8458 } else { 8459 return element; 8460 } 8461 8462 element = getActiveElement(win.document); 8463 } 8464 8465 return element; 8466 } 8467 /** 8468 * @ReactInputSelection: React input selection module. Based on Selection.js, 8469 * but modified to be suitable for react and has a couple of bug fixes (doesn't 8470 * assume buttons have range selections allowed). 8471 * Input selection module for React. 8472 */ 8473 8474 /** 8475 * @hasSelectionCapabilities: we get the element types that support selection 8476 * from https://html.spec.whatwg.org/#do-not-apply, looking at `selectionStart` 8477 * and `selectionEnd` rows. 8478 */ 8479 8480 8481 function hasSelectionCapabilities(elem) { 8482 var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); 8483 return nodeName && (nodeName === 'input' && (elem.type === 'text' || elem.type === 'search' || elem.type === 'tel' || elem.type === 'url' || elem.type === 'password') || nodeName === 'textarea' || elem.contentEditable === 'true'); 8484 } 8485 function getSelectionInformation() { 8486 var focusedElem = getActiveElementDeep(); 8487 return { 8488 focusedElem: focusedElem, 8489 selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection(focusedElem) : null 8490 }; 8491 } 8492 /** 8493 * @restoreSelection: If any selection information was potentially lost, 8494 * restore it. This is useful when performing operations that could remove dom 8495 * nodes and place them back in, resulting in focus being lost. 8496 */ 8497 8498 function restoreSelection(priorSelectionInformation) { 8499 var curFocusedElem = getActiveElementDeep(); 8500 var priorFocusedElem = priorSelectionInformation.focusedElem; 8501 var priorSelectionRange = priorSelectionInformation.selectionRange; 8502 8503 if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) { 8504 if (priorSelectionRange !== null && hasSelectionCapabilities(priorFocusedElem)) { 8505 setSelection(priorFocusedElem, priorSelectionRange); 8506 } // Focusing a node can change the scroll position, which is undesirable 8507 8508 8509 var ancestors = []; 8510 var ancestor = priorFocusedElem; 8511 8512 while (ancestor = ancestor.parentNode) { 8513 if (ancestor.nodeType === ELEMENT_NODE) { 8514 ancestors.push({ 8515 element: ancestor, 8516 left: ancestor.scrollLeft, 8517 top: ancestor.scrollTop 8518 }); 8519 } 8520 } 8521 8522 if (typeof priorFocusedElem.focus === 'function') { 8523 priorFocusedElem.focus(); 8524 } 8525 8526 for (var i = 0; i < ancestors.length; i++) { 8527 var info = ancestors[i]; 8528 info.element.scrollLeft = info.left; 8529 info.element.scrollTop = info.top; 8530 } 8531 } 8532 } 8533 /** 8534 * @getSelection: Gets the selection bounds of a focused textarea, input or 8535 * contentEditable node. 8536 * -@input: Look up selection bounds of this input 8537 * -@return {start: selectionStart, end: selectionEnd} 8538 */ 8539 8540 function getSelection(input) { 8541 var selection; 8542 8543 if ('selectionStart' in input) { 8544 // Modern browser with input or textarea. 8545 selection = { 8546 start: input.selectionStart, 8547 end: input.selectionEnd 8548 }; 8549 } else { 8550 // Content editable or old IE textarea. 8551 selection = getOffsets(input); 8552 } 8553 8554 return selection || { 8555 start: 0, 8556 end: 0 8557 }; 8558 } 8559 /** 8560 * @setSelection: Sets the selection bounds of a textarea or input and focuses 8561 * the input. 8562 * -@input Set selection bounds of this input or textarea 8563 * -@offsets Object of same form that is returned from get* 8564 */ 8565 8566 function setSelection(input, offsets) { 8567 var start = offsets.start; 8568 var end = offsets.end; 8569 8570 if (end === undefined) { 8571 end = start; 8572 } 8573 8574 if ('selectionStart' in input) { 8575 input.selectionStart = start; 8576 input.selectionEnd = Math.min(end, input.value.length); 8577 } else { 8578 setOffsets(input, offsets); 8579 } 8580 } 8581 8582 var skipSelectionChangeEvent = canUseDOM && 'documentMode' in document && document.documentMode <= 11; 8583 8584 function registerEvents$3() { 8585 registerTwoPhaseEvent('onSelect', ['focusout', 'contextmenu', 'dragend', 'focusin', 'keydown', 'keyup', 'mousedown', 'mouseup', 'selectionchange']); 8586 } 8587 8588 var activeElement$1 = null; 8589 var activeElementInst$1 = null; 8590 var lastSelection = null; 8591 var mouseDown = false; 8592 /** 8593 * Get an object which is a unique representation of the current selection. 8594 * 8595 * The return value will not be consistent across nodes or browsers, but 8596 * two identical selections on the same node will return identical objects. 8597 */ 8598 8599 function getSelection$1(node) { 8600 if ('selectionStart' in node && hasSelectionCapabilities(node)) { 8601 return { 8602 start: node.selectionStart, 8603 end: node.selectionEnd 8604 }; 8605 } else { 8606 var win = node.ownerDocument && node.ownerDocument.defaultView || window; 8607 var selection = win.getSelection(); 8608 return { 8609 anchorNode: selection.anchorNode, 8610 anchorOffset: selection.anchorOffset, 8611 focusNode: selection.focusNode, 8612 focusOffset: selection.focusOffset 8613 }; 8614 } 8615 } 8616 /** 8617 * Get document associated with the event target. 8618 */ 8619 8620 8621 function getEventTargetDocument(eventTarget) { 8622 return eventTarget.window === eventTarget ? eventTarget.document : eventTarget.nodeType === DOCUMENT_NODE ? eventTarget : eventTarget.ownerDocument; 8623 } 8624 /** 8625 * Poll selection to see whether it's changed. 8626 * 8627 * @param {object} nativeEvent 8628 * @param {object} nativeEventTarget 8629 * @return {?SyntheticEvent} 8630 */ 8631 8632 8633 function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) { 8634 // Ensure we have the right element, and that the user is not dragging a 8635 // selection (this matches native `select` event behavior). In HTML5, select 8636 // fires only on input and textarea thus if there's no focused element we 8637 // won't dispatch. 8638 var doc = getEventTargetDocument(nativeEventTarget); 8639 8640 if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement(doc)) { 8641 return; 8642 } // Only fire when selection has actually changed. 8643 8644 8645 var currentSelection = getSelection$1(activeElement$1); 8646 8647 if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) { 8648 lastSelection = currentSelection; 8649 var listeners = accumulateTwoPhaseListeners(activeElementInst$1, 'onSelect'); 8650 8651 if (listeners.length > 0) { 8652 var event = new SyntheticEvent('onSelect', 'select', null, nativeEvent, nativeEventTarget); 8653 dispatchQueue.push({ 8654 event: event, 8655 listeners: listeners 8656 }); 8657 event.target = activeElement$1; 8658 } 8659 } 8660 } 8661 /** 8662 * This plugin creates an `onSelect` event that normalizes select events 8663 * across form elements. 8664 * 8665 * Supported elements are: 8666 * - input (see `isTextInputElement`) 8667 * - textarea 8668 * - contentEditable 8669 * 8670 * This differs from native browser implementations in the following ways: 8671 * - Fires on contentEditable fields as well as inputs. 8672 * - Fires for collapsed selection. 8673 * - Fires after user input. 8674 */ 8675 8676 8677 function extractEvents$3(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8678 var targetNode = targetInst ? getNodeFromInstance(targetInst) : window; 8679 8680 switch (domEventName) { 8681 // Track the input node that has focus. 8682 case 'focusin': 8683 if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') { 8684 activeElement$1 = targetNode; 8685 activeElementInst$1 = targetInst; 8686 lastSelection = null; 8687 } 8688 8689 break; 8690 8691 case 'focusout': 8692 activeElement$1 = null; 8693 activeElementInst$1 = null; 8694 lastSelection = null; 8695 break; 8696 // Don't fire the event while the user is dragging. This matches the 8697 // semantics of the native select event. 8698 8699 case 'mousedown': 8700 mouseDown = true; 8701 break; 8702 8703 case 'contextmenu': 8704 case 'mouseup': 8705 case 'dragend': 8706 mouseDown = false; 8707 constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget); 8708 break; 8709 // Chrome and IE fire non-standard event when selection is changed (and 8710 // sometimes when it hasn't). IE's event fires out of order with respect 8711 // to key and input events on deletion, so we discard it. 8712 // 8713 // Firefox doesn't support selectionchange, so check selection status 8714 // after each key entry. The selection changes after keydown and before 8715 // keyup, but we check on keydown as well in the case of holding down a 8716 // key, when multiple keydown events are fired but only one keyup is. 8717 // This is also our approach for IE handling, for the reason above. 8718 8719 case 'selectionchange': 8720 if (skipSelectionChangeEvent) { 8721 break; 8722 } 8723 8724 // falls through 8725 8726 case 'keydown': 8727 case 'keyup': 8728 constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget); 8729 } 8730 } 8731 8732 /** 8733 * Generate a mapping of standard vendor prefixes using the defined style property and event name. 8734 * 8735 * @param {string} styleProp 8736 * @param {string} eventName 8737 * @returns {object} 8738 */ 8739 8740 function makePrefixMap(styleProp, eventName) { 8741 var prefixes = {}; 8742 prefixes[styleProp.toLowerCase()] = eventName.toLowerCase(); 8743 prefixes['Webkit' + styleProp] = 'webkit' + eventName; 8744 prefixes['Moz' + styleProp] = 'moz' + eventName; 8745 return prefixes; 8746 } 8747 /** 8748 * A list of event names to a configurable list of vendor prefixes. 8749 */ 8750 8751 8752 var vendorPrefixes = { 8753 animationend: makePrefixMap('Animation', 'AnimationEnd'), 8754 animationiteration: makePrefixMap('Animation', 'AnimationIteration'), 8755 animationstart: makePrefixMap('Animation', 'AnimationStart'), 8756 transitionend: makePrefixMap('Transition', 'TransitionEnd') 8757 }; 8758 /** 8759 * Event names that have already been detected and prefixed (if applicable). 8760 */ 8761 8762 var prefixedEventNames = {}; 8763 /** 8764 * Element to check for prefixes on. 8765 */ 8766 8767 var style = {}; 8768 /** 8769 * Bootstrap if a DOM exists. 8770 */ 8771 8772 if (canUseDOM) { 8773 style = document.createElement('div').style; // On some platforms, in particular some releases of Android 4.x, 8774 // the un-prefixed "animation" and "transition" properties are defined on the 8775 // style object but the events that fire will still be prefixed, so we need 8776 // to check if the un-prefixed events are usable, and if not remove them from the map. 8777 8778 if (!('AnimationEvent' in window)) { 8779 delete vendorPrefixes.animationend.animation; 8780 delete vendorPrefixes.animationiteration.animation; 8781 delete vendorPrefixes.animationstart.animation; 8782 } // Same as above 8783 8784 8785 if (!('TransitionEvent' in window)) { 8786 delete vendorPrefixes.transitionend.transition; 8787 } 8788 } 8789 /** 8790 * Attempts to determine the correct vendor prefixed event name. 8791 * 8792 * @param {string} eventName 8793 * @returns {string} 8794 */ 8795 8796 8797 function getVendorPrefixedEventName(eventName) { 8798 if (prefixedEventNames[eventName]) { 8799 return prefixedEventNames[eventName]; 8800 } else if (!vendorPrefixes[eventName]) { 8801 return eventName; 8802 } 8803 8804 var prefixMap = vendorPrefixes[eventName]; 8805 8806 for (var styleProp in prefixMap) { 8807 if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) { 8808 return prefixedEventNames[eventName] = prefixMap[styleProp]; 8809 } 8810 } 8811 8812 return eventName; 8813 } 8814 8815 var ANIMATION_END = getVendorPrefixedEventName('animationend'); 8816 var ANIMATION_ITERATION = getVendorPrefixedEventName('animationiteration'); 8817 var ANIMATION_START = getVendorPrefixedEventName('animationstart'); 8818 var TRANSITION_END = getVendorPrefixedEventName('transitionend'); 8819 8820 var topLevelEventsToReactNames = new Map(); // NOTE: Capitalization is important in this list! 8821 // 8822 // E.g. it needs "pointerDown", not "pointerdown". 8823 // This is because we derive both React name ("onPointerDown") 8824 // and DOM name ("pointerdown") from the same list. 8825 // 8826 // Exceptions that don't match this convention are listed separately. 8827 // 8828 // prettier-ignore 8829 8830 var simpleEventPluginEvents = ['abort', 'auxClick', 'cancel', 'canPlay', 'canPlayThrough', 'click', 'close', 'contextMenu', 'copy', 'cut', 'drag', 'dragEnd', 'dragEnter', 'dragExit', 'dragLeave', 'dragOver', 'dragStart', 'drop', 'durationChange', 'emptied', 'encrypted', 'ended', 'error', 'gotPointerCapture', 'input', 'invalid', 'keyDown', 'keyPress', 'keyUp', 'load', 'loadedData', 'loadedMetadata', 'loadStart', 'lostPointerCapture', 'mouseDown', 'mouseMove', 'mouseOut', 'mouseOver', 'mouseUp', 'paste', 'pause', 'play', 'playing', 'pointerCancel', 'pointerDown', 'pointerMove', 'pointerOut', 'pointerOver', 'pointerUp', 'progress', 'rateChange', 'reset', 'resize', 'seeked', 'seeking', 'stalled', 'submit', 'suspend', 'timeUpdate', 'touchCancel', 'touchEnd', 'touchStart', 'volumeChange', 'scroll', 'toggle', 'touchMove', 'waiting', 'wheel']; 8831 8832 function registerSimpleEvent(domEventName, reactName) { 8833 topLevelEventsToReactNames.set(domEventName, reactName); 8834 registerTwoPhaseEvent(reactName, [domEventName]); 8835 } 8836 8837 function registerSimpleEvents() { 8838 for (var i = 0; i < simpleEventPluginEvents.length; i++) { 8839 var eventName = simpleEventPluginEvents[i]; 8840 var domEventName = eventName.toLowerCase(); 8841 var capitalizedEvent = eventName[0].toUpperCase() + eventName.slice(1); 8842 registerSimpleEvent(domEventName, 'on' + capitalizedEvent); 8843 } // Special cases where event names don't match. 8844 8845 8846 registerSimpleEvent(ANIMATION_END, 'onAnimationEnd'); 8847 registerSimpleEvent(ANIMATION_ITERATION, 'onAnimationIteration'); 8848 registerSimpleEvent(ANIMATION_START, 'onAnimationStart'); 8849 registerSimpleEvent('dblclick', 'onDoubleClick'); 8850 registerSimpleEvent('focusin', 'onFocus'); 8851 registerSimpleEvent('focusout', 'onBlur'); 8852 registerSimpleEvent(TRANSITION_END, 'onTransitionEnd'); 8853 } 8854 8855 function extractEvents$4(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 8856 var reactName = topLevelEventsToReactNames.get(domEventName); 8857 8858 if (reactName === undefined) { 8859 return; 8860 } 8861 8862 var SyntheticEventCtor = SyntheticEvent; 8863 var reactEventType = domEventName; 8864 8865 switch (domEventName) { 8866 case 'keypress': 8867 // Firefox creates a keypress event for function keys too. This removes 8868 // the unwanted keypress events. Enter is however both printable and 8869 // non-printable. One would expect Tab to be as well (but it isn't). 8870 if (getEventCharCode(nativeEvent) === 0) { 8871 return; 8872 } 8873 8874 /* falls through */ 8875 8876 case 'keydown': 8877 case 'keyup': 8878 SyntheticEventCtor = SyntheticKeyboardEvent; 8879 break; 8880 8881 case 'focusin': 8882 reactEventType = 'focus'; 8883 SyntheticEventCtor = SyntheticFocusEvent; 8884 break; 8885 8886 case 'focusout': 8887 reactEventType = 'blur'; 8888 SyntheticEventCtor = SyntheticFocusEvent; 8889 break; 8890 8891 case 'beforeblur': 8892 case 'afterblur': 8893 SyntheticEventCtor = SyntheticFocusEvent; 8894 break; 8895 8896 case 'click': 8897 // Firefox creates a click event on right mouse clicks. This removes the 8898 // unwanted click events. 8899 if (nativeEvent.button === 2) { 8900 return; 8901 } 8902 8903 /* falls through */ 8904 8905 case 'auxclick': 8906 case 'dblclick': 8907 case 'mousedown': 8908 case 'mousemove': 8909 case 'mouseup': // TODO: Disabled elements should not respond to mouse events 8910 8911 /* falls through */ 8912 8913 case 'mouseout': 8914 case 'mouseover': 8915 case 'contextmenu': 8916 SyntheticEventCtor = SyntheticMouseEvent; 8917 break; 8918 8919 case 'drag': 8920 case 'dragend': 8921 case 'dragenter': 8922 case 'dragexit': 8923 case 'dragleave': 8924 case 'dragover': 8925 case 'dragstart': 8926 case 'drop': 8927 SyntheticEventCtor = SyntheticDragEvent; 8928 break; 8929 8930 case 'touchcancel': 8931 case 'touchend': 8932 case 'touchmove': 8933 case 'touchstart': 8934 SyntheticEventCtor = SyntheticTouchEvent; 8935 break; 8936 8937 case ANIMATION_END: 8938 case ANIMATION_ITERATION: 8939 case ANIMATION_START: 8940 SyntheticEventCtor = SyntheticAnimationEvent; 8941 break; 8942 8943 case TRANSITION_END: 8944 SyntheticEventCtor = SyntheticTransitionEvent; 8945 break; 8946 8947 case 'scroll': 8948 SyntheticEventCtor = SyntheticUIEvent; 8949 break; 8950 8951 case 'wheel': 8952 SyntheticEventCtor = SyntheticWheelEvent; 8953 break; 8954 8955 case 'copy': 8956 case 'cut': 8957 case 'paste': 8958 SyntheticEventCtor = SyntheticClipboardEvent; 8959 break; 8960 8961 case 'gotpointercapture': 8962 case 'lostpointercapture': 8963 case 'pointercancel': 8964 case 'pointerdown': 8965 case 'pointermove': 8966 case 'pointerout': 8967 case 'pointerover': 8968 case 'pointerup': 8969 SyntheticEventCtor = SyntheticPointerEvent; 8970 break; 8971 } 8972 8973 var inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0; 8974 8975 { 8976 // Some events don't bubble in the browser. 8977 // In the past, React has always bubbled them, but this can be surprising. 8978 // We're going to try aligning closer to the browser behavior by not bubbling 8979 // them in React either. We'll start by not bubbling onScroll, and then expand. 8980 var accumulateTargetOnly = !inCapturePhase && // TODO: ideally, we'd eventually add all events from 8981 // nonDelegatedEvents list in DOMPluginEventSystem. 8982 // Then we can remove this special list. 8983 // This is a breaking change that can wait until React 18. 8984 domEventName === 'scroll'; 8985 8986 var _listeners = accumulateSinglePhaseListeners(targetInst, reactName, nativeEvent.type, inCapturePhase, accumulateTargetOnly); 8987 8988 if (_listeners.length > 0) { 8989 // Intentionally create event lazily. 8990 var _event = new SyntheticEventCtor(reactName, reactEventType, null, nativeEvent, nativeEventTarget); 8991 8992 dispatchQueue.push({ 8993 event: _event, 8994 listeners: _listeners 8995 }); 8996 } 8997 } 8998 } 8999 9000 // TODO: remove top-level side effect. 9001 registerSimpleEvents(); 9002 registerEvents$2(); 9003 registerEvents$1(); 9004 registerEvents$3(); 9005 registerEvents(); 9006 9007 function extractEvents$5(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags, targetContainer) { 9008 // TODO: we should remove the concept of a "SimpleEventPlugin". 9009 // This is the basic functionality of the event system. All 9010 // the other plugins are essentially polyfills. So the plugin 9011 // should probably be inlined somewhere and have its logic 9012 // be core the to event system. This would potentially allow 9013 // us to ship builds of React without the polyfilled plugins below. 9014 extractEvents$4(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags); 9015 var shouldProcessPolyfillPlugins = (eventSystemFlags & SHOULD_NOT_PROCESS_POLYFILL_EVENT_PLUGINS) === 0; // We don't process these events unless we are in the 9016 // event's native "bubble" phase, which means that we're 9017 // not in the capture phase. That's because we emulate 9018 // the capture phase here still. This is a trade-off, 9019 // because in an ideal world we would not emulate and use 9020 // the phases properly, like we do with the SimpleEvent 9021 // plugin. However, the plugins below either expect 9022 // emulation (EnterLeave) or use state localized to that 9023 // plugin (BeforeInput, Change, Select). The state in 9024 // these modules complicates things, as you'll essentially 9025 // get the case where the capture phase event might change 9026 // state, only for the following bubble event to come in 9027 // later and not trigger anything as the state now 9028 // invalidates the heuristics of the event plugin. We 9029 // could alter all these plugins to work in such ways, but 9030 // that might cause other unknown side-effects that we 9031 // can't foresee right now. 9032 9033 if (shouldProcessPolyfillPlugins) { 9034 extractEvents$2(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 9035 extractEvents$1(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 9036 extractEvents$3(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 9037 extractEvents(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); 9038 } 9039 } // List of events that need to be individually attached to media elements. 9040 9041 9042 var mediaEventTypes = ['abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'encrypted', 'ended', 'error', 'loadeddata', 'loadedmetadata', 'loadstart', 'pause', 'play', 'playing', 'progress', 'ratechange', 'resize', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'volumechange', 'waiting']; // We should not delegate these events to the container, but rather 9043 // set them on the actual target element itself. This is primarily 9044 // because these events do not consistently bubble in the DOM. 9045 9046 var nonDelegatedEvents = new Set(['cancel', 'close', 'invalid', 'load', 'scroll', 'toggle'].concat(mediaEventTypes)); 9047 9048 function executeDispatch(event, listener, currentTarget) { 9049 var type = event.type || 'unknown-event'; 9050 event.currentTarget = currentTarget; 9051 invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event); 9052 event.currentTarget = null; 9053 } 9054 9055 function processDispatchQueueItemsInOrder(event, dispatchListeners, inCapturePhase) { 9056 var previousInstance; 9057 9058 if (inCapturePhase) { 9059 for (var i = dispatchListeners.length - 1; i >= 0; i--) { 9060 var _dispatchListeners$i = dispatchListeners[i], 9061 instance = _dispatchListeners$i.instance, 9062 currentTarget = _dispatchListeners$i.currentTarget, 9063 listener = _dispatchListeners$i.listener; 9064 9065 if (instance !== previousInstance && event.isPropagationStopped()) { 9066 return; 9067 } 9068 9069 executeDispatch(event, listener, currentTarget); 9070 previousInstance = instance; 9071 } 9072 } else { 9073 for (var _i = 0; _i < dispatchListeners.length; _i++) { 9074 var _dispatchListeners$_i = dispatchListeners[_i], 9075 _instance = _dispatchListeners$_i.instance, 9076 _currentTarget = _dispatchListeners$_i.currentTarget, 9077 _listener = _dispatchListeners$_i.listener; 9078 9079 if (_instance !== previousInstance && event.isPropagationStopped()) { 9080 return; 9081 } 9082 9083 executeDispatch(event, _listener, _currentTarget); 9084 previousInstance = _instance; 9085 } 9086 } 9087 } 9088 9089 function processDispatchQueue(dispatchQueue, eventSystemFlags) { 9090 var inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0; 9091 9092 for (var i = 0; i < dispatchQueue.length; i++) { 9093 var _dispatchQueue$i = dispatchQueue[i], 9094 event = _dispatchQueue$i.event, 9095 listeners = _dispatchQueue$i.listeners; 9096 processDispatchQueueItemsInOrder(event, listeners, inCapturePhase); // event system doesn't use pooling. 9097 } // This would be a good time to rethrow if any of the event handlers threw. 9098 9099 9100 rethrowCaughtError(); 9101 } 9102 9103 function dispatchEventsForPlugins(domEventName, eventSystemFlags, nativeEvent, targetInst, targetContainer) { 9104 var nativeEventTarget = getEventTarget(nativeEvent); 9105 var dispatchQueue = []; 9106 extractEvents$5(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget, eventSystemFlags); 9107 processDispatchQueue(dispatchQueue, eventSystemFlags); 9108 } 9109 9110 function listenToNonDelegatedEvent(domEventName, targetElement) { 9111 { 9112 if (!nonDelegatedEvents.has(domEventName)) { 9113 error('Did not expect a listenToNonDelegatedEvent() call for "%s". ' + 'This is a bug in React. Please file an issue.', domEventName); 9114 } 9115 } 9116 9117 var isCapturePhaseListener = false; 9118 var listenerSet = getEventListenerSet(targetElement); 9119 var listenerSetKey = getListenerSetKey(domEventName, isCapturePhaseListener); 9120 9121 if (!listenerSet.has(listenerSetKey)) { 9122 addTrappedEventListener(targetElement, domEventName, IS_NON_DELEGATED, isCapturePhaseListener); 9123 listenerSet.add(listenerSetKey); 9124 } 9125 } 9126 function listenToNativeEvent(domEventName, isCapturePhaseListener, target) { 9127 { 9128 if (nonDelegatedEvents.has(domEventName) && !isCapturePhaseListener) { 9129 error('Did not expect a listenToNativeEvent() call for "%s" in the bubble phase. ' + 'This is a bug in React. Please file an issue.', domEventName); 9130 } 9131 } 9132 9133 var eventSystemFlags = 0; 9134 9135 if (isCapturePhaseListener) { 9136 eventSystemFlags |= IS_CAPTURE_PHASE; 9137 } 9138 9139 addTrappedEventListener(target, domEventName, eventSystemFlags, isCapturePhaseListener); 9140 } // This is only used by createEventHandle when the 9141 var listeningMarker = '_reactListening' + Math.random().toString(36).slice(2); 9142 function listenToAllSupportedEvents(rootContainerElement) { 9143 if (!rootContainerElement[listeningMarker]) { 9144 rootContainerElement[listeningMarker] = true; 9145 allNativeEvents.forEach(function (domEventName) { 9146 // We handle selectionchange separately because it 9147 // doesn't bubble and needs to be on the document. 9148 if (domEventName !== 'selectionchange') { 9149 if (!nonDelegatedEvents.has(domEventName)) { 9150 listenToNativeEvent(domEventName, false, rootContainerElement); 9151 } 9152 9153 listenToNativeEvent(domEventName, true, rootContainerElement); 9154 } 9155 }); 9156 var ownerDocument = rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument; 9157 9158 if (ownerDocument !== null) { 9159 // The selectionchange event also needs deduplication 9160 // but it is attached to the document. 9161 if (!ownerDocument[listeningMarker]) { 9162 ownerDocument[listeningMarker] = true; 9163 listenToNativeEvent('selectionchange', false, ownerDocument); 9164 } 9165 } 9166 } 9167 } 9168 9169 function addTrappedEventListener(targetContainer, domEventName, eventSystemFlags, isCapturePhaseListener, isDeferredListenerForLegacyFBSupport) { 9170 var listener = createEventListenerWrapperWithPriority(targetContainer, domEventName, eventSystemFlags); // If passive option is not supported, then the event will be 9171 // active and not passive. 9172 9173 var isPassiveListener = undefined; 9174 9175 if (passiveBrowserEventsSupported) { 9176 // Browsers introduced an intervention, making these events 9177 // passive by default on document. React doesn't bind them 9178 // to document anymore, but changing this now would undo 9179 // the performance wins from the change. So we emulate 9180 // the existing behavior manually on the roots now. 9181 // https://github.com/facebook/react/issues/19651 9182 if (domEventName === 'touchstart' || domEventName === 'touchmove' || domEventName === 'wheel') { 9183 isPassiveListener = true; 9184 } 9185 } 9186 9187 targetContainer = targetContainer; 9188 var unsubscribeListener; // When legacyFBSupport is enabled, it's for when we 9189 9190 9191 if (isCapturePhaseListener) { 9192 if (isPassiveListener !== undefined) { 9193 unsubscribeListener = addEventCaptureListenerWithPassiveFlag(targetContainer, domEventName, listener, isPassiveListener); 9194 } else { 9195 unsubscribeListener = addEventCaptureListener(targetContainer, domEventName, listener); 9196 } 9197 } else { 9198 if (isPassiveListener !== undefined) { 9199 unsubscribeListener = addEventBubbleListenerWithPassiveFlag(targetContainer, domEventName, listener, isPassiveListener); 9200 } else { 9201 unsubscribeListener = addEventBubbleListener(targetContainer, domEventName, listener); 9202 } 9203 } 9204 } 9205 9206 function isMatchingRootContainer(grandContainer, targetContainer) { 9207 return grandContainer === targetContainer || grandContainer.nodeType === COMMENT_NODE && grandContainer.parentNode === targetContainer; 9208 } 9209 9210 function dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, targetInst, targetContainer) { 9211 var ancestorInst = targetInst; 9212 9213 if ((eventSystemFlags & IS_EVENT_HANDLE_NON_MANAGED_NODE) === 0 && (eventSystemFlags & IS_NON_DELEGATED) === 0) { 9214 var targetContainerNode = targetContainer; // If we are using the legacy FB support flag, we 9215 9216 if (targetInst !== null) { 9217 // The below logic attempts to work out if we need to change 9218 // the target fiber to a different ancestor. We had similar logic 9219 // in the legacy event system, except the big difference between 9220 // systems is that the modern event system now has an event listener 9221 // attached to each React Root and React Portal Root. Together, 9222 // the DOM nodes representing these roots are the "rootContainer". 9223 // To figure out which ancestor instance we should use, we traverse 9224 // up the fiber tree from the target instance and attempt to find 9225 // root boundaries that match that of our current "rootContainer". 9226 // If we find that "rootContainer", we find the parent fiber 9227 // sub-tree for that root and make that our ancestor instance. 9228 var node = targetInst; 9229 9230 mainLoop: while (true) { 9231 if (node === null) { 9232 return; 9233 } 9234 9235 var nodeTag = node.tag; 9236 9237 if (nodeTag === HostRoot || nodeTag === HostPortal) { 9238 var container = node.stateNode.containerInfo; 9239 9240 if (isMatchingRootContainer(container, targetContainerNode)) { 9241 break; 9242 } 9243 9244 if (nodeTag === HostPortal) { 9245 // The target is a portal, but it's not the rootContainer we're looking for. 9246 // Normally portals handle their own events all the way down to the root. 9247 // So we should be able to stop now. However, we don't know if this portal 9248 // was part of *our* root. 9249 var grandNode = node.return; 9250 9251 while (grandNode !== null) { 9252 var grandTag = grandNode.tag; 9253 9254 if (grandTag === HostRoot || grandTag === HostPortal) { 9255 var grandContainer = grandNode.stateNode.containerInfo; 9256 9257 if (isMatchingRootContainer(grandContainer, targetContainerNode)) { 9258 // This is the rootContainer we're looking for and we found it as 9259 // a parent of the Portal. That means we can ignore it because the 9260 // Portal will bubble through to us. 9261 return; 9262 } 9263 } 9264 9265 grandNode = grandNode.return; 9266 } 9267 } // Now we need to find it's corresponding host fiber in the other 9268 // tree. To do this we can use getClosestInstanceFromNode, but we 9269 // need to validate that the fiber is a host instance, otherwise 9270 // we need to traverse up through the DOM till we find the correct 9271 // node that is from the other tree. 9272 9273 9274 while (container !== null) { 9275 var parentNode = getClosestInstanceFromNode(container); 9276 9277 if (parentNode === null) { 9278 return; 9279 } 9280 9281 var parentTag = parentNode.tag; 9282 9283 if (parentTag === HostComponent || parentTag === HostText) { 9284 node = ancestorInst = parentNode; 9285 continue mainLoop; 9286 } 9287 9288 container = container.parentNode; 9289 } 9290 } 9291 9292 node = node.return; 9293 } 9294 } 9295 } 9296 9297 batchedUpdates(function () { 9298 return dispatchEventsForPlugins(domEventName, eventSystemFlags, nativeEvent, ancestorInst); 9299 }); 9300 } 9301 9302 function createDispatchListener(instance, listener, currentTarget) { 9303 return { 9304 instance: instance, 9305 listener: listener, 9306 currentTarget: currentTarget 9307 }; 9308 } 9309 9310 function accumulateSinglePhaseListeners(targetFiber, reactName, nativeEventType, inCapturePhase, accumulateTargetOnly, nativeEvent) { 9311 var captureName = reactName !== null ? reactName + 'Capture' : null; 9312 var reactEventName = inCapturePhase ? captureName : reactName; 9313 var listeners = []; 9314 var instance = targetFiber; 9315 var lastHostComponent = null; // Accumulate all instances and listeners via the target -> root path. 9316 9317 while (instance !== null) { 9318 var _instance2 = instance, 9319 stateNode = _instance2.stateNode, 9320 tag = _instance2.tag; // Handle listeners that are on HostComponents (i.e. <div>) 9321 9322 if (tag === HostComponent && stateNode !== null) { 9323 lastHostComponent = stateNode; // createEventHandle listeners 9324 9325 9326 if (reactEventName !== null) { 9327 var listener = getListener(instance, reactEventName); 9328 9329 if (listener != null) { 9330 listeners.push(createDispatchListener(instance, listener, lastHostComponent)); 9331 } 9332 } 9333 } // If we are only accumulating events for the target, then we don't 9334 // continue to propagate through the React fiber tree to find other 9335 // listeners. 9336 9337 9338 if (accumulateTargetOnly) { 9339 break; 9340 } // If we are processing the onBeforeBlur event, then we need to take 9341 9342 instance = instance.return; 9343 } 9344 9345 return listeners; 9346 } // We should only use this function for: 9347 // - BeforeInputEventPlugin 9348 // - ChangeEventPlugin 9349 // - SelectEventPlugin 9350 // This is because we only process these plugins 9351 // in the bubble phase, so we need to accumulate two 9352 // phase event listeners (via emulation). 9353 9354 function accumulateTwoPhaseListeners(targetFiber, reactName) { 9355 var captureName = reactName + 'Capture'; 9356 var listeners = []; 9357 var instance = targetFiber; // Accumulate all instances and listeners via the target -> root path. 9358 9359 while (instance !== null) { 9360 var _instance3 = instance, 9361 stateNode = _instance3.stateNode, 9362 tag = _instance3.tag; // Handle listeners that are on HostComponents (i.e. <div>) 9363 9364 if (tag === HostComponent && stateNode !== null) { 9365 var currentTarget = stateNode; 9366 var captureListener = getListener(instance, captureName); 9367 9368 if (captureListener != null) { 9369 listeners.unshift(createDispatchListener(instance, captureListener, currentTarget)); 9370 } 9371 9372 var bubbleListener = getListener(instance, reactName); 9373 9374 if (bubbleListener != null) { 9375 listeners.push(createDispatchListener(instance, bubbleListener, currentTarget)); 9376 } 9377 } 9378 9379 instance = instance.return; 9380 } 9381 9382 return listeners; 9383 } 9384 9385 function getParent(inst) { 9386 if (inst === null) { 9387 return null; 9388 } 9389 9390 do { 9391 inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. 9392 // That is depending on if we want nested subtrees (layers) to bubble 9393 // events to their parent. We could also go through parentNode on the 9394 // host node but that wouldn't work for React Native and doesn't let us 9395 // do the portal feature. 9396 } while (inst && inst.tag !== HostComponent); 9397 9398 if (inst) { 9399 return inst; 9400 } 9401 9402 return null; 9403 } 9404 /** 9405 * Return the lowest common ancestor of A and B, or null if they are in 9406 * different trees. 9407 */ 9408 9409 9410 function getLowestCommonAncestor(instA, instB) { 9411 var nodeA = instA; 9412 var nodeB = instB; 9413 var depthA = 0; 9414 9415 for (var tempA = nodeA; tempA; tempA = getParent(tempA)) { 9416 depthA++; 9417 } 9418 9419 var depthB = 0; 9420 9421 for (var tempB = nodeB; tempB; tempB = getParent(tempB)) { 9422 depthB++; 9423 } // If A is deeper, crawl up. 9424 9425 9426 while (depthA - depthB > 0) { 9427 nodeA = getParent(nodeA); 9428 depthA--; 9429 } // If B is deeper, crawl up. 9430 9431 9432 while (depthB - depthA > 0) { 9433 nodeB = getParent(nodeB); 9434 depthB--; 9435 } // Walk in lockstep until we find a match. 9436 9437 9438 var depth = depthA; 9439 9440 while (depth--) { 9441 if (nodeA === nodeB || nodeB !== null && nodeA === nodeB.alternate) { 9442 return nodeA; 9443 } 9444 9445 nodeA = getParent(nodeA); 9446 nodeB = getParent(nodeB); 9447 } 9448 9449 return null; 9450 } 9451 9452 function accumulateEnterLeaveListenersForEvent(dispatchQueue, event, target, common, inCapturePhase) { 9453 var registrationName = event._reactName; 9454 var listeners = []; 9455 var instance = target; 9456 9457 while (instance !== null) { 9458 if (instance === common) { 9459 break; 9460 } 9461 9462 var _instance4 = instance, 9463 alternate = _instance4.alternate, 9464 stateNode = _instance4.stateNode, 9465 tag = _instance4.tag; 9466 9467 if (alternate !== null && alternate === common) { 9468 break; 9469 } 9470 9471 if (tag === HostComponent && stateNode !== null) { 9472 var currentTarget = stateNode; 9473 9474 if (inCapturePhase) { 9475 var captureListener = getListener(instance, registrationName); 9476 9477 if (captureListener != null) { 9478 listeners.unshift(createDispatchListener(instance, captureListener, currentTarget)); 9479 } 9480 } else if (!inCapturePhase) { 9481 var bubbleListener = getListener(instance, registrationName); 9482 9483 if (bubbleListener != null) { 9484 listeners.push(createDispatchListener(instance, bubbleListener, currentTarget)); 9485 } 9486 } 9487 } 9488 9489 instance = instance.return; 9490 } 9491 9492 if (listeners.length !== 0) { 9493 dispatchQueue.push({ 9494 event: event, 9495 listeners: listeners 9496 }); 9497 } 9498 } // We should only use this function for: 9499 // - EnterLeaveEventPlugin 9500 // This is because we only process this plugin 9501 // in the bubble phase, so we need to accumulate two 9502 // phase event listeners. 9503 9504 9505 function accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leaveEvent, enterEvent, from, to) { 9506 var common = from && to ? getLowestCommonAncestor(from, to) : null; 9507 9508 if (from !== null) { 9509 accumulateEnterLeaveListenersForEvent(dispatchQueue, leaveEvent, from, common, false); 9510 } 9511 9512 if (to !== null && enterEvent !== null) { 9513 accumulateEnterLeaveListenersForEvent(dispatchQueue, enterEvent, to, common, true); 9514 } 9515 } 9516 function getListenerSetKey(domEventName, capture) { 9517 return domEventName + "__" + (capture ? 'capture' : 'bubble'); 9518 } 9519 9520 var didWarnInvalidHydration = false; 9521 var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML'; 9522 var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning'; 9523 var SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning'; 9524 var AUTOFOCUS = 'autoFocus'; 9525 var CHILDREN = 'children'; 9526 var STYLE = 'style'; 9527 var HTML$1 = '__html'; 9528 var warnedUnknownTags; 9529 var validatePropertiesInDevelopment; 9530 var warnForPropDifference; 9531 var warnForExtraAttributes; 9532 var warnForInvalidEventListener; 9533 var canDiffStyleForHydrationWarning; 9534 var normalizeHTML; 9535 9536 { 9537 warnedUnknownTags = { 9538 // There are working polyfills for <dialog>. Let people use it. 9539 dialog: true, 9540 // Electron ships a custom <webview> tag to display external web content in 9541 // an isolated frame and process. 9542 // This tag is not present in non Electron environments such as JSDom which 9543 // is often used for testing purposes. 9544 // @see https://electronjs.org/docs/api/webview-tag 9545 webview: true 9546 }; 9547 9548 validatePropertiesInDevelopment = function (type, props) { 9549 validateProperties(type, props); 9550 validateProperties$1(type, props); 9551 validateProperties$2(type, props, { 9552 registrationNameDependencies: registrationNameDependencies, 9553 possibleRegistrationNames: possibleRegistrationNames 9554 }); 9555 }; // IE 11 parses & normalizes the style attribute as opposed to other 9556 // browsers. It adds spaces and sorts the properties in some 9557 // non-alphabetical order. Handling that would require sorting CSS 9558 // properties in the client & server versions or applying 9559 // `expectedStyle` to a temporary DOM node to read its `style` attribute 9560 // normalized. Since it only affects IE, we're skipping style warnings 9561 // in that browser completely in favor of doing all that work. 9562 // See https://github.com/facebook/react/issues/11807 9563 9564 9565 canDiffStyleForHydrationWarning = canUseDOM && !document.documentMode; 9566 9567 warnForPropDifference = function (propName, serverValue, clientValue) { 9568 if (didWarnInvalidHydration) { 9569 return; 9570 } 9571 9572 var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue); 9573 var normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue); 9574 9575 if (normalizedServerValue === normalizedClientValue) { 9576 return; 9577 } 9578 9579 didWarnInvalidHydration = true; 9580 9581 error('Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue)); 9582 }; 9583 9584 warnForExtraAttributes = function (attributeNames) { 9585 if (didWarnInvalidHydration) { 9586 return; 9587 } 9588 9589 didWarnInvalidHydration = true; 9590 var names = []; 9591 attributeNames.forEach(function (name) { 9592 names.push(name); 9593 }); 9594 9595 error('Extra attributes from the server: %s', names); 9596 }; 9597 9598 warnForInvalidEventListener = function (registrationName, listener) { 9599 if (listener === false) { 9600 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); 9601 } else { 9602 error('Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener); 9603 } 9604 }; // Parse the HTML and read it back to normalize the HTML string so that it 9605 // can be used for comparison. 9606 9607 9608 normalizeHTML = function (parent, html) { 9609 // We could have created a separate document here to avoid 9610 // re-initializing custom elements if they exist. But this breaks 9611 // how <noscript> is being handled. So we use the same document. 9612 // See the discussion in https://github.com/facebook/react/pull/11157. 9613 var testElement = parent.namespaceURI === HTML_NAMESPACE ? parent.ownerDocument.createElement(parent.tagName) : parent.ownerDocument.createElementNS(parent.namespaceURI, parent.tagName); 9614 testElement.innerHTML = html; 9615 return testElement.innerHTML; 9616 }; 9617 } // HTML parsing normalizes CR and CRLF to LF. 9618 // It also can turn \u0000 into \uFFFD inside attributes. 9619 // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream 9620 // If we have a mismatch, it might be caused by that. 9621 // We will still patch up in this case but not fire the warning. 9622 9623 9624 var NORMALIZE_NEWLINES_REGEX = /\r\n?/g; 9625 var NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g; 9626 9627 function normalizeMarkupForTextOrAttribute(markup) { 9628 { 9629 checkHtmlStringCoercion(markup); 9630 } 9631 9632 var markupString = typeof markup === 'string' ? markup : '' + markup; 9633 return markupString.replace(NORMALIZE_NEWLINES_REGEX, '\n').replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, ''); 9634 } 9635 9636 function checkForUnmatchedText(serverText, clientText, isConcurrentMode, shouldWarnDev) { 9637 var normalizedClientText = normalizeMarkupForTextOrAttribute(clientText); 9638 var normalizedServerText = normalizeMarkupForTextOrAttribute(serverText); 9639 9640 if (normalizedServerText === normalizedClientText) { 9641 return; 9642 } 9643 9644 if (shouldWarnDev) { 9645 { 9646 if (!didWarnInvalidHydration) { 9647 didWarnInvalidHydration = true; 9648 9649 error('Text content did not match. Server: "%s" Client: "%s"', normalizedServerText, normalizedClientText); 9650 } 9651 } 9652 } 9653 9654 if (isConcurrentMode && enableClientRenderFallbackOnTextMismatch) { 9655 // In concurrent roots, we throw when there's a text mismatch and revert to 9656 // client rendering, up to the nearest Suspense boundary. 9657 throw new Error('Text content does not match server-rendered HTML.'); 9658 } 9659 } 9660 9661 function getOwnerDocumentFromRootContainer(rootContainerElement) { 9662 return rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument; 9663 } 9664 9665 function noop() {} 9666 9667 function trapClickOnNonInteractiveElement(node) { 9668 // Mobile Safari does not fire properly bubble click events on 9669 // non-interactive elements, which means delegated click listeners do not 9670 // fire. The workaround for this bug involves attaching an empty click 9671 // listener on the target node. 9672 // https://www.quirksmode.org/blog/archives/2010/09/click_event_del.html 9673 // Just set it using the onclick property so that we don't have to manage any 9674 // bookkeeping for it. Not sure if we need to clear it when the listener is 9675 // removed. 9676 // TODO: Only do this for the relevant Safaris maybe? 9677 node.onclick = noop; 9678 } 9679 9680 function setInitialDOMProperties(tag, domElement, rootContainerElement, nextProps, isCustomComponentTag) { 9681 for (var propKey in nextProps) { 9682 if (!nextProps.hasOwnProperty(propKey)) { 9683 continue; 9684 } 9685 9686 var nextProp = nextProps[propKey]; 9687 9688 if (propKey === STYLE) { 9689 { 9690 if (nextProp) { 9691 // Freeze the next style object so that we can assume it won't be 9692 // mutated. We have already warned for this in the past. 9693 Object.freeze(nextProp); 9694 } 9695 } // Relies on `updateStylesByID` not mutating `styleUpdates`. 9696 9697 9698 setValueForStyles(domElement, nextProp); 9699 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) { 9700 var nextHtml = nextProp ? nextProp[HTML$1] : undefined; 9701 9702 if (nextHtml != null) { 9703 setInnerHTML(domElement, nextHtml); 9704 } 9705 } else if (propKey === CHILDREN) { 9706 if (typeof nextProp === 'string') { 9707 // Avoid setting initial textContent when the text is empty. In IE11 setting 9708 // textContent on a <textarea> will cause the placeholder to not 9709 // show within the <textarea> until it has been focused and blurred again. 9710 // https://github.com/facebook/react/issues/6731#issuecomment-254874553 9711 var canSetTextContent = tag !== 'textarea' || nextProp !== ''; 9712 9713 if (canSetTextContent) { 9714 setTextContent(domElement, nextProp); 9715 } 9716 } else if (typeof nextProp === 'number') { 9717 setTextContent(domElement, '' + nextProp); 9718 } 9719 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING) ; else if (propKey === AUTOFOCUS) ; else if (registrationNameDependencies.hasOwnProperty(propKey)) { 9720 if (nextProp != null) { 9721 if ( typeof nextProp !== 'function') { 9722 warnForInvalidEventListener(propKey, nextProp); 9723 } 9724 9725 if (propKey === 'onScroll') { 9726 listenToNonDelegatedEvent('scroll', domElement); 9727 } 9728 } 9729 } else if (nextProp != null) { 9730 setValueForProperty(domElement, propKey, nextProp, isCustomComponentTag); 9731 } 9732 } 9733 } 9734 9735 function updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag) { 9736 // TODO: Handle wasCustomComponentTag 9737 for (var i = 0; i < updatePayload.length; i += 2) { 9738 var propKey = updatePayload[i]; 9739 var propValue = updatePayload[i + 1]; 9740 9741 if (propKey === STYLE) { 9742 setValueForStyles(domElement, propValue); 9743 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) { 9744 setInnerHTML(domElement, propValue); 9745 } else if (propKey === CHILDREN) { 9746 setTextContent(domElement, propValue); 9747 } else { 9748 setValueForProperty(domElement, propKey, propValue, isCustomComponentTag); 9749 } 9750 } 9751 } 9752 9753 function createElement(type, props, rootContainerElement, parentNamespace) { 9754 var isCustomComponentTag; // We create tags in the namespace of their parent container, except HTML 9755 // tags get no namespace. 9756 9757 var ownerDocument = getOwnerDocumentFromRootContainer(rootContainerElement); 9758 var domElement; 9759 var namespaceURI = parentNamespace; 9760 9761 if (namespaceURI === HTML_NAMESPACE) { 9762 namespaceURI = getIntrinsicNamespace(type); 9763 } 9764 9765 if (namespaceURI === HTML_NAMESPACE) { 9766 { 9767 isCustomComponentTag = isCustomComponent(type, props); // Should this check be gated by parent namespace? Not sure we want to 9768 // allow <SVG> or <mATH>. 9769 9770 if (!isCustomComponentTag && type !== type.toLowerCase()) { 9771 error('<%s /> is using incorrect casing. ' + 'Use PascalCase for React components, ' + 'or lowercase for HTML elements.', type); 9772 } 9773 } 9774 9775 if (type === 'script') { 9776 // Create the script via .innerHTML so its "parser-inserted" flag is 9777 // set to true and it does not execute 9778 var div = ownerDocument.createElement('div'); 9779 9780 div.innerHTML = '<script><' + '/script>'; // eslint-disable-line 9781 // This is guaranteed to yield a script element. 9782 9783 var firstChild = div.firstChild; 9784 domElement = div.removeChild(firstChild); 9785 } else if (typeof props.is === 'string') { 9786 // $FlowIssue `createElement` should be updated for Web Components 9787 domElement = ownerDocument.createElement(type, { 9788 is: props.is 9789 }); 9790 } else { 9791 // Separate else branch instead of using `props.is || undefined` above because of a Firefox bug. 9792 // See discussion in https://github.com/facebook/react/pull/6896 9793 // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240 9794 domElement = ownerDocument.createElement(type); // Normally attributes are assigned in `setInitialDOMProperties`, however the `multiple` and `size` 9795 // attributes on `select`s needs to be added before `option`s are inserted. 9796 // This prevents: 9797 // - a bug where the `select` does not scroll to the correct option because singular 9798 // `select` elements automatically pick the first item #13222 9799 // - a bug where the `select` set the first item as selected despite the `size` attribute #14239 9800 // See https://github.com/facebook/react/issues/13222 9801 // and https://github.com/facebook/react/issues/14239 9802 9803 if (type === 'select') { 9804 var node = domElement; 9805 9806 if (props.multiple) { 9807 node.multiple = true; 9808 } else if (props.size) { 9809 // Setting a size greater than 1 causes a select to behave like `multiple=true`, where 9810 // it is possible that no option is selected. 9811 // 9812 // This is only necessary when a select in "single selection mode". 9813 node.size = props.size; 9814 } 9815 } 9816 } 9817 } else { 9818 domElement = ownerDocument.createElementNS(namespaceURI, type); 9819 } 9820 9821 { 9822 if (namespaceURI === HTML_NAMESPACE) { 9823 if (!isCustomComponentTag && Object.prototype.toString.call(domElement) === '[object HTMLUnknownElement]' && !hasOwnProperty.call(warnedUnknownTags, type)) { 9824 warnedUnknownTags[type] = true; 9825 9826 error('The tag <%s> is unrecognized in this browser. ' + 'If you meant to render a React component, start its name with ' + 'an uppercase letter.', type); 9827 } 9828 } 9829 } 9830 9831 return domElement; 9832 } 9833 function createTextNode(text, rootContainerElement) { 9834 return getOwnerDocumentFromRootContainer(rootContainerElement).createTextNode(text); 9835 } 9836 function setInitialProperties(domElement, tag, rawProps, rootContainerElement) { 9837 var isCustomComponentTag = isCustomComponent(tag, rawProps); 9838 9839 { 9840 validatePropertiesInDevelopment(tag, rawProps); 9841 } // TODO: Make sure that we check isMounted before firing any of these events. 9842 9843 9844 var props; 9845 9846 switch (tag) { 9847 case 'dialog': 9848 listenToNonDelegatedEvent('cancel', domElement); 9849 listenToNonDelegatedEvent('close', domElement); 9850 props = rawProps; 9851 break; 9852 9853 case 'iframe': 9854 case 'object': 9855 case 'embed': 9856 // We listen to this event in case to ensure emulated bubble 9857 // listeners still fire for the load event. 9858 listenToNonDelegatedEvent('load', domElement); 9859 props = rawProps; 9860 break; 9861 9862 case 'video': 9863 case 'audio': 9864 // We listen to these events in case to ensure emulated bubble 9865 // listeners still fire for all the media events. 9866 for (var i = 0; i < mediaEventTypes.length; i++) { 9867 listenToNonDelegatedEvent(mediaEventTypes[i], domElement); 9868 } 9869 9870 props = rawProps; 9871 break; 9872 9873 case 'source': 9874 // We listen to this event in case to ensure emulated bubble 9875 // listeners still fire for the error event. 9876 listenToNonDelegatedEvent('error', domElement); 9877 props = rawProps; 9878 break; 9879 9880 case 'img': 9881 case 'image': 9882 case 'link': 9883 // We listen to these events in case to ensure emulated bubble 9884 // listeners still fire for error and load events. 9885 listenToNonDelegatedEvent('error', domElement); 9886 listenToNonDelegatedEvent('load', domElement); 9887 props = rawProps; 9888 break; 9889 9890 case 'details': 9891 // We listen to this event in case to ensure emulated bubble 9892 // listeners still fire for the toggle event. 9893 listenToNonDelegatedEvent('toggle', domElement); 9894 props = rawProps; 9895 break; 9896 9897 case 'input': 9898 initWrapperState(domElement, rawProps); 9899 props = getHostProps(domElement, rawProps); // We listen to this event in case to ensure emulated bubble 9900 // listeners still fire for the invalid event. 9901 9902 listenToNonDelegatedEvent('invalid', domElement); 9903 break; 9904 9905 case 'option': 9906 validateProps(domElement, rawProps); 9907 props = rawProps; 9908 break; 9909 9910 case 'select': 9911 initWrapperState$1(domElement, rawProps); 9912 props = getHostProps$1(domElement, rawProps); // We listen to this event in case to ensure emulated bubble 9913 // listeners still fire for the invalid event. 9914 9915 listenToNonDelegatedEvent('invalid', domElement); 9916 break; 9917 9918 case 'textarea': 9919 initWrapperState$2(domElement, rawProps); 9920 props = getHostProps$2(domElement, rawProps); // We listen to this event in case to ensure emulated bubble 9921 // listeners still fire for the invalid event. 9922 9923 listenToNonDelegatedEvent('invalid', domElement); 9924 break; 9925 9926 default: 9927 props = rawProps; 9928 } 9929 9930 assertValidProps(tag, props); 9931 setInitialDOMProperties(tag, domElement, rootContainerElement, props, isCustomComponentTag); 9932 9933 switch (tag) { 9934 case 'input': 9935 // TODO: Make sure we check if this is still unmounted or do any clean 9936 // up necessary since we never stop tracking anymore. 9937 track(domElement); 9938 postMountWrapper(domElement, rawProps, false); 9939 break; 9940 9941 case 'textarea': 9942 // TODO: Make sure we check if this is still unmounted or do any clean 9943 // up necessary since we never stop tracking anymore. 9944 track(domElement); 9945 postMountWrapper$3(domElement); 9946 break; 9947 9948 case 'option': 9949 postMountWrapper$1(domElement, rawProps); 9950 break; 9951 9952 case 'select': 9953 postMountWrapper$2(domElement, rawProps); 9954 break; 9955 9956 default: 9957 if (typeof props.onClick === 'function') { 9958 // TODO: This cast may not be sound for SVG, MathML or custom elements. 9959 trapClickOnNonInteractiveElement(domElement); 9960 } 9961 9962 break; 9963 } 9964 } // Calculate the diff between the two objects. 9965 9966 function diffProperties(domElement, tag, lastRawProps, nextRawProps, rootContainerElement) { 9967 { 9968 validatePropertiesInDevelopment(tag, nextRawProps); 9969 } 9970 9971 var updatePayload = null; 9972 var lastProps; 9973 var nextProps; 9974 9975 switch (tag) { 9976 case 'input': 9977 lastProps = getHostProps(domElement, lastRawProps); 9978 nextProps = getHostProps(domElement, nextRawProps); 9979 updatePayload = []; 9980 break; 9981 9982 case 'select': 9983 lastProps = getHostProps$1(domElement, lastRawProps); 9984 nextProps = getHostProps$1(domElement, nextRawProps); 9985 updatePayload = []; 9986 break; 9987 9988 case 'textarea': 9989 lastProps = getHostProps$2(domElement, lastRawProps); 9990 nextProps = getHostProps$2(domElement, nextRawProps); 9991 updatePayload = []; 9992 break; 9993 9994 default: 9995 lastProps = lastRawProps; 9996 nextProps = nextRawProps; 9997 9998 if (typeof lastProps.onClick !== 'function' && typeof nextProps.onClick === 'function') { 9999 // TODO: This cast may not be sound for SVG, MathML or custom elements. 10000 trapClickOnNonInteractiveElement(domElement); 10001 } 10002 10003 break; 10004 } 10005 10006 assertValidProps(tag, nextProps); 10007 var propKey; 10008 var styleName; 10009 var styleUpdates = null; 10010 10011 for (propKey in lastProps) { 10012 if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) { 10013 continue; 10014 } 10015 10016 if (propKey === STYLE) { 10017 var lastStyle = lastProps[propKey]; 10018 10019 for (styleName in lastStyle) { 10020 if (lastStyle.hasOwnProperty(styleName)) { 10021 if (!styleUpdates) { 10022 styleUpdates = {}; 10023 } 10024 10025 styleUpdates[styleName] = ''; 10026 } 10027 } 10028 } else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN) ; else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING) ; else if (propKey === AUTOFOCUS) ; else if (registrationNameDependencies.hasOwnProperty(propKey)) { 10029 // This is a special case. If any listener updates we need to ensure 10030 // that the "current" fiber pointer gets updated so we need a commit 10031 // to update this element. 10032 if (!updatePayload) { 10033 updatePayload = []; 10034 } 10035 } else { 10036 // For all other deleted properties we add it to the queue. We use 10037 // the allowed property list in the commit phase instead. 10038 (updatePayload = updatePayload || []).push(propKey, null); 10039 } 10040 } 10041 10042 for (propKey in nextProps) { 10043 var nextProp = nextProps[propKey]; 10044 var lastProp = lastProps != null ? lastProps[propKey] : undefined; 10045 10046 if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) { 10047 continue; 10048 } 10049 10050 if (propKey === STYLE) { 10051 { 10052 if (nextProp) { 10053 // Freeze the next style object so that we can assume it won't be 10054 // mutated. We have already warned for this in the past. 10055 Object.freeze(nextProp); 10056 } 10057 } 10058 10059 if (lastProp) { 10060 // Unset styles on `lastProp` but not on `nextProp`. 10061 for (styleName in lastProp) { 10062 if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) { 10063 if (!styleUpdates) { 10064 styleUpdates = {}; 10065 } 10066 10067 styleUpdates[styleName] = ''; 10068 } 10069 } // Update styles that changed since `lastProp`. 10070 10071 10072 for (styleName in nextProp) { 10073 if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) { 10074 if (!styleUpdates) { 10075 styleUpdates = {}; 10076 } 10077 10078 styleUpdates[styleName] = nextProp[styleName]; 10079 } 10080 } 10081 } else { 10082 // Relies on `updateStylesByID` not mutating `styleUpdates`. 10083 if (!styleUpdates) { 10084 if (!updatePayload) { 10085 updatePayload = []; 10086 } 10087 10088 updatePayload.push(propKey, styleUpdates); 10089 } 10090 10091 styleUpdates = nextProp; 10092 } 10093 } else if (propKey === DANGEROUSLY_SET_INNER_HTML) { 10094 var nextHtml = nextProp ? nextProp[HTML$1] : undefined; 10095 var lastHtml = lastProp ? lastProp[HTML$1] : undefined; 10096 10097 if (nextHtml != null) { 10098 if (lastHtml !== nextHtml) { 10099 (updatePayload = updatePayload || []).push(propKey, nextHtml); 10100 } 10101 } 10102 } else if (propKey === CHILDREN) { 10103 if (typeof nextProp === 'string' || typeof nextProp === 'number') { 10104 (updatePayload = updatePayload || []).push(propKey, '' + nextProp); 10105 } 10106 } else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING) ; else if (registrationNameDependencies.hasOwnProperty(propKey)) { 10107 if (nextProp != null) { 10108 // We eagerly listen to this even though we haven't committed yet. 10109 if ( typeof nextProp !== 'function') { 10110 warnForInvalidEventListener(propKey, nextProp); 10111 } 10112 10113 if (propKey === 'onScroll') { 10114 listenToNonDelegatedEvent('scroll', domElement); 10115 } 10116 } 10117 10118 if (!updatePayload && lastProp !== nextProp) { 10119 // This is a special case. If any listener updates we need to ensure 10120 // that the "current" props pointer gets updated so we need a commit 10121 // to update this element. 10122 updatePayload = []; 10123 } 10124 } else { 10125 // For any other property we always add it to the queue and then we 10126 // filter it out using the allowed property list during the commit. 10127 (updatePayload = updatePayload || []).push(propKey, nextProp); 10128 } 10129 } 10130 10131 if (styleUpdates) { 10132 { 10133 validateShorthandPropertyCollisionInDev(styleUpdates, nextProps[STYLE]); 10134 } 10135 10136 (updatePayload = updatePayload || []).push(STYLE, styleUpdates); 10137 } 10138 10139 return updatePayload; 10140 } // Apply the diff. 10141 10142 function updateProperties(domElement, updatePayload, tag, lastRawProps, nextRawProps) { 10143 // Update checked *before* name. 10144 // In the middle of an update, it is possible to have multiple checked. 10145 // When a checked radio tries to change name, browser makes another radio's checked false. 10146 if (tag === 'input' && nextRawProps.type === 'radio' && nextRawProps.name != null) { 10147 updateChecked(domElement, nextRawProps); 10148 } 10149 10150 var wasCustomComponentTag = isCustomComponent(tag, lastRawProps); 10151 var isCustomComponentTag = isCustomComponent(tag, nextRawProps); // Apply the diff. 10152 10153 updateDOMProperties(domElement, updatePayload, wasCustomComponentTag, isCustomComponentTag); // TODO: Ensure that an update gets scheduled if any of the special props 10154 // changed. 10155 10156 switch (tag) { 10157 case 'input': 10158 // Update the wrapper around inputs *after* updating props. This has to 10159 // happen after `updateDOMProperties`. Otherwise HTML5 input validations 10160 // raise warnings and prevent the new value from being assigned. 10161 updateWrapper(domElement, nextRawProps); 10162 break; 10163 10164 case 'textarea': 10165 updateWrapper$1(domElement, nextRawProps); 10166 break; 10167 10168 case 'select': 10169 // <select> value update needs to occur after <option> children 10170 // reconciliation 10171 postUpdateWrapper(domElement, nextRawProps); 10172 break; 10173 } 10174 } 10175 10176 function getPossibleStandardName(propName) { 10177 { 10178 var lowerCasedName = propName.toLowerCase(); 10179 10180 if (!possibleStandardNames.hasOwnProperty(lowerCasedName)) { 10181 return null; 10182 } 10183 10184 return possibleStandardNames[lowerCasedName] || null; 10185 } 10186 } 10187 10188 function diffHydratedProperties(domElement, tag, rawProps, parentNamespace, rootContainerElement, isConcurrentMode, shouldWarnDev) { 10189 var isCustomComponentTag; 10190 var extraAttributeNames; 10191 10192 { 10193 isCustomComponentTag = isCustomComponent(tag, rawProps); 10194 validatePropertiesInDevelopment(tag, rawProps); 10195 } // TODO: Make sure that we check isMounted before firing any of these events. 10196 10197 10198 switch (tag) { 10199 case 'dialog': 10200 listenToNonDelegatedEvent('cancel', domElement); 10201 listenToNonDelegatedEvent('close', domElement); 10202 break; 10203 10204 case 'iframe': 10205 case 'object': 10206 case 'embed': 10207 // We listen to this event in case to ensure emulated bubble 10208 // listeners still fire for the load event. 10209 listenToNonDelegatedEvent('load', domElement); 10210 break; 10211 10212 case 'video': 10213 case 'audio': 10214 // We listen to these events in case to ensure emulated bubble 10215 // listeners still fire for all the media events. 10216 for (var i = 0; i < mediaEventTypes.length; i++) { 10217 listenToNonDelegatedEvent(mediaEventTypes[i], domElement); 10218 } 10219 10220 break; 10221 10222 case 'source': 10223 // We listen to this event in case to ensure emulated bubble 10224 // listeners still fire for the error event. 10225 listenToNonDelegatedEvent('error', domElement); 10226 break; 10227 10228 case 'img': 10229 case 'image': 10230 case 'link': 10231 // We listen to these events in case to ensure emulated bubble 10232 // listeners still fire for error and load events. 10233 listenToNonDelegatedEvent('error', domElement); 10234 listenToNonDelegatedEvent('load', domElement); 10235 break; 10236 10237 case 'details': 10238 // We listen to this event in case to ensure emulated bubble 10239 // listeners still fire for the toggle event. 10240 listenToNonDelegatedEvent('toggle', domElement); 10241 break; 10242 10243 case 'input': 10244 initWrapperState(domElement, rawProps); // We listen to this event in case to ensure emulated bubble 10245 // listeners still fire for the invalid event. 10246 10247 listenToNonDelegatedEvent('invalid', domElement); 10248 break; 10249 10250 case 'option': 10251 validateProps(domElement, rawProps); 10252 break; 10253 10254 case 'select': 10255 initWrapperState$1(domElement, rawProps); // We listen to this event in case to ensure emulated bubble 10256 // listeners still fire for the invalid event. 10257 10258 listenToNonDelegatedEvent('invalid', domElement); 10259 break; 10260 10261 case 'textarea': 10262 initWrapperState$2(domElement, rawProps); // We listen to this event in case to ensure emulated bubble 10263 // listeners still fire for the invalid event. 10264 10265 listenToNonDelegatedEvent('invalid', domElement); 10266 break; 10267 } 10268 10269 assertValidProps(tag, rawProps); 10270 10271 { 10272 extraAttributeNames = new Set(); 10273 var attributes = domElement.attributes; 10274 10275 for (var _i = 0; _i < attributes.length; _i++) { 10276 var name = attributes[_i].name.toLowerCase(); 10277 10278 switch (name) { 10279 // Controlled attributes are not validated 10280 // TODO: Only ignore them on controlled tags. 10281 case 'value': 10282 break; 10283 10284 case 'checked': 10285 break; 10286 10287 case 'selected': 10288 break; 10289 10290 default: 10291 // Intentionally use the original name. 10292 // See discussion in https://github.com/facebook/react/pull/10676. 10293 extraAttributeNames.add(attributes[_i].name); 10294 } 10295 } 10296 } 10297 10298 var updatePayload = null; 10299 10300 for (var propKey in rawProps) { 10301 if (!rawProps.hasOwnProperty(propKey)) { 10302 continue; 10303 } 10304 10305 var nextProp = rawProps[propKey]; 10306 10307 if (propKey === CHILDREN) { 10308 // For text content children we compare against textContent. This 10309 // might match additional HTML that is hidden when we read it using 10310 // textContent. E.g. "foo" will match "f<span>oo</span>" but that still 10311 // satisfies our requirement. Our requirement is not to produce perfect 10312 // HTML and attributes. Ideally we should preserve structure but it's 10313 // ok not to if the visible content is still enough to indicate what 10314 // even listeners these nodes might be wired up to. 10315 // TODO: Warn if there is more than a single textNode as a child. 10316 // TODO: Should we use domElement.firstChild.nodeValue to compare? 10317 if (typeof nextProp === 'string') { 10318 if (domElement.textContent !== nextProp) { 10319 if (rawProps[SUPPRESS_HYDRATION_WARNING] !== true) { 10320 checkForUnmatchedText(domElement.textContent, nextProp, isConcurrentMode, shouldWarnDev); 10321 } 10322 10323 updatePayload = [CHILDREN, nextProp]; 10324 } 10325 } else if (typeof nextProp === 'number') { 10326 if (domElement.textContent !== '' + nextProp) { 10327 if (rawProps[SUPPRESS_HYDRATION_WARNING] !== true) { 10328 checkForUnmatchedText(domElement.textContent, nextProp, isConcurrentMode, shouldWarnDev); 10329 } 10330 10331 updatePayload = [CHILDREN, '' + nextProp]; 10332 } 10333 } 10334 } else if (registrationNameDependencies.hasOwnProperty(propKey)) { 10335 if (nextProp != null) { 10336 if ( typeof nextProp !== 'function') { 10337 warnForInvalidEventListener(propKey, nextProp); 10338 } 10339 10340 if (propKey === 'onScroll') { 10341 listenToNonDelegatedEvent('scroll', domElement); 10342 } 10343 } 10344 } else if (shouldWarnDev && true && // Convince Flow we've calculated it (it's DEV-only in this method.) 10345 typeof isCustomComponentTag === 'boolean') { 10346 // Validate that the properties correspond to their expected values. 10347 var serverValue = void 0; 10348 var propertyInfo = isCustomComponentTag && enableCustomElementPropertySupport ? null : getPropertyInfo(propKey); 10349 10350 if (rawProps[SUPPRESS_HYDRATION_WARNING] === true) ; else if (propKey === SUPPRESS_CONTENT_EDITABLE_WARNING || propKey === SUPPRESS_HYDRATION_WARNING || // Controlled attributes are not validated 10351 // TODO: Only ignore them on controlled tags. 10352 propKey === 'value' || propKey === 'checked' || propKey === 'selected') ; else if (propKey === DANGEROUSLY_SET_INNER_HTML) { 10353 var serverHTML = domElement.innerHTML; 10354 var nextHtml = nextProp ? nextProp[HTML$1] : undefined; 10355 10356 if (nextHtml != null) { 10357 var expectedHTML = normalizeHTML(domElement, nextHtml); 10358 10359 if (expectedHTML !== serverHTML) { 10360 warnForPropDifference(propKey, serverHTML, expectedHTML); 10361 } 10362 } 10363 } else if (propKey === STYLE) { 10364 // $FlowFixMe - Should be inferred as not undefined. 10365 extraAttributeNames.delete(propKey); 10366 10367 if (canDiffStyleForHydrationWarning) { 10368 var expectedStyle = createDangerousStringForStyles(nextProp); 10369 serverValue = domElement.getAttribute('style'); 10370 10371 if (expectedStyle !== serverValue) { 10372 warnForPropDifference(propKey, serverValue, expectedStyle); 10373 } 10374 } 10375 } else if (isCustomComponentTag && !enableCustomElementPropertySupport) { 10376 // $FlowFixMe - Should be inferred as not undefined. 10377 extraAttributeNames.delete(propKey.toLowerCase()); 10378 serverValue = getValueForAttribute(domElement, propKey, nextProp); 10379 10380 if (nextProp !== serverValue) { 10381 warnForPropDifference(propKey, serverValue, nextProp); 10382 } 10383 } else if (!shouldIgnoreAttribute(propKey, propertyInfo, isCustomComponentTag) && !shouldRemoveAttribute(propKey, nextProp, propertyInfo, isCustomComponentTag)) { 10384 var isMismatchDueToBadCasing = false; 10385 10386 if (propertyInfo !== null) { 10387 // $FlowFixMe - Should be inferred as not undefined. 10388 extraAttributeNames.delete(propertyInfo.attributeName); 10389 serverValue = getValueForProperty(domElement, propKey, nextProp, propertyInfo); 10390 } else { 10391 var ownNamespace = parentNamespace; 10392 10393 if (ownNamespace === HTML_NAMESPACE) { 10394 ownNamespace = getIntrinsicNamespace(tag); 10395 } 10396 10397 if (ownNamespace === HTML_NAMESPACE) { 10398 // $FlowFixMe - Should be inferred as not undefined. 10399 extraAttributeNames.delete(propKey.toLowerCase()); 10400 } else { 10401 var standardName = getPossibleStandardName(propKey); 10402 10403 if (standardName !== null && standardName !== propKey) { 10404 // If an SVG prop is supplied with bad casing, it will 10405 // be successfully parsed from HTML, but will produce a mismatch 10406 // (and would be incorrectly rendered on the client). 10407 // However, we already warn about bad casing elsewhere. 10408 // So we'll skip the misleading extra mismatch warning in this case. 10409 isMismatchDueToBadCasing = true; // $FlowFixMe - Should be inferred as not undefined. 10410 10411 extraAttributeNames.delete(standardName); 10412 } // $FlowFixMe - Should be inferred as not undefined. 10413 10414 10415 extraAttributeNames.delete(propKey); 10416 } 10417 10418 serverValue = getValueForAttribute(domElement, propKey, nextProp); 10419 } 10420 10421 var dontWarnCustomElement = enableCustomElementPropertySupport ; 10422 10423 if (!dontWarnCustomElement && nextProp !== serverValue && !isMismatchDueToBadCasing) { 10424 warnForPropDifference(propKey, serverValue, nextProp); 10425 } 10426 } 10427 } 10428 } 10429 10430 { 10431 if (shouldWarnDev) { 10432 if ( // $FlowFixMe - Should be inferred as not undefined. 10433 extraAttributeNames.size > 0 && rawProps[SUPPRESS_HYDRATION_WARNING] !== true) { 10434 // $FlowFixMe - Should be inferred as not undefined. 10435 warnForExtraAttributes(extraAttributeNames); 10436 } 10437 } 10438 } 10439 10440 switch (tag) { 10441 case 'input': 10442 // TODO: Make sure we check if this is still unmounted or do any clean 10443 // up necessary since we never stop tracking anymore. 10444 track(domElement); 10445 postMountWrapper(domElement, rawProps, true); 10446 break; 10447 10448 case 'textarea': 10449 // TODO: Make sure we check if this is still unmounted or do any clean 10450 // up necessary since we never stop tracking anymore. 10451 track(domElement); 10452 postMountWrapper$3(domElement); 10453 break; 10454 10455 case 'select': 10456 case 'option': 10457 // For input and textarea we current always set the value property at 10458 // post mount to force it to diverge from attributes. However, for 10459 // option and select we don't quite do the same thing and select 10460 // is not resilient to the DOM state changing so we don't do that here. 10461 // TODO: Consider not doing this for input and textarea. 10462 break; 10463 10464 default: 10465 if (typeof rawProps.onClick === 'function') { 10466 // TODO: This cast may not be sound for SVG, MathML or custom elements. 10467 trapClickOnNonInteractiveElement(domElement); 10468 } 10469 10470 break; 10471 } 10472 10473 return updatePayload; 10474 } 10475 function diffHydratedText(textNode, text, isConcurrentMode) { 10476 var isDifferent = textNode.nodeValue !== text; 10477 return isDifferent; 10478 } 10479 function warnForDeletedHydratableElement(parentNode, child) { 10480 { 10481 if (didWarnInvalidHydration) { 10482 return; 10483 } 10484 10485 didWarnInvalidHydration = true; 10486 10487 error('Did not expect server HTML to contain a <%s> in <%s>.', child.nodeName.toLowerCase(), parentNode.nodeName.toLowerCase()); 10488 } 10489 } 10490 function warnForDeletedHydratableText(parentNode, child) { 10491 { 10492 if (didWarnInvalidHydration) { 10493 return; 10494 } 10495 10496 didWarnInvalidHydration = true; 10497 10498 error('Did not expect server HTML to contain the text node "%s" in <%s>.', child.nodeValue, parentNode.nodeName.toLowerCase()); 10499 } 10500 } 10501 function warnForInsertedHydratedElement(parentNode, tag, props) { 10502 { 10503 if (didWarnInvalidHydration) { 10504 return; 10505 } 10506 10507 didWarnInvalidHydration = true; 10508 10509 error('Expected server HTML to contain a matching <%s> in <%s>.', tag, parentNode.nodeName.toLowerCase()); 10510 } 10511 } 10512 function warnForInsertedHydratedText(parentNode, text) { 10513 { 10514 if (text === '') { 10515 // We expect to insert empty text nodes since they're not represented in 10516 // the HTML. 10517 // TODO: Remove this special case if we can just avoid inserting empty 10518 // text nodes. 10519 return; 10520 } 10521 10522 if (didWarnInvalidHydration) { 10523 return; 10524 } 10525 10526 didWarnInvalidHydration = true; 10527 10528 error('Expected server HTML to contain a matching text node for "%s" in <%s>.', text, parentNode.nodeName.toLowerCase()); 10529 } 10530 } 10531 function restoreControlledState$3(domElement, tag, props) { 10532 switch (tag) { 10533 case 'input': 10534 restoreControlledState(domElement, props); 10535 return; 10536 10537 case 'textarea': 10538 restoreControlledState$2(domElement, props); 10539 return; 10540 10541 case 'select': 10542 restoreControlledState$1(domElement, props); 10543 return; 10544 } 10545 } 10546 10547 var validateDOMNesting = function () {}; 10548 10549 var updatedAncestorInfo = function () {}; 10550 10551 { 10552 // This validation code was written based on the HTML5 parsing spec: 10553 // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope 10554 // 10555 // Note: this does not catch all invalid nesting, nor does it try to (as it's 10556 // not clear what practical benefit doing so provides); instead, we warn only 10557 // for cases where the parser will give a parse tree differing from what React 10558 // intended. For example, <b><div></div></b> is invalid but we don't warn 10559 // because it still parses correctly; we do warn for other cases like nested 10560 // <p> tags where the beginning of the second element implicitly closes the 10561 // first, causing a confusing mess. 10562 // https://html.spec.whatwg.org/multipage/syntax.html#special 10563 var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp']; // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope 10564 10565 var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template', // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point 10566 // TODO: Distinguish by namespace here -- for <title>, including it here 10567 // errs on the side of fewer warnings 10568 'foreignObject', 'desc', 'title']; // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope 10569 10570 var buttonScopeTags = inScopeTags.concat(['button']); // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags 10571 10572 var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt']; 10573 var emptyAncestorInfo = { 10574 current: null, 10575 formTag: null, 10576 aTagInScope: null, 10577 buttonTagInScope: null, 10578 nobrTagInScope: null, 10579 pTagInButtonScope: null, 10580 listItemTagAutoclosing: null, 10581 dlItemTagAutoclosing: null 10582 }; 10583 10584 updatedAncestorInfo = function (oldInfo, tag) { 10585 var ancestorInfo = assign({}, oldInfo || emptyAncestorInfo); 10586 10587 var info = { 10588 tag: tag 10589 }; 10590 10591 if (inScopeTags.indexOf(tag) !== -1) { 10592 ancestorInfo.aTagInScope = null; 10593 ancestorInfo.buttonTagInScope = null; 10594 ancestorInfo.nobrTagInScope = null; 10595 } 10596 10597 if (buttonScopeTags.indexOf(tag) !== -1) { 10598 ancestorInfo.pTagInButtonScope = null; 10599 } // See rules for 'li', 'dd', 'dt' start tags in 10600 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody 10601 10602 10603 if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') { 10604 ancestorInfo.listItemTagAutoclosing = null; 10605 ancestorInfo.dlItemTagAutoclosing = null; 10606 } 10607 10608 ancestorInfo.current = info; 10609 10610 if (tag === 'form') { 10611 ancestorInfo.formTag = info; 10612 } 10613 10614 if (tag === 'a') { 10615 ancestorInfo.aTagInScope = info; 10616 } 10617 10618 if (tag === 'button') { 10619 ancestorInfo.buttonTagInScope = info; 10620 } 10621 10622 if (tag === 'nobr') { 10623 ancestorInfo.nobrTagInScope = info; 10624 } 10625 10626 if (tag === 'p') { 10627 ancestorInfo.pTagInButtonScope = info; 10628 } 10629 10630 if (tag === 'li') { 10631 ancestorInfo.listItemTagAutoclosing = info; 10632 } 10633 10634 if (tag === 'dd' || tag === 'dt') { 10635 ancestorInfo.dlItemTagAutoclosing = info; 10636 } 10637 10638 return ancestorInfo; 10639 }; 10640 /** 10641 * Returns whether 10642 */ 10643 10644 10645 var isTagValidWithParent = function (tag, parentTag) { 10646 // First, let's check if we're in an unusual parsing mode... 10647 switch (parentTag) { 10648 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect 10649 case 'select': 10650 return tag === 'option' || tag === 'optgroup' || tag === '#text'; 10651 10652 case 'optgroup': 10653 return tag === 'option' || tag === '#text'; 10654 // Strictly speaking, seeing an <option> doesn't mean we're in a <select> 10655 // but 10656 10657 case 'option': 10658 return tag === '#text'; 10659 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd 10660 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption 10661 // No special behavior since these rules fall back to "in body" mode for 10662 // all except special table nodes which cause bad parsing behavior anyway. 10663 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr 10664 10665 case 'tr': 10666 return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template'; 10667 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody 10668 10669 case 'tbody': 10670 case 'thead': 10671 case 'tfoot': 10672 return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template'; 10673 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup 10674 10675 case 'colgroup': 10676 return tag === 'col' || tag === 'template'; 10677 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable 10678 10679 case 'table': 10680 return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template'; 10681 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead 10682 10683 case 'head': 10684 return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template'; 10685 // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element 10686 10687 case 'html': 10688 return tag === 'head' || tag === 'body' || tag === 'frameset'; 10689 10690 case 'frameset': 10691 return tag === 'frame'; 10692 10693 case '#document': 10694 return tag === 'html'; 10695 } // Probably in the "in body" parsing mode, so we outlaw only tag combos 10696 // where the parsing rules cause implicit opens or closes to be added. 10697 // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody 10698 10699 10700 switch (tag) { 10701 case 'h1': 10702 case 'h2': 10703 case 'h3': 10704 case 'h4': 10705 case 'h5': 10706 case 'h6': 10707 return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6'; 10708 10709 case 'rp': 10710 case 'rt': 10711 return impliedEndTags.indexOf(parentTag) === -1; 10712 10713 case 'body': 10714 case 'caption': 10715 case 'col': 10716 case 'colgroup': 10717 case 'frameset': 10718 case 'frame': 10719 case 'head': 10720 case 'html': 10721 case 'tbody': 10722 case 'td': 10723 case 'tfoot': 10724 case 'th': 10725 case 'thead': 10726 case 'tr': 10727 // These tags are only valid with a few parents that have special child 10728 // parsing rules -- if we're down here, then none of those matched and 10729 // so we allow it only if we don't know what the parent is, as all other 10730 // cases are invalid. 10731 return parentTag == null; 10732 } 10733 10734 return true; 10735 }; 10736 /** 10737 * Returns whether 10738 */ 10739 10740 10741 var findInvalidAncestorForTag = function (tag, ancestorInfo) { 10742 switch (tag) { 10743 case 'address': 10744 case 'article': 10745 case 'aside': 10746 case 'blockquote': 10747 case 'center': 10748 case 'details': 10749 case 'dialog': 10750 case 'dir': 10751 case 'div': 10752 case 'dl': 10753 case 'fieldset': 10754 case 'figcaption': 10755 case 'figure': 10756 case 'footer': 10757 case 'header': 10758 case 'hgroup': 10759 case 'main': 10760 case 'menu': 10761 case 'nav': 10762 case 'ol': 10763 case 'p': 10764 case 'section': 10765 case 'summary': 10766 case 'ul': 10767 case 'pre': 10768 case 'listing': 10769 case 'table': 10770 case 'hr': 10771 case 'xmp': 10772 case 'h1': 10773 case 'h2': 10774 case 'h3': 10775 case 'h4': 10776 case 'h5': 10777 case 'h6': 10778 return ancestorInfo.pTagInButtonScope; 10779 10780 case 'form': 10781 return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope; 10782 10783 case 'li': 10784 return ancestorInfo.listItemTagAutoclosing; 10785 10786 case 'dd': 10787 case 'dt': 10788 return ancestorInfo.dlItemTagAutoclosing; 10789 10790 case 'button': 10791 return ancestorInfo.buttonTagInScope; 10792 10793 case 'a': 10794 // Spec says something about storing a list of markers, but it sounds 10795 // equivalent to this check. 10796 return ancestorInfo.aTagInScope; 10797 10798 case 'nobr': 10799 return ancestorInfo.nobrTagInScope; 10800 } 10801 10802 return null; 10803 }; 10804 10805 var didWarn$1 = {}; 10806 10807 validateDOMNesting = function (childTag, childText, ancestorInfo) { 10808 ancestorInfo = ancestorInfo || emptyAncestorInfo; 10809 var parentInfo = ancestorInfo.current; 10810 var parentTag = parentInfo && parentInfo.tag; 10811 10812 if (childText != null) { 10813 if (childTag != null) { 10814 error('validateDOMNesting: when childText is passed, childTag should be null'); 10815 } 10816 10817 childTag = '#text'; 10818 } 10819 10820 var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo; 10821 var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo); 10822 var invalidParentOrAncestor = invalidParent || invalidAncestor; 10823 10824 if (!invalidParentOrAncestor) { 10825 return; 10826 } 10827 10828 var ancestorTag = invalidParentOrAncestor.tag; 10829 var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag; 10830 10831 if (didWarn$1[warnKey]) { 10832 return; 10833 } 10834 10835 didWarn$1[warnKey] = true; 10836 var tagDisplayName = childTag; 10837 var whitespaceInfo = ''; 10838 10839 if (childTag === '#text') { 10840 if (/\S/.test(childText)) { 10841 tagDisplayName = 'Text nodes'; 10842 } else { 10843 tagDisplayName = 'Whitespace text nodes'; 10844 whitespaceInfo = " Make sure you don't have any extra whitespace between tags on " + 'each line of your source code.'; 10845 } 10846 } else { 10847 tagDisplayName = '<' + childTag + '>'; 10848 } 10849 10850 if (invalidParent) { 10851 var info = ''; 10852 10853 if (ancestorTag === 'table' && childTag === 'tr') { 10854 info += ' Add a <tbody>, <thead> or <tfoot> to your code to match the DOM tree generated by ' + 'the browser.'; 10855 } 10856 10857 error('validateDOMNesting(...): %s cannot appear as a child of <%s>.%s%s', tagDisplayName, ancestorTag, whitespaceInfo, info); 10858 } else { 10859 error('validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>.', tagDisplayName, ancestorTag); 10860 } 10861 }; 10862 } 10863 10864 var SUPPRESS_HYDRATION_WARNING$1 = 'suppressHydrationWarning'; 10865 var SUSPENSE_START_DATA = '$'; 10866 var SUSPENSE_END_DATA = '/$'; 10867 var SUSPENSE_PENDING_START_DATA = '$?'; 10868 var SUSPENSE_FALLBACK_START_DATA = '$!'; 10869 var STYLE$1 = 'style'; 10870 var eventsEnabled = null; 10871 var selectionInformation = null; 10872 function getRootHostContext(rootContainerInstance) { 10873 var type; 10874 var namespace; 10875 var nodeType = rootContainerInstance.nodeType; 10876 10877 switch (nodeType) { 10878 case DOCUMENT_NODE: 10879 case DOCUMENT_FRAGMENT_NODE: 10880 { 10881 type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment'; 10882 var root = rootContainerInstance.documentElement; 10883 namespace = root ? root.namespaceURI : getChildNamespace(null, ''); 10884 break; 10885 } 10886 10887 default: 10888 { 10889 var container = nodeType === COMMENT_NODE ? rootContainerInstance.parentNode : rootContainerInstance; 10890 var ownNamespace = container.namespaceURI || null; 10891 type = container.tagName; 10892 namespace = getChildNamespace(ownNamespace, type); 10893 break; 10894 } 10895 } 10896 10897 { 10898 var validatedTag = type.toLowerCase(); 10899 var ancestorInfo = updatedAncestorInfo(null, validatedTag); 10900 return { 10901 namespace: namespace, 10902 ancestorInfo: ancestorInfo 10903 }; 10904 } 10905 } 10906 function getChildHostContext(parentHostContext, type, rootContainerInstance) { 10907 { 10908 var parentHostContextDev = parentHostContext; 10909 var namespace = getChildNamespace(parentHostContextDev.namespace, type); 10910 var ancestorInfo = updatedAncestorInfo(parentHostContextDev.ancestorInfo, type); 10911 return { 10912 namespace: namespace, 10913 ancestorInfo: ancestorInfo 10914 }; 10915 } 10916 } 10917 function getPublicInstance(instance) { 10918 return instance; 10919 } 10920 function prepareForCommit(containerInfo) { 10921 eventsEnabled = isEnabled(); 10922 selectionInformation = getSelectionInformation(); 10923 var activeInstance = null; 10924 10925 setEnabled(false); 10926 return activeInstance; 10927 } 10928 function resetAfterCommit(containerInfo) { 10929 restoreSelection(selectionInformation); 10930 setEnabled(eventsEnabled); 10931 eventsEnabled = null; 10932 selectionInformation = null; 10933 } 10934 function createInstance(type, props, rootContainerInstance, hostContext, internalInstanceHandle) { 10935 var parentNamespace; 10936 10937 { 10938 // TODO: take namespace into account when validating. 10939 var hostContextDev = hostContext; 10940 validateDOMNesting(type, null, hostContextDev.ancestorInfo); 10941 10942 if (typeof props.children === 'string' || typeof props.children === 'number') { 10943 var string = '' + props.children; 10944 var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type); 10945 validateDOMNesting(null, string, ownAncestorInfo); 10946 } 10947 10948 parentNamespace = hostContextDev.namespace; 10949 } 10950 10951 var domElement = createElement(type, props, rootContainerInstance, parentNamespace); 10952 precacheFiberNode(internalInstanceHandle, domElement); 10953 updateFiberProps(domElement, props); 10954 return domElement; 10955 } 10956 function appendInitialChild(parentInstance, child) { 10957 parentInstance.appendChild(child); 10958 } 10959 function finalizeInitialChildren(domElement, type, props, rootContainerInstance, hostContext) { 10960 setInitialProperties(domElement, type, props, rootContainerInstance); 10961 10962 switch (type) { 10963 case 'button': 10964 case 'input': 10965 case 'select': 10966 case 'textarea': 10967 return !!props.autoFocus; 10968 10969 case 'img': 10970 return true; 10971 10972 default: 10973 return false; 10974 } 10975 } 10976 function prepareUpdate(domElement, type, oldProps, newProps, rootContainerInstance, hostContext) { 10977 { 10978 var hostContextDev = hostContext; 10979 10980 if (typeof newProps.children !== typeof oldProps.children && (typeof newProps.children === 'string' || typeof newProps.children === 'number')) { 10981 var string = '' + newProps.children; 10982 var ownAncestorInfo = updatedAncestorInfo(hostContextDev.ancestorInfo, type); 10983 validateDOMNesting(null, string, ownAncestorInfo); 10984 } 10985 } 10986 10987 return diffProperties(domElement, type, oldProps, newProps); 10988 } 10989 function shouldSetTextContent(type, props) { 10990 return type === 'textarea' || type === 'noscript' || typeof props.children === 'string' || typeof props.children === 'number' || typeof props.dangerouslySetInnerHTML === 'object' && props.dangerouslySetInnerHTML !== null && props.dangerouslySetInnerHTML.__html != null; 10991 } 10992 function createTextInstance(text, rootContainerInstance, hostContext, internalInstanceHandle) { 10993 { 10994 var hostContextDev = hostContext; 10995 validateDOMNesting(null, text, hostContextDev.ancestorInfo); 10996 } 10997 10998 var textNode = createTextNode(text, rootContainerInstance); 10999 precacheFiberNode(internalInstanceHandle, textNode); 11000 return textNode; 11001 } 11002 function getCurrentEventPriority() { 11003 var currentEvent = window.event; 11004 11005 if (currentEvent === undefined) { 11006 return DefaultEventPriority; 11007 } 11008 11009 return getEventPriority(currentEvent.type); 11010 } 11011 // if a component just imports ReactDOM (e.g. for findDOMNode). 11012 // Some environments might not have setTimeout or clearTimeout. 11013 11014 var scheduleTimeout = typeof setTimeout === 'function' ? setTimeout : undefined; 11015 var cancelTimeout = typeof clearTimeout === 'function' ? clearTimeout : undefined; 11016 var noTimeout = -1; 11017 var localPromise = typeof Promise === 'function' ? Promise : undefined; // ------------------- 11018 var scheduleMicrotask = typeof queueMicrotask === 'function' ? queueMicrotask : typeof localPromise !== 'undefined' ? function (callback) { 11019 return localPromise.resolve(null).then(callback).catch(handleErrorInNextTick); 11020 } : scheduleTimeout; // TODO: Determine the best fallback here. 11021 11022 function handleErrorInNextTick(error) { 11023 setTimeout(function () { 11024 throw error; 11025 }); 11026 } // ------------------- 11027 function commitMount(domElement, type, newProps, internalInstanceHandle) { 11028 // Despite the naming that might imply otherwise, this method only 11029 // fires if there is an `Update` effect scheduled during mounting. 11030 // This happens if `finalizeInitialChildren` returns `true` (which it 11031 // does to implement the `autoFocus` attribute on the client). But 11032 // there are also other cases when this might happen (such as patching 11033 // up text content during hydration mismatch). So we'll check this again. 11034 switch (type) { 11035 case 'button': 11036 case 'input': 11037 case 'select': 11038 case 'textarea': 11039 if (newProps.autoFocus) { 11040 domElement.focus(); 11041 } 11042 11043 return; 11044 11045 case 'img': 11046 { 11047 if (newProps.src) { 11048 domElement.src = newProps.src; 11049 } 11050 11051 return; 11052 } 11053 } 11054 } 11055 function commitUpdate(domElement, updatePayload, type, oldProps, newProps, internalInstanceHandle) { 11056 // Apply the diff to the DOM node. 11057 updateProperties(domElement, updatePayload, type, oldProps, newProps); // Update the props handle so that we know which props are the ones with 11058 // with current event handlers. 11059 11060 updateFiberProps(domElement, newProps); 11061 } 11062 function resetTextContent(domElement) { 11063 setTextContent(domElement, ''); 11064 } 11065 function commitTextUpdate(textInstance, oldText, newText) { 11066 textInstance.nodeValue = newText; 11067 } 11068 function appendChild(parentInstance, child) { 11069 parentInstance.appendChild(child); 11070 } 11071 function appendChildToContainer(container, child) { 11072 var parentNode; 11073 11074 if (container.nodeType === COMMENT_NODE) { 11075 parentNode = container.parentNode; 11076 parentNode.insertBefore(child, container); 11077 } else { 11078 parentNode = container; 11079 parentNode.appendChild(child); 11080 } // This container might be used for a portal. 11081 // If something inside a portal is clicked, that click should bubble 11082 // through the React tree. However, on Mobile Safari the click would 11083 // never bubble through the *DOM* tree unless an ancestor with onclick 11084 // event exists. So we wouldn't see it and dispatch it. 11085 // This is why we ensure that non React root containers have inline onclick 11086 // defined. 11087 // https://github.com/facebook/react/issues/11918 11088 11089 11090 var reactRootContainer = container._reactRootContainer; 11091 11092 if ((reactRootContainer === null || reactRootContainer === undefined) && parentNode.onclick === null) { 11093 // TODO: This cast may not be sound for SVG, MathML or custom elements. 11094 trapClickOnNonInteractiveElement(parentNode); 11095 } 11096 } 11097 function insertBefore(parentInstance, child, beforeChild) { 11098 parentInstance.insertBefore(child, beforeChild); 11099 } 11100 function insertInContainerBefore(container, child, beforeChild) { 11101 if (container.nodeType === COMMENT_NODE) { 11102 container.parentNode.insertBefore(child, beforeChild); 11103 } else { 11104 container.insertBefore(child, beforeChild); 11105 } 11106 } 11107 11108 function removeChild(parentInstance, child) { 11109 parentInstance.removeChild(child); 11110 } 11111 function removeChildFromContainer(container, child) { 11112 if (container.nodeType === COMMENT_NODE) { 11113 container.parentNode.removeChild(child); 11114 } else { 11115 container.removeChild(child); 11116 } 11117 } 11118 function clearSuspenseBoundary(parentInstance, suspenseInstance) { 11119 var node = suspenseInstance; // Delete all nodes within this suspense boundary. 11120 // There might be nested nodes so we need to keep track of how 11121 // deep we are and only break out when we're back on top. 11122 11123 var depth = 0; 11124 11125 do { 11126 var nextNode = node.nextSibling; 11127 parentInstance.removeChild(node); 11128 11129 if (nextNode && nextNode.nodeType === COMMENT_NODE) { 11130 var data = nextNode.data; 11131 11132 if (data === SUSPENSE_END_DATA) { 11133 if (depth === 0) { 11134 parentInstance.removeChild(nextNode); // Retry if any event replaying was blocked on this. 11135 11136 retryIfBlockedOn(suspenseInstance); 11137 return; 11138 } else { 11139 depth--; 11140 } 11141 } else if (data === SUSPENSE_START_DATA || data === SUSPENSE_PENDING_START_DATA || data === SUSPENSE_FALLBACK_START_DATA) { 11142 depth++; 11143 } 11144 } 11145 11146 node = nextNode; 11147 } while (node); // TODO: Warn, we didn't find the end comment boundary. 11148 // Retry if any event replaying was blocked on this. 11149 11150 11151 retryIfBlockedOn(suspenseInstance); 11152 } 11153 function clearSuspenseBoundaryFromContainer(container, suspenseInstance) { 11154 if (container.nodeType === COMMENT_NODE) { 11155 clearSuspenseBoundary(container.parentNode, suspenseInstance); 11156 } else if (container.nodeType === ELEMENT_NODE) { 11157 clearSuspenseBoundary(container, suspenseInstance); 11158 } // Retry if any event replaying was blocked on this. 11159 11160 11161 retryIfBlockedOn(container); 11162 } 11163 function hideInstance(instance) { 11164 // TODO: Does this work for all element types? What about MathML? Should we 11165 // pass host context to this method? 11166 instance = instance; 11167 var style = instance.style; 11168 11169 if (typeof style.setProperty === 'function') { 11170 style.setProperty('display', 'none', 'important'); 11171 } else { 11172 style.display = 'none'; 11173 } 11174 } 11175 function hideTextInstance(textInstance) { 11176 textInstance.nodeValue = ''; 11177 } 11178 function unhideInstance(instance, props) { 11179 instance = instance; 11180 var styleProp = props[STYLE$1]; 11181 var display = styleProp !== undefined && styleProp !== null && styleProp.hasOwnProperty('display') ? styleProp.display : null; 11182 instance.style.display = dangerousStyleValue('display', display); 11183 } 11184 function unhideTextInstance(textInstance, text) { 11185 textInstance.nodeValue = text; 11186 } 11187 function clearContainer(container) { 11188 if (container.nodeType === ELEMENT_NODE) { 11189 container.textContent = ''; 11190 } else if (container.nodeType === DOCUMENT_NODE) { 11191 if (container.documentElement) { 11192 container.removeChild(container.documentElement); 11193 } 11194 } 11195 } // ------------------- 11196 function canHydrateInstance(instance, type, props) { 11197 if (instance.nodeType !== ELEMENT_NODE || type.toLowerCase() !== instance.nodeName.toLowerCase()) { 11198 return null; 11199 } // This has now been refined to an element node. 11200 11201 11202 return instance; 11203 } 11204 function canHydrateTextInstance(instance, text) { 11205 if (text === '' || instance.nodeType !== TEXT_NODE) { 11206 // Empty strings are not parsed by HTML so there won't be a correct match here. 11207 return null; 11208 } // This has now been refined to a text node. 11209 11210 11211 return instance; 11212 } 11213 function canHydrateSuspenseInstance(instance) { 11214 if (instance.nodeType !== COMMENT_NODE) { 11215 // Empty strings are not parsed by HTML so there won't be a correct match here. 11216 return null; 11217 } // This has now been refined to a suspense node. 11218 11219 11220 return instance; 11221 } 11222 function isSuspenseInstancePending(instance) { 11223 return instance.data === SUSPENSE_PENDING_START_DATA; 11224 } 11225 function isSuspenseInstanceFallback(instance) { 11226 return instance.data === SUSPENSE_FALLBACK_START_DATA; 11227 } 11228 function getSuspenseInstanceFallbackErrorDetails(instance) { 11229 var dataset = instance.nextSibling && instance.nextSibling.dataset; 11230 var digest, message, stack; 11231 11232 if (dataset) { 11233 digest = dataset.dgst; 11234 11235 { 11236 message = dataset.msg; 11237 stack = dataset.stck; 11238 } 11239 } 11240 11241 { 11242 return { 11243 message: message, 11244 digest: digest, 11245 stack: stack 11246 }; 11247 } // let value = {message: undefined, hash: undefined}; 11248 // const nextSibling = instance.nextSibling; 11249 // if (nextSibling) { 11250 // const dataset = ((nextSibling: any): HTMLTemplateElement).dataset; 11251 // value.message = dataset.msg; 11252 // value.hash = dataset.hash; 11253 // if (true) { 11254 // value.stack = dataset.stack; 11255 // } 11256 // } 11257 // return value; 11258 11259 } 11260 function registerSuspenseInstanceRetry(instance, callback) { 11261 instance._reactRetry = callback; 11262 } 11263 11264 function getNextHydratable(node) { 11265 // Skip non-hydratable nodes. 11266 for (; node != null; node = node.nextSibling) { 11267 var nodeType = node.nodeType; 11268 11269 if (nodeType === ELEMENT_NODE || nodeType === TEXT_NODE) { 11270 break; 11271 } 11272 11273 if (nodeType === COMMENT_NODE) { 11274 var nodeData = node.data; 11275 11276 if (nodeData === SUSPENSE_START_DATA || nodeData === SUSPENSE_FALLBACK_START_DATA || nodeData === SUSPENSE_PENDING_START_DATA) { 11277 break; 11278 } 11279 11280 if (nodeData === SUSPENSE_END_DATA) { 11281 return null; 11282 } 11283 } 11284 } 11285 11286 return node; 11287 } 11288 11289 function getNextHydratableSibling(instance) { 11290 return getNextHydratable(instance.nextSibling); 11291 } 11292 function getFirstHydratableChild(parentInstance) { 11293 return getNextHydratable(parentInstance.firstChild); 11294 } 11295 function getFirstHydratableChildWithinContainer(parentContainer) { 11296 return getNextHydratable(parentContainer.firstChild); 11297 } 11298 function getFirstHydratableChildWithinSuspenseInstance(parentInstance) { 11299 return getNextHydratable(parentInstance.nextSibling); 11300 } 11301 function hydrateInstance(instance, type, props, rootContainerInstance, hostContext, internalInstanceHandle, shouldWarnDev) { 11302 precacheFiberNode(internalInstanceHandle, instance); // TODO: Possibly defer this until the commit phase where all the events 11303 // get attached. 11304 11305 updateFiberProps(instance, props); 11306 var parentNamespace; 11307 11308 { 11309 var hostContextDev = hostContext; 11310 parentNamespace = hostContextDev.namespace; 11311 } // TODO: Temporary hack to check if we're in a concurrent root. We can delete 11312 // when the legacy root API is removed. 11313 11314 11315 var isConcurrentMode = (internalInstanceHandle.mode & ConcurrentMode) !== NoMode; 11316 return diffHydratedProperties(instance, type, props, parentNamespace, rootContainerInstance, isConcurrentMode, shouldWarnDev); 11317 } 11318 function hydrateTextInstance(textInstance, text, internalInstanceHandle, shouldWarnDev) { 11319 precacheFiberNode(internalInstanceHandle, textInstance); // TODO: Temporary hack to check if we're in a concurrent root. We can delete 11320 // when the legacy root API is removed. 11321 11322 var isConcurrentMode = (internalInstanceHandle.mode & ConcurrentMode) !== NoMode; 11323 return diffHydratedText(textInstance, text); 11324 } 11325 function hydrateSuspenseInstance(suspenseInstance, internalInstanceHandle) { 11326 precacheFiberNode(internalInstanceHandle, suspenseInstance); 11327 } 11328 function getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance) { 11329 var node = suspenseInstance.nextSibling; // Skip past all nodes within this suspense boundary. 11330 // There might be nested nodes so we need to keep track of how 11331 // deep we are and only break out when we're back on top. 11332 11333 var depth = 0; 11334 11335 while (node) { 11336 if (node.nodeType === COMMENT_NODE) { 11337 var data = node.data; 11338 11339 if (data === SUSPENSE_END_DATA) { 11340 if (depth === 0) { 11341 return getNextHydratableSibling(node); 11342 } else { 11343 depth--; 11344 } 11345 } else if (data === SUSPENSE_START_DATA || data === SUSPENSE_FALLBACK_START_DATA || data === SUSPENSE_PENDING_START_DATA) { 11346 depth++; 11347 } 11348 } 11349 11350 node = node.nextSibling; 11351 } // TODO: Warn, we didn't find the end comment boundary. 11352 11353 11354 return null; 11355 } // Returns the SuspenseInstance if this node is a direct child of a 11356 // SuspenseInstance. I.e. if its previous sibling is a Comment with 11357 // SUSPENSE_x_START_DATA. Otherwise, null. 11358 11359 function getParentSuspenseInstance(targetInstance) { 11360 var node = targetInstance.previousSibling; // Skip past all nodes within this suspense boundary. 11361 // There might be nested nodes so we need to keep track of how 11362 // deep we are and only break out when we're back on top. 11363 11364 var depth = 0; 11365 11366 while (node) { 11367 if (node.nodeType === COMMENT_NODE) { 11368 var data = node.data; 11369 11370 if (data === SUSPENSE_START_DATA || data === SUSPENSE_FALLBACK_START_DATA || data === SUSPENSE_PENDING_START_DATA) { 11371 if (depth === 0) { 11372 return node; 11373 } else { 11374 depth--; 11375 } 11376 } else if (data === SUSPENSE_END_DATA) { 11377 depth++; 11378 } 11379 } 11380 11381 node = node.previousSibling; 11382 } 11383 11384 return null; 11385 } 11386 function commitHydratedContainer(container) { 11387 // Retry if any event replaying was blocked on this. 11388 retryIfBlockedOn(container); 11389 } 11390 function commitHydratedSuspenseInstance(suspenseInstance) { 11391 // Retry if any event replaying was blocked on this. 11392 retryIfBlockedOn(suspenseInstance); 11393 } 11394 function shouldDeleteUnhydratedTailInstances(parentType) { 11395 return parentType !== 'head' && parentType !== 'body'; 11396 } 11397 function didNotMatchHydratedContainerTextInstance(parentContainer, textInstance, text, isConcurrentMode) { 11398 var shouldWarnDev = true; 11399 checkForUnmatchedText(textInstance.nodeValue, text, isConcurrentMode, shouldWarnDev); 11400 } 11401 function didNotMatchHydratedTextInstance(parentType, parentProps, parentInstance, textInstance, text, isConcurrentMode) { 11402 if (parentProps[SUPPRESS_HYDRATION_WARNING$1] !== true) { 11403 var shouldWarnDev = true; 11404 checkForUnmatchedText(textInstance.nodeValue, text, isConcurrentMode, shouldWarnDev); 11405 } 11406 } 11407 function didNotHydrateInstanceWithinContainer(parentContainer, instance) { 11408 { 11409 if (instance.nodeType === ELEMENT_NODE) { 11410 warnForDeletedHydratableElement(parentContainer, instance); 11411 } else if (instance.nodeType === COMMENT_NODE) ; else { 11412 warnForDeletedHydratableText(parentContainer, instance); 11413 } 11414 } 11415 } 11416 function didNotHydrateInstanceWithinSuspenseInstance(parentInstance, instance) { 11417 { 11418 // $FlowFixMe: Only Element or Document can be parent nodes. 11419 var parentNode = parentInstance.parentNode; 11420 11421 if (parentNode !== null) { 11422 if (instance.nodeType === ELEMENT_NODE) { 11423 warnForDeletedHydratableElement(parentNode, instance); 11424 } else if (instance.nodeType === COMMENT_NODE) ; else { 11425 warnForDeletedHydratableText(parentNode, instance); 11426 } 11427 } 11428 } 11429 } 11430 function didNotHydrateInstance(parentType, parentProps, parentInstance, instance, isConcurrentMode) { 11431 { 11432 if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING$1] !== true) { 11433 if (instance.nodeType === ELEMENT_NODE) { 11434 warnForDeletedHydratableElement(parentInstance, instance); 11435 } else if (instance.nodeType === COMMENT_NODE) ; else { 11436 warnForDeletedHydratableText(parentInstance, instance); 11437 } 11438 } 11439 } 11440 } 11441 function didNotFindHydratableInstanceWithinContainer(parentContainer, type, props) { 11442 { 11443 warnForInsertedHydratedElement(parentContainer, type); 11444 } 11445 } 11446 function didNotFindHydratableTextInstanceWithinContainer(parentContainer, text) { 11447 { 11448 warnForInsertedHydratedText(parentContainer, text); 11449 } 11450 } 11451 function didNotFindHydratableInstanceWithinSuspenseInstance(parentInstance, type, props) { 11452 { 11453 // $FlowFixMe: Only Element or Document can be parent nodes. 11454 var parentNode = parentInstance.parentNode; 11455 if (parentNode !== null) warnForInsertedHydratedElement(parentNode, type); 11456 } 11457 } 11458 function didNotFindHydratableTextInstanceWithinSuspenseInstance(parentInstance, text) { 11459 { 11460 // $FlowFixMe: Only Element or Document can be parent nodes. 11461 var parentNode = parentInstance.parentNode; 11462 if (parentNode !== null) warnForInsertedHydratedText(parentNode, text); 11463 } 11464 } 11465 function didNotFindHydratableInstance(parentType, parentProps, parentInstance, type, props, isConcurrentMode) { 11466 { 11467 if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING$1] !== true) { 11468 warnForInsertedHydratedElement(parentInstance, type); 11469 } 11470 } 11471 } 11472 function didNotFindHydratableTextInstance(parentType, parentProps, parentInstance, text, isConcurrentMode) { 11473 { 11474 if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING$1] !== true) { 11475 warnForInsertedHydratedText(parentInstance, text); 11476 } 11477 } 11478 } 11479 function errorHydratingContainer(parentContainer) { 11480 { 11481 // TODO: This gets logged by onRecoverableError, too, so we should be 11482 // able to remove it. 11483 error('An error occurred during hydration. The server HTML was replaced with client content in <%s>.', parentContainer.nodeName.toLowerCase()); 11484 } 11485 } 11486 function preparePortalMount(portalInstance) { 11487 listenToAllSupportedEvents(portalInstance); 11488 } 11489 11490 var randomKey = Math.random().toString(36).slice(2); 11491 var internalInstanceKey = '__reactFiber$' + randomKey; 11492 var internalPropsKey = '__reactProps$' + randomKey; 11493 var internalContainerInstanceKey = '__reactContainer$' + randomKey; 11494 var internalEventHandlersKey = '__reactEvents$' + randomKey; 11495 var internalEventHandlerListenersKey = '__reactListeners$' + randomKey; 11496 var internalEventHandlesSetKey = '__reactHandles$' + randomKey; 11497 function detachDeletedInstance(node) { 11498 // TODO: This function is only called on host components. I don't think all of 11499 // these fields are relevant. 11500 delete node[internalInstanceKey]; 11501 delete node[internalPropsKey]; 11502 delete node[internalEventHandlersKey]; 11503 delete node[internalEventHandlerListenersKey]; 11504 delete node[internalEventHandlesSetKey]; 11505 } 11506 function precacheFiberNode(hostInst, node) { 11507 node[internalInstanceKey] = hostInst; 11508 } 11509 function markContainerAsRoot(hostRoot, node) { 11510 node[internalContainerInstanceKey] = hostRoot; 11511 } 11512 function unmarkContainerAsRoot(node) { 11513 node[internalContainerInstanceKey] = null; 11514 } 11515 function isContainerMarkedAsRoot(node) { 11516 return !!node[internalContainerInstanceKey]; 11517 } // Given a DOM node, return the closest HostComponent or HostText fiber ancestor. 11518 // If the target node is part of a hydrated or not yet rendered subtree, then 11519 // this may also return a SuspenseComponent or HostRoot to indicate that. 11520 // Conceptually the HostRoot fiber is a child of the Container node. So if you 11521 // pass the Container node as the targetNode, you will not actually get the 11522 // HostRoot back. To get to the HostRoot, you need to pass a child of it. 11523 // The same thing applies to Suspense boundaries. 11524 11525 function getClosestInstanceFromNode(targetNode) { 11526 var targetInst = targetNode[internalInstanceKey]; 11527 11528 if (targetInst) { 11529 // Don't return HostRoot or SuspenseComponent here. 11530 return targetInst; 11531 } // If the direct event target isn't a React owned DOM node, we need to look 11532 // to see if one of its parents is a React owned DOM node. 11533 11534 11535 var parentNode = targetNode.parentNode; 11536 11537 while (parentNode) { 11538 // We'll check if this is a container root that could include 11539 // React nodes in the future. We need to check this first because 11540 // if we're a child of a dehydrated container, we need to first 11541 // find that inner container before moving on to finding the parent 11542 // instance. Note that we don't check this field on the targetNode 11543 // itself because the fibers are conceptually between the container 11544 // node and the first child. It isn't surrounding the container node. 11545 // If it's not a container, we check if it's an instance. 11546 targetInst = parentNode[internalContainerInstanceKey] || parentNode[internalInstanceKey]; 11547 11548 if (targetInst) { 11549 // Since this wasn't the direct target of the event, we might have 11550 // stepped past dehydrated DOM nodes to get here. However they could 11551 // also have been non-React nodes. We need to answer which one. 11552 // If we the instance doesn't have any children, then there can't be 11553 // a nested suspense boundary within it. So we can use this as a fast 11554 // bailout. Most of the time, when people add non-React children to 11555 // the tree, it is using a ref to a child-less DOM node. 11556 // Normally we'd only need to check one of the fibers because if it 11557 // has ever gone from having children to deleting them or vice versa 11558 // it would have deleted the dehydrated boundary nested inside already. 11559 // However, since the HostRoot starts out with an alternate it might 11560 // have one on the alternate so we need to check in case this was a 11561 // root. 11562 var alternate = targetInst.alternate; 11563 11564 if (targetInst.child !== null || alternate !== null && alternate.child !== null) { 11565 // Next we need to figure out if the node that skipped past is 11566 // nested within a dehydrated boundary and if so, which one. 11567 var suspenseInstance = getParentSuspenseInstance(targetNode); 11568 11569 while (suspenseInstance !== null) { 11570 // We found a suspense instance. That means that we haven't 11571 // hydrated it yet. Even though we leave the comments in the 11572 // DOM after hydrating, and there are boundaries in the DOM 11573 // that could already be hydrated, we wouldn't have found them 11574 // through this pass since if the target is hydrated it would 11575 // have had an internalInstanceKey on it. 11576 // Let's get the fiber associated with the SuspenseComponent 11577 // as the deepest instance. 11578 var targetSuspenseInst = suspenseInstance[internalInstanceKey]; 11579 11580 if (targetSuspenseInst) { 11581 return targetSuspenseInst; 11582 } // If we don't find a Fiber on the comment, it might be because 11583 // we haven't gotten to hydrate it yet. There might still be a 11584 // parent boundary that hasn't above this one so we need to find 11585 // the outer most that is known. 11586 11587 11588 suspenseInstance = getParentSuspenseInstance(suspenseInstance); // If we don't find one, then that should mean that the parent 11589 // host component also hasn't hydrated yet. We can return it 11590 // below since it will bail out on the isMounted check later. 11591 } 11592 } 11593 11594 return targetInst; 11595 } 11596 11597 targetNode = parentNode; 11598 parentNode = targetNode.parentNode; 11599 } 11600 11601 return null; 11602 } 11603 /** 11604 * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent 11605 * instance, or null if the node was not rendered by this React. 11606 */ 11607 11608 function getInstanceFromNode(node) { 11609 var inst = node[internalInstanceKey] || node[internalContainerInstanceKey]; 11610 11611 if (inst) { 11612 if (inst.tag === HostComponent || inst.tag === HostText || inst.tag === SuspenseComponent || inst.tag === HostRoot) { 11613 return inst; 11614 } else { 11615 return null; 11616 } 11617 } 11618 11619 return null; 11620 } 11621 /** 11622 * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding 11623 * DOM node. 11624 */ 11625 11626 function getNodeFromInstance(inst) { 11627 if (inst.tag === HostComponent || inst.tag === HostText) { 11628 // In Fiber this, is just the state node right now. We assume it will be 11629 // a host component or host text. 11630 return inst.stateNode; 11631 } // Without this first invariant, passing a non-DOM-component triggers the next 11632 // invariant for a missing parent, which is super confusing. 11633 11634 11635 throw new Error('getNodeFromInstance: Invalid argument.'); 11636 } 11637 function getFiberCurrentPropsFromNode(node) { 11638 return node[internalPropsKey] || null; 11639 } 11640 function updateFiberProps(node, props) { 11641 node[internalPropsKey] = props; 11642 } 11643 function getEventListenerSet(node) { 11644 var elementListenerSet = node[internalEventHandlersKey]; 11645 11646 if (elementListenerSet === undefined) { 11647 elementListenerSet = node[internalEventHandlersKey] = new Set(); 11648 } 11649 11650 return elementListenerSet; 11651 } 11652 11653 var loggedTypeFailures = {}; 11654 var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; 11655 11656 function setCurrentlyValidatingElement(element) { 11657 { 11658 if (element) { 11659 var owner = element._owner; 11660 var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null); 11661 ReactDebugCurrentFrame$1.setExtraStackFrame(stack); 11662 } else { 11663 ReactDebugCurrentFrame$1.setExtraStackFrame(null); 11664 } 11665 } 11666 } 11667 11668 function checkPropTypes(typeSpecs, values, location, componentName, element) { 11669 { 11670 // $FlowFixMe This is okay but Flow doesn't know it. 11671 var has = Function.call.bind(hasOwnProperty); 11672 11673 for (var typeSpecName in typeSpecs) { 11674 if (has(typeSpecs, typeSpecName)) { 11675 var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to 11676 // fail the render phase where it didn't fail before. So we log it. 11677 // After these have been cleaned up, we'll let them throw. 11678 11679 try { 11680 // This is intentionally an invariant that gets caught. It's the same 11681 // behavior as without this statement except with a better message. 11682 if (typeof typeSpecs[typeSpecName] !== 'function') { 11683 // eslint-disable-next-line react-internal/prod-error-codes 11684 var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.'); 11685 err.name = 'Invariant Violation'; 11686 throw err; 11687 } 11688 11689 error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'); 11690 } catch (ex) { 11691 error$1 = ex; 11692 } 11693 11694 if (error$1 && !(error$1 instanceof Error)) { 11695 setCurrentlyValidatingElement(element); 11696 11697 error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1); 11698 11699 setCurrentlyValidatingElement(null); 11700 } 11701 11702 if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) { 11703 // Only monitor this failure once because there tends to be a lot of the 11704 // same error. 11705 loggedTypeFailures[error$1.message] = true; 11706 setCurrentlyValidatingElement(element); 11707 11708 error('Failed %s type: %s', location, error$1.message); 11709 11710 setCurrentlyValidatingElement(null); 11711 } 11712 } 11713 } 11714 } 11715 } 11716 11717 var valueStack = []; 11718 var fiberStack; 11719 11720 { 11721 fiberStack = []; 11722 } 11723 11724 var index = -1; 11725 11726 function createCursor(defaultValue) { 11727 return { 11728 current: defaultValue 11729 }; 11730 } 11731 11732 function pop(cursor, fiber) { 11733 if (index < 0) { 11734 { 11735 error('Unexpected pop.'); 11736 } 11737 11738 return; 11739 } 11740 11741 { 11742 if (fiber !== fiberStack[index]) { 11743 error('Unexpected Fiber popped.'); 11744 } 11745 } 11746 11747 cursor.current = valueStack[index]; 11748 valueStack[index] = null; 11749 11750 { 11751 fiberStack[index] = null; 11752 } 11753 11754 index--; 11755 } 11756 11757 function push(cursor, value, fiber) { 11758 index++; 11759 valueStack[index] = cursor.current; 11760 11761 { 11762 fiberStack[index] = fiber; 11763 } 11764 11765 cursor.current = value; 11766 } 11767 11768 var warnedAboutMissingGetChildContext; 11769 11770 { 11771 warnedAboutMissingGetChildContext = {}; 11772 } 11773 11774 var emptyContextObject = {}; 11775 11776 { 11777 Object.freeze(emptyContextObject); 11778 } // A cursor to the current merged context object on the stack. 11779 11780 11781 var contextStackCursor = createCursor(emptyContextObject); // A cursor to a boolean indicating whether the context has changed. 11782 11783 var didPerformWorkStackCursor = createCursor(false); // Keep track of the previous context object that was on the stack. 11784 // We use this to get access to the parent context after we have already 11785 // pushed the next context provider, and now need to merge their contexts. 11786 11787 var previousContext = emptyContextObject; 11788 11789 function getUnmaskedContext(workInProgress, Component, didPushOwnContextIfProvider) { 11790 { 11791 if (didPushOwnContextIfProvider && isContextProvider(Component)) { 11792 // If the fiber is a context provider itself, when we read its context 11793 // we may have already pushed its own child context on the stack. A context 11794 // provider should not "see" its own child context. Therefore we read the 11795 // previous (parent) context instead for a context provider. 11796 return previousContext; 11797 } 11798 11799 return contextStackCursor.current; 11800 } 11801 } 11802 11803 function cacheContext(workInProgress, unmaskedContext, maskedContext) { 11804 { 11805 var instance = workInProgress.stateNode; 11806 instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext; 11807 instance.__reactInternalMemoizedMaskedChildContext = maskedContext; 11808 } 11809 } 11810 11811 function getMaskedContext(workInProgress, unmaskedContext) { 11812 { 11813 var type = workInProgress.type; 11814 var contextTypes = type.contextTypes; 11815 11816 if (!contextTypes) { 11817 return emptyContextObject; 11818 } // Avoid recreating masked context unless unmasked context has changed. 11819 // Failing to do this will result in unnecessary calls to componentWillReceiveProps. 11820 // This may trigger infinite loops if componentWillReceiveProps calls setState. 11821 11822 11823 var instance = workInProgress.stateNode; 11824 11825 if (instance && instance.__reactInternalMemoizedUnmaskedChildContext === unmaskedContext) { 11826 return instance.__reactInternalMemoizedMaskedChildContext; 11827 } 11828 11829 var context = {}; 11830 11831 for (var key in contextTypes) { 11832 context[key] = unmaskedContext[key]; 11833 } 11834 11835 { 11836 var name = getComponentNameFromFiber(workInProgress) || 'Unknown'; 11837 checkPropTypes(contextTypes, context, 'context', name); 11838 } // Cache unmasked context so we can avoid recreating masked context unless necessary. 11839 // Context is created before the class component is instantiated so check for instance. 11840 11841 11842 if (instance) { 11843 cacheContext(workInProgress, unmaskedContext, context); 11844 } 11845 11846 return context; 11847 } 11848 } 11849 11850 function hasContextChanged() { 11851 { 11852 return didPerformWorkStackCursor.current; 11853 } 11854 } 11855 11856 function isContextProvider(type) { 11857 { 11858 var childContextTypes = type.childContextTypes; 11859 return childContextTypes !== null && childContextTypes !== undefined; 11860 } 11861 } 11862 11863 function popContext(fiber) { 11864 { 11865 pop(didPerformWorkStackCursor, fiber); 11866 pop(contextStackCursor, fiber); 11867 } 11868 } 11869 11870 function popTopLevelContextObject(fiber) { 11871 { 11872 pop(didPerformWorkStackCursor, fiber); 11873 pop(contextStackCursor, fiber); 11874 } 11875 } 11876 11877 function pushTopLevelContextObject(fiber, context, didChange) { 11878 { 11879 if (contextStackCursor.current !== emptyContextObject) { 11880 throw new Error('Unexpected context found on stack. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 11881 } 11882 11883 push(contextStackCursor, context, fiber); 11884 push(didPerformWorkStackCursor, didChange, fiber); 11885 } 11886 } 11887 11888 function processChildContext(fiber, type, parentContext) { 11889 { 11890 var instance = fiber.stateNode; 11891 var childContextTypes = type.childContextTypes; // TODO (bvaughn) Replace this behavior with an invariant() in the future. 11892 // It has only been added in Fiber to match the (unintentional) behavior in Stack. 11893 11894 if (typeof instance.getChildContext !== 'function') { 11895 { 11896 var componentName = getComponentNameFromFiber(fiber) || 'Unknown'; 11897 11898 if (!warnedAboutMissingGetChildContext[componentName]) { 11899 warnedAboutMissingGetChildContext[componentName] = true; 11900 11901 error('%s.childContextTypes is specified but there is no getChildContext() method ' + 'on the instance. You can either define getChildContext() on %s or remove ' + 'childContextTypes from it.', componentName, componentName); 11902 } 11903 } 11904 11905 return parentContext; 11906 } 11907 11908 var childContext = instance.getChildContext(); 11909 11910 for (var contextKey in childContext) { 11911 if (!(contextKey in childContextTypes)) { 11912 throw new Error((getComponentNameFromFiber(fiber) || 'Unknown') + ".getChildContext(): key \"" + contextKey + "\" is not defined in childContextTypes."); 11913 } 11914 } 11915 11916 { 11917 var name = getComponentNameFromFiber(fiber) || 'Unknown'; 11918 checkPropTypes(childContextTypes, childContext, 'child context', name); 11919 } 11920 11921 return assign({}, parentContext, childContext); 11922 } 11923 } 11924 11925 function pushContextProvider(workInProgress) { 11926 { 11927 var instance = workInProgress.stateNode; // We push the context as early as possible to ensure stack integrity. 11928 // If the instance does not exist yet, we will push null at first, 11929 // and replace it on the stack later when invalidating the context. 11930 11931 var memoizedMergedChildContext = instance && instance.__reactInternalMemoizedMergedChildContext || emptyContextObject; // Remember the parent context so we can merge with it later. 11932 // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. 11933 11934 previousContext = contextStackCursor.current; 11935 push(contextStackCursor, memoizedMergedChildContext, workInProgress); 11936 push(didPerformWorkStackCursor, didPerformWorkStackCursor.current, workInProgress); 11937 return true; 11938 } 11939 } 11940 11941 function invalidateContextProvider(workInProgress, type, didChange) { 11942 { 11943 var instance = workInProgress.stateNode; 11944 11945 if (!instance) { 11946 throw new Error('Expected to have an instance by this point. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 11947 } 11948 11949 if (didChange) { 11950 // Merge parent and own context. 11951 // Skip this if we're not updating due to sCU. 11952 // This avoids unnecessarily recomputing memoized values. 11953 var mergedContext = processChildContext(workInProgress, type, previousContext); 11954 instance.__reactInternalMemoizedMergedChildContext = mergedContext; // Replace the old (or empty) context with the new one. 11955 // It is important to unwind the context in the reverse order. 11956 11957 pop(didPerformWorkStackCursor, workInProgress); 11958 pop(contextStackCursor, workInProgress); // Now push the new context and mark that it has changed. 11959 11960 push(contextStackCursor, mergedContext, workInProgress); 11961 push(didPerformWorkStackCursor, didChange, workInProgress); 11962 } else { 11963 pop(didPerformWorkStackCursor, workInProgress); 11964 push(didPerformWorkStackCursor, didChange, workInProgress); 11965 } 11966 } 11967 } 11968 11969 function findCurrentUnmaskedContext(fiber) { 11970 { 11971 // Currently this is only used with renderSubtreeIntoContainer; not sure if it 11972 // makes sense elsewhere 11973 if (!isFiberMounted(fiber) || fiber.tag !== ClassComponent) { 11974 throw new Error('Expected subtree parent to be a mounted class component. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 11975 } 11976 11977 var node = fiber; 11978 11979 do { 11980 switch (node.tag) { 11981 case HostRoot: 11982 return node.stateNode.context; 11983 11984 case ClassComponent: 11985 { 11986 var Component = node.type; 11987 11988 if (isContextProvider(Component)) { 11989 return node.stateNode.__reactInternalMemoizedMergedChildContext; 11990 } 11991 11992 break; 11993 } 11994 } 11995 11996 node = node.return; 11997 } while (node !== null); 11998 11999 throw new Error('Found unexpected detached subtree parent. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 12000 } 12001 } 12002 12003 var LegacyRoot = 0; 12004 var ConcurrentRoot = 1; 12005 12006 var syncQueue = null; 12007 var includesLegacySyncCallbacks = false; 12008 var isFlushingSyncQueue = false; 12009 function scheduleSyncCallback(callback) { 12010 // Push this callback into an internal queue. We'll flush these either in 12011 // the next tick, or earlier if something calls `flushSyncCallbackQueue`. 12012 if (syncQueue === null) { 12013 syncQueue = [callback]; 12014 } else { 12015 // Push onto existing queue. Don't need to schedule a callback because 12016 // we already scheduled one when we created the queue. 12017 syncQueue.push(callback); 12018 } 12019 } 12020 function scheduleLegacySyncCallback(callback) { 12021 includesLegacySyncCallbacks = true; 12022 scheduleSyncCallback(callback); 12023 } 12024 function flushSyncCallbacksOnlyInLegacyMode() { 12025 // Only flushes the queue if there's a legacy sync callback scheduled. 12026 // TODO: There's only a single type of callback: performSyncOnWorkOnRoot. So 12027 // it might make more sense for the queue to be a list of roots instead of a 12028 // list of generic callbacks. Then we can have two: one for legacy roots, one 12029 // for concurrent roots. And this method would only flush the legacy ones. 12030 if (includesLegacySyncCallbacks) { 12031 flushSyncCallbacks(); 12032 } 12033 } 12034 function flushSyncCallbacks() { 12035 if (!isFlushingSyncQueue && syncQueue !== null) { 12036 // Prevent re-entrance. 12037 isFlushingSyncQueue = true; 12038 var i = 0; 12039 var previousUpdatePriority = getCurrentUpdatePriority(); 12040 12041 try { 12042 var isSync = true; 12043 var queue = syncQueue; // TODO: Is this necessary anymore? The only user code that runs in this 12044 // queue is in the render or commit phases. 12045 12046 setCurrentUpdatePriority(DiscreteEventPriority); 12047 12048 for (; i < queue.length; i++) { 12049 var callback = queue[i]; 12050 12051 do { 12052 callback = callback(isSync); 12053 } while (callback !== null); 12054 } 12055 12056 syncQueue = null; 12057 includesLegacySyncCallbacks = false; 12058 } catch (error) { 12059 // If something throws, leave the remaining callbacks on the queue. 12060 if (syncQueue !== null) { 12061 syncQueue = syncQueue.slice(i + 1); 12062 } // Resume flushing in the next tick 12063 12064 12065 scheduleCallback(ImmediatePriority, flushSyncCallbacks); 12066 throw error; 12067 } finally { 12068 setCurrentUpdatePriority(previousUpdatePriority); 12069 isFlushingSyncQueue = false; 12070 } 12071 } 12072 12073 return null; 12074 } 12075 12076 // TODO: Use the unified fiber stack module instead of this local one? 12077 // Intentionally not using it yet to derisk the initial implementation, because 12078 // the way we push/pop these values is a bit unusual. If there's a mistake, I'd 12079 // rather the ids be wrong than crash the whole reconciler. 12080 var forkStack = []; 12081 var forkStackIndex = 0; 12082 var treeForkProvider = null; 12083 var treeForkCount = 0; 12084 var idStack = []; 12085 var idStackIndex = 0; 12086 var treeContextProvider = null; 12087 var treeContextId = 1; 12088 var treeContextOverflow = ''; 12089 function isForkedChild(workInProgress) { 12090 warnIfNotHydrating(); 12091 return (workInProgress.flags & Forked) !== NoFlags; 12092 } 12093 function getForksAtLevel(workInProgress) { 12094 warnIfNotHydrating(); 12095 return treeForkCount; 12096 } 12097 function getTreeId() { 12098 var overflow = treeContextOverflow; 12099 var idWithLeadingBit = treeContextId; 12100 var id = idWithLeadingBit & ~getLeadingBit(idWithLeadingBit); 12101 return id.toString(32) + overflow; 12102 } 12103 function pushTreeFork(workInProgress, totalChildren) { 12104 // This is called right after we reconcile an array (or iterator) of child 12105 // fibers, because that's the only place where we know how many children in 12106 // the whole set without doing extra work later, or storing addtional 12107 // information on the fiber. 12108 // 12109 // That's why this function is separate from pushTreeId — it's called during 12110 // the render phase of the fork parent, not the child, which is where we push 12111 // the other context values. 12112 // 12113 // In the Fizz implementation this is much simpler because the child is 12114 // rendered in the same callstack as the parent. 12115 // 12116 // It might be better to just add a `forks` field to the Fiber type. It would 12117 // make this module simpler. 12118 warnIfNotHydrating(); 12119 forkStack[forkStackIndex++] = treeForkCount; 12120 forkStack[forkStackIndex++] = treeForkProvider; 12121 treeForkProvider = workInProgress; 12122 treeForkCount = totalChildren; 12123 } 12124 function pushTreeId(workInProgress, totalChildren, index) { 12125 warnIfNotHydrating(); 12126 idStack[idStackIndex++] = treeContextId; 12127 idStack[idStackIndex++] = treeContextOverflow; 12128 idStack[idStackIndex++] = treeContextProvider; 12129 treeContextProvider = workInProgress; 12130 var baseIdWithLeadingBit = treeContextId; 12131 var baseOverflow = treeContextOverflow; // The leftmost 1 marks the end of the sequence, non-inclusive. It's not part 12132 // of the id; we use it to account for leading 0s. 12133 12134 var baseLength = getBitLength(baseIdWithLeadingBit) - 1; 12135 var baseId = baseIdWithLeadingBit & ~(1 << baseLength); 12136 var slot = index + 1; 12137 var length = getBitLength(totalChildren) + baseLength; // 30 is the max length we can store without overflowing, taking into 12138 // consideration the leading 1 we use to mark the end of the sequence. 12139 12140 if (length > 30) { 12141 // We overflowed the bitwise-safe range. Fall back to slower algorithm. 12142 // This branch assumes the length of the base id is greater than 5; it won't 12143 // work for smaller ids, because you need 5 bits per character. 12144 // 12145 // We encode the id in multiple steps: first the base id, then the 12146 // remaining digits. 12147 // 12148 // Each 5 bit sequence corresponds to a single base 32 character. So for 12149 // example, if the current id is 23 bits long, we can convert 20 of those 12150 // bits into a string of 4 characters, with 3 bits left over. 12151 // 12152 // First calculate how many bits in the base id represent a complete 12153 // sequence of characters. 12154 var numberOfOverflowBits = baseLength - baseLength % 5; // Then create a bitmask that selects only those bits. 12155 12156 var newOverflowBits = (1 << numberOfOverflowBits) - 1; // Select the bits, and convert them to a base 32 string. 12157 12158 var newOverflow = (baseId & newOverflowBits).toString(32); // Now we can remove those bits from the base id. 12159 12160 var restOfBaseId = baseId >> numberOfOverflowBits; 12161 var restOfBaseLength = baseLength - numberOfOverflowBits; // Finally, encode the rest of the bits using the normal algorithm. Because 12162 // we made more room, this time it won't overflow. 12163 12164 var restOfLength = getBitLength(totalChildren) + restOfBaseLength; 12165 var restOfNewBits = slot << restOfBaseLength; 12166 var id = restOfNewBits | restOfBaseId; 12167 var overflow = newOverflow + baseOverflow; 12168 treeContextId = 1 << restOfLength | id; 12169 treeContextOverflow = overflow; 12170 } else { 12171 // Normal path 12172 var newBits = slot << baseLength; 12173 12174 var _id = newBits | baseId; 12175 12176 var _overflow = baseOverflow; 12177 treeContextId = 1 << length | _id; 12178 treeContextOverflow = _overflow; 12179 } 12180 } 12181 function pushMaterializedTreeId(workInProgress) { 12182 warnIfNotHydrating(); // This component materialized an id. This will affect any ids that appear 12183 // in its children. 12184 12185 var returnFiber = workInProgress.return; 12186 12187 if (returnFiber !== null) { 12188 var numberOfForks = 1; 12189 var slotIndex = 0; 12190 pushTreeFork(workInProgress, numberOfForks); 12191 pushTreeId(workInProgress, numberOfForks, slotIndex); 12192 } 12193 } 12194 12195 function getBitLength(number) { 12196 return 32 - clz32(number); 12197 } 12198 12199 function getLeadingBit(id) { 12200 return 1 << getBitLength(id) - 1; 12201 } 12202 12203 function popTreeContext(workInProgress) { 12204 // Restore the previous values. 12205 // This is a bit more complicated than other context-like modules in Fiber 12206 // because the same Fiber may appear on the stack multiple times and for 12207 // different reasons. We have to keep popping until the work-in-progress is 12208 // no longer at the top of the stack. 12209 while (workInProgress === treeForkProvider) { 12210 treeForkProvider = forkStack[--forkStackIndex]; 12211 forkStack[forkStackIndex] = null; 12212 treeForkCount = forkStack[--forkStackIndex]; 12213 forkStack[forkStackIndex] = null; 12214 } 12215 12216 while (workInProgress === treeContextProvider) { 12217 treeContextProvider = idStack[--idStackIndex]; 12218 idStack[idStackIndex] = null; 12219 treeContextOverflow = idStack[--idStackIndex]; 12220 idStack[idStackIndex] = null; 12221 treeContextId = idStack[--idStackIndex]; 12222 idStack[idStackIndex] = null; 12223 } 12224 } 12225 function getSuspendedTreeContext() { 12226 warnIfNotHydrating(); 12227 12228 if (treeContextProvider !== null) { 12229 return { 12230 id: treeContextId, 12231 overflow: treeContextOverflow 12232 }; 12233 } else { 12234 return null; 12235 } 12236 } 12237 function restoreSuspendedTreeContext(workInProgress, suspendedContext) { 12238 warnIfNotHydrating(); 12239 idStack[idStackIndex++] = treeContextId; 12240 idStack[idStackIndex++] = treeContextOverflow; 12241 idStack[idStackIndex++] = treeContextProvider; 12242 treeContextId = suspendedContext.id; 12243 treeContextOverflow = suspendedContext.overflow; 12244 treeContextProvider = workInProgress; 12245 } 12246 12247 function warnIfNotHydrating() { 12248 { 12249 if (!getIsHydrating()) { 12250 error('Expected to be hydrating. This is a bug in React. Please file ' + 'an issue.'); 12251 } 12252 } 12253 } 12254 12255 // This may have been an insertion or a hydration. 12256 12257 var hydrationParentFiber = null; 12258 var nextHydratableInstance = null; 12259 var isHydrating = false; // This flag allows for warning supression when we expect there to be mismatches 12260 // due to earlier mismatches or a suspended fiber. 12261 12262 var didSuspendOrErrorDEV = false; // Hydration errors that were thrown inside this boundary 12263 12264 var hydrationErrors = null; 12265 12266 function warnIfHydrating() { 12267 { 12268 if (isHydrating) { 12269 error('We should not be hydrating here. This is a bug in React. Please file a bug.'); 12270 } 12271 } 12272 } 12273 12274 function markDidThrowWhileHydratingDEV() { 12275 { 12276 didSuspendOrErrorDEV = true; 12277 } 12278 } 12279 function didSuspendOrErrorWhileHydratingDEV() { 12280 { 12281 return didSuspendOrErrorDEV; 12282 } 12283 } 12284 12285 function enterHydrationState(fiber) { 12286 12287 var parentInstance = fiber.stateNode.containerInfo; 12288 nextHydratableInstance = getFirstHydratableChildWithinContainer(parentInstance); 12289 hydrationParentFiber = fiber; 12290 isHydrating = true; 12291 hydrationErrors = null; 12292 didSuspendOrErrorDEV = false; 12293 return true; 12294 } 12295 12296 function reenterHydrationStateFromDehydratedSuspenseInstance(fiber, suspenseInstance, treeContext) { 12297 12298 nextHydratableInstance = getFirstHydratableChildWithinSuspenseInstance(suspenseInstance); 12299 hydrationParentFiber = fiber; 12300 isHydrating = true; 12301 hydrationErrors = null; 12302 didSuspendOrErrorDEV = false; 12303 12304 if (treeContext !== null) { 12305 restoreSuspendedTreeContext(fiber, treeContext); 12306 } 12307 12308 return true; 12309 } 12310 12311 function warnUnhydratedInstance(returnFiber, instance) { 12312 { 12313 switch (returnFiber.tag) { 12314 case HostRoot: 12315 { 12316 didNotHydrateInstanceWithinContainer(returnFiber.stateNode.containerInfo, instance); 12317 break; 12318 } 12319 12320 case HostComponent: 12321 { 12322 var isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode; 12323 didNotHydrateInstance(returnFiber.type, returnFiber.memoizedProps, returnFiber.stateNode, instance, // TODO: Delete this argument when we remove the legacy root API. 12324 isConcurrentMode); 12325 break; 12326 } 12327 12328 case SuspenseComponent: 12329 { 12330 var suspenseState = returnFiber.memoizedState; 12331 if (suspenseState.dehydrated !== null) didNotHydrateInstanceWithinSuspenseInstance(suspenseState.dehydrated, instance); 12332 break; 12333 } 12334 } 12335 } 12336 } 12337 12338 function deleteHydratableInstance(returnFiber, instance) { 12339 warnUnhydratedInstance(returnFiber, instance); 12340 var childToDelete = createFiberFromHostInstanceForDeletion(); 12341 childToDelete.stateNode = instance; 12342 childToDelete.return = returnFiber; 12343 var deletions = returnFiber.deletions; 12344 12345 if (deletions === null) { 12346 returnFiber.deletions = [childToDelete]; 12347 returnFiber.flags |= ChildDeletion; 12348 } else { 12349 deletions.push(childToDelete); 12350 } 12351 } 12352 12353 function warnNonhydratedInstance(returnFiber, fiber) { 12354 { 12355 if (didSuspendOrErrorDEV) { 12356 // Inside a boundary that already suspended. We're currently rendering the 12357 // siblings of a suspended node. The mismatch may be due to the missing 12358 // data, so it's probably a false positive. 12359 return; 12360 } 12361 12362 switch (returnFiber.tag) { 12363 case HostRoot: 12364 { 12365 var parentContainer = returnFiber.stateNode.containerInfo; 12366 12367 switch (fiber.tag) { 12368 case HostComponent: 12369 var type = fiber.type; 12370 var props = fiber.pendingProps; 12371 didNotFindHydratableInstanceWithinContainer(parentContainer, type); 12372 break; 12373 12374 case HostText: 12375 var text = fiber.pendingProps; 12376 didNotFindHydratableTextInstanceWithinContainer(parentContainer, text); 12377 break; 12378 } 12379 12380 break; 12381 } 12382 12383 case HostComponent: 12384 { 12385 var parentType = returnFiber.type; 12386 var parentProps = returnFiber.memoizedProps; 12387 var parentInstance = returnFiber.stateNode; 12388 12389 switch (fiber.tag) { 12390 case HostComponent: 12391 { 12392 var _type = fiber.type; 12393 var _props = fiber.pendingProps; 12394 var isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode; 12395 didNotFindHydratableInstance(parentType, parentProps, parentInstance, _type, _props, // TODO: Delete this argument when we remove the legacy root API. 12396 isConcurrentMode); 12397 break; 12398 } 12399 12400 case HostText: 12401 { 12402 var _text = fiber.pendingProps; 12403 12404 var _isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode; 12405 12406 didNotFindHydratableTextInstance(parentType, parentProps, parentInstance, _text, // TODO: Delete this argument when we remove the legacy root API. 12407 _isConcurrentMode); 12408 break; 12409 } 12410 } 12411 12412 break; 12413 } 12414 12415 case SuspenseComponent: 12416 { 12417 var suspenseState = returnFiber.memoizedState; 12418 var _parentInstance = suspenseState.dehydrated; 12419 if (_parentInstance !== null) switch (fiber.tag) { 12420 case HostComponent: 12421 var _type2 = fiber.type; 12422 var _props2 = fiber.pendingProps; 12423 didNotFindHydratableInstanceWithinSuspenseInstance(_parentInstance, _type2); 12424 break; 12425 12426 case HostText: 12427 var _text2 = fiber.pendingProps; 12428 didNotFindHydratableTextInstanceWithinSuspenseInstance(_parentInstance, _text2); 12429 break; 12430 } 12431 break; 12432 } 12433 12434 default: 12435 return; 12436 } 12437 } 12438 } 12439 12440 function insertNonHydratedInstance(returnFiber, fiber) { 12441 fiber.flags = fiber.flags & ~Hydrating | Placement; 12442 warnNonhydratedInstance(returnFiber, fiber); 12443 } 12444 12445 function tryHydrate(fiber, nextInstance) { 12446 switch (fiber.tag) { 12447 case HostComponent: 12448 { 12449 var type = fiber.type; 12450 var props = fiber.pendingProps; 12451 var instance = canHydrateInstance(nextInstance, type); 12452 12453 if (instance !== null) { 12454 fiber.stateNode = instance; 12455 hydrationParentFiber = fiber; 12456 nextHydratableInstance = getFirstHydratableChild(instance); 12457 return true; 12458 } 12459 12460 return false; 12461 } 12462 12463 case HostText: 12464 { 12465 var text = fiber.pendingProps; 12466 var textInstance = canHydrateTextInstance(nextInstance, text); 12467 12468 if (textInstance !== null) { 12469 fiber.stateNode = textInstance; 12470 hydrationParentFiber = fiber; // Text Instances don't have children so there's nothing to hydrate. 12471 12472 nextHydratableInstance = null; 12473 return true; 12474 } 12475 12476 return false; 12477 } 12478 12479 case SuspenseComponent: 12480 { 12481 var suspenseInstance = canHydrateSuspenseInstance(nextInstance); 12482 12483 if (suspenseInstance !== null) { 12484 var suspenseState = { 12485 dehydrated: suspenseInstance, 12486 treeContext: getSuspendedTreeContext(), 12487 retryLane: OffscreenLane 12488 }; 12489 fiber.memoizedState = suspenseState; // Store the dehydrated fragment as a child fiber. 12490 // This simplifies the code for getHostSibling and deleting nodes, 12491 // since it doesn't have to consider all Suspense boundaries and 12492 // check if they're dehydrated ones or not. 12493 12494 var dehydratedFragment = createFiberFromDehydratedFragment(suspenseInstance); 12495 dehydratedFragment.return = fiber; 12496 fiber.child = dehydratedFragment; 12497 hydrationParentFiber = fiber; // While a Suspense Instance does have children, we won't step into 12498 // it during the first pass. Instead, we'll reenter it later. 12499 12500 nextHydratableInstance = null; 12501 return true; 12502 } 12503 12504 return false; 12505 } 12506 12507 default: 12508 return false; 12509 } 12510 } 12511 12512 function shouldClientRenderOnMismatch(fiber) { 12513 return (fiber.mode & ConcurrentMode) !== NoMode && (fiber.flags & DidCapture) === NoFlags; 12514 } 12515 12516 function throwOnHydrationMismatch(fiber) { 12517 throw new Error('Hydration failed because the initial UI does not match what was ' + 'rendered on the server.'); 12518 } 12519 12520 function tryToClaimNextHydratableInstance(fiber) { 12521 if (!isHydrating) { 12522 return; 12523 } 12524 12525 var nextInstance = nextHydratableInstance; 12526 12527 if (!nextInstance) { 12528 if (shouldClientRenderOnMismatch(fiber)) { 12529 warnNonhydratedInstance(hydrationParentFiber, fiber); 12530 throwOnHydrationMismatch(); 12531 } // Nothing to hydrate. Make it an insertion. 12532 12533 12534 insertNonHydratedInstance(hydrationParentFiber, fiber); 12535 isHydrating = false; 12536 hydrationParentFiber = fiber; 12537 return; 12538 } 12539 12540 var firstAttemptedInstance = nextInstance; 12541 12542 if (!tryHydrate(fiber, nextInstance)) { 12543 if (shouldClientRenderOnMismatch(fiber)) { 12544 warnNonhydratedInstance(hydrationParentFiber, fiber); 12545 throwOnHydrationMismatch(); 12546 } // If we can't hydrate this instance let's try the next one. 12547 // We use this as a heuristic. It's based on intuition and not data so it 12548 // might be flawed or unnecessary. 12549 12550 12551 nextInstance = getNextHydratableSibling(firstAttemptedInstance); 12552 var prevHydrationParentFiber = hydrationParentFiber; 12553 12554 if (!nextInstance || !tryHydrate(fiber, nextInstance)) { 12555 // Nothing to hydrate. Make it an insertion. 12556 insertNonHydratedInstance(hydrationParentFiber, fiber); 12557 isHydrating = false; 12558 hydrationParentFiber = fiber; 12559 return; 12560 } // We matched the next one, we'll now assume that the first one was 12561 // superfluous and we'll delete it. Since we can't eagerly delete it 12562 // we'll have to schedule a deletion. To do that, this node needs a dummy 12563 // fiber associated with it. 12564 12565 12566 deleteHydratableInstance(prevHydrationParentFiber, firstAttemptedInstance); 12567 } 12568 } 12569 12570 function prepareToHydrateHostInstance(fiber, rootContainerInstance, hostContext) { 12571 12572 var instance = fiber.stateNode; 12573 var shouldWarnIfMismatchDev = !didSuspendOrErrorDEV; 12574 var updatePayload = hydrateInstance(instance, fiber.type, fiber.memoizedProps, rootContainerInstance, hostContext, fiber, shouldWarnIfMismatchDev); // TODO: Type this specific to this type of component. 12575 12576 fiber.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there 12577 // is a new ref we mark this as an update. 12578 12579 if (updatePayload !== null) { 12580 return true; 12581 } 12582 12583 return false; 12584 } 12585 12586 function prepareToHydrateHostTextInstance(fiber) { 12587 12588 var textInstance = fiber.stateNode; 12589 var textContent = fiber.memoizedProps; 12590 var shouldUpdate = hydrateTextInstance(textInstance, textContent, fiber); 12591 12592 if (shouldUpdate) { 12593 // We assume that prepareToHydrateHostTextInstance is called in a context where the 12594 // hydration parent is the parent host component of this host text. 12595 var returnFiber = hydrationParentFiber; 12596 12597 if (returnFiber !== null) { 12598 switch (returnFiber.tag) { 12599 case HostRoot: 12600 { 12601 var parentContainer = returnFiber.stateNode.containerInfo; 12602 var isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode; 12603 didNotMatchHydratedContainerTextInstance(parentContainer, textInstance, textContent, // TODO: Delete this argument when we remove the legacy root API. 12604 isConcurrentMode); 12605 break; 12606 } 12607 12608 case HostComponent: 12609 { 12610 var parentType = returnFiber.type; 12611 var parentProps = returnFiber.memoizedProps; 12612 var parentInstance = returnFiber.stateNode; 12613 12614 var _isConcurrentMode2 = (returnFiber.mode & ConcurrentMode) !== NoMode; 12615 12616 didNotMatchHydratedTextInstance(parentType, parentProps, parentInstance, textInstance, textContent, // TODO: Delete this argument when we remove the legacy root API. 12617 _isConcurrentMode2); 12618 break; 12619 } 12620 } 12621 } 12622 } 12623 12624 return shouldUpdate; 12625 } 12626 12627 function prepareToHydrateHostSuspenseInstance(fiber) { 12628 12629 var suspenseState = fiber.memoizedState; 12630 var suspenseInstance = suspenseState !== null ? suspenseState.dehydrated : null; 12631 12632 if (!suspenseInstance) { 12633 throw new Error('Expected to have a hydrated suspense instance. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 12634 } 12635 12636 hydrateSuspenseInstance(suspenseInstance, fiber); 12637 } 12638 12639 function skipPastDehydratedSuspenseInstance(fiber) { 12640 12641 var suspenseState = fiber.memoizedState; 12642 var suspenseInstance = suspenseState !== null ? suspenseState.dehydrated : null; 12643 12644 if (!suspenseInstance) { 12645 throw new Error('Expected to have a hydrated suspense instance. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 12646 } 12647 12648 return getNextHydratableInstanceAfterSuspenseInstance(suspenseInstance); 12649 } 12650 12651 function popToNextHostParent(fiber) { 12652 var parent = fiber.return; 12653 12654 while (parent !== null && parent.tag !== HostComponent && parent.tag !== HostRoot && parent.tag !== SuspenseComponent) { 12655 parent = parent.return; 12656 } 12657 12658 hydrationParentFiber = parent; 12659 } 12660 12661 function popHydrationState(fiber) { 12662 12663 if (fiber !== hydrationParentFiber) { 12664 // We're deeper than the current hydration context, inside an inserted 12665 // tree. 12666 return false; 12667 } 12668 12669 if (!isHydrating) { 12670 // If we're not currently hydrating but we're in a hydration context, then 12671 // we were an insertion and now need to pop up reenter hydration of our 12672 // siblings. 12673 popToNextHostParent(fiber); 12674 isHydrating = true; 12675 return false; 12676 } // If we have any remaining hydratable nodes, we need to delete them now. 12677 // We only do this deeper than head and body since they tend to have random 12678 // other nodes in them. We also ignore components with pure text content in 12679 // side of them. We also don't delete anything inside the root container. 12680 12681 12682 if (fiber.tag !== HostRoot && (fiber.tag !== HostComponent || shouldDeleteUnhydratedTailInstances(fiber.type) && !shouldSetTextContent(fiber.type, fiber.memoizedProps))) { 12683 var nextInstance = nextHydratableInstance; 12684 12685 if (nextInstance) { 12686 if (shouldClientRenderOnMismatch(fiber)) { 12687 warnIfUnhydratedTailNodes(fiber); 12688 throwOnHydrationMismatch(); 12689 } else { 12690 while (nextInstance) { 12691 deleteHydratableInstance(fiber, nextInstance); 12692 nextInstance = getNextHydratableSibling(nextInstance); 12693 } 12694 } 12695 } 12696 } 12697 12698 popToNextHostParent(fiber); 12699 12700 if (fiber.tag === SuspenseComponent) { 12701 nextHydratableInstance = skipPastDehydratedSuspenseInstance(fiber); 12702 } else { 12703 nextHydratableInstance = hydrationParentFiber ? getNextHydratableSibling(fiber.stateNode) : null; 12704 } 12705 12706 return true; 12707 } 12708 12709 function hasUnhydratedTailNodes() { 12710 return isHydrating && nextHydratableInstance !== null; 12711 } 12712 12713 function warnIfUnhydratedTailNodes(fiber) { 12714 var nextInstance = nextHydratableInstance; 12715 12716 while (nextInstance) { 12717 warnUnhydratedInstance(fiber, nextInstance); 12718 nextInstance = getNextHydratableSibling(nextInstance); 12719 } 12720 } 12721 12722 function resetHydrationState() { 12723 12724 hydrationParentFiber = null; 12725 nextHydratableInstance = null; 12726 isHydrating = false; 12727 didSuspendOrErrorDEV = false; 12728 } 12729 12730 function upgradeHydrationErrorsToRecoverable() { 12731 if (hydrationErrors !== null) { 12732 // Successfully completed a forced client render. The errors that occurred 12733 // during the hydration attempt are now recovered. We will log them in 12734 // commit phase, once the entire tree has finished. 12735 queueRecoverableErrors(hydrationErrors); 12736 hydrationErrors = null; 12737 } 12738 } 12739 12740 function getIsHydrating() { 12741 return isHydrating; 12742 } 12743 12744 function queueHydrationError(error) { 12745 if (hydrationErrors === null) { 12746 hydrationErrors = [error]; 12747 } else { 12748 hydrationErrors.push(error); 12749 } 12750 } 12751 12752 var ReactCurrentBatchConfig$1 = ReactSharedInternals.ReactCurrentBatchConfig; 12753 var NoTransition = null; 12754 function requestCurrentTransition() { 12755 return ReactCurrentBatchConfig$1.transition; 12756 } 12757 12758 var ReactStrictModeWarnings = { 12759 recordUnsafeLifecycleWarnings: function (fiber, instance) {}, 12760 flushPendingUnsafeLifecycleWarnings: function () {}, 12761 recordLegacyContextWarning: function (fiber, instance) {}, 12762 flushLegacyContextWarning: function () {}, 12763 discardPendingWarnings: function () {} 12764 }; 12765 12766 { 12767 var findStrictRoot = function (fiber) { 12768 var maybeStrictRoot = null; 12769 var node = fiber; 12770 12771 while (node !== null) { 12772 if (node.mode & StrictLegacyMode) { 12773 maybeStrictRoot = node; 12774 } 12775 12776 node = node.return; 12777 } 12778 12779 return maybeStrictRoot; 12780 }; 12781 12782 var setToSortedString = function (set) { 12783 var array = []; 12784 set.forEach(function (value) { 12785 array.push(value); 12786 }); 12787 return array.sort().join(', '); 12788 }; 12789 12790 var pendingComponentWillMountWarnings = []; 12791 var pendingUNSAFE_ComponentWillMountWarnings = []; 12792 var pendingComponentWillReceivePropsWarnings = []; 12793 var pendingUNSAFE_ComponentWillReceivePropsWarnings = []; 12794 var pendingComponentWillUpdateWarnings = []; 12795 var pendingUNSAFE_ComponentWillUpdateWarnings = []; // Tracks components we have already warned about. 12796 12797 var didWarnAboutUnsafeLifecycles = new Set(); 12798 12799 ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function (fiber, instance) { 12800 // Dedupe strategy: Warn once per component. 12801 if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { 12802 return; 12803 } 12804 12805 if (typeof instance.componentWillMount === 'function' && // Don't warn about react-lifecycles-compat polyfilled components. 12806 instance.componentWillMount.__suppressDeprecationWarning !== true) { 12807 pendingComponentWillMountWarnings.push(fiber); 12808 } 12809 12810 if (fiber.mode & StrictLegacyMode && typeof instance.UNSAFE_componentWillMount === 'function') { 12811 pendingUNSAFE_ComponentWillMountWarnings.push(fiber); 12812 } 12813 12814 if (typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) { 12815 pendingComponentWillReceivePropsWarnings.push(fiber); 12816 } 12817 12818 if (fiber.mode & StrictLegacyMode && typeof instance.UNSAFE_componentWillReceiveProps === 'function') { 12819 pendingUNSAFE_ComponentWillReceivePropsWarnings.push(fiber); 12820 } 12821 12822 if (typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true) { 12823 pendingComponentWillUpdateWarnings.push(fiber); 12824 } 12825 12826 if (fiber.mode & StrictLegacyMode && typeof instance.UNSAFE_componentWillUpdate === 'function') { 12827 pendingUNSAFE_ComponentWillUpdateWarnings.push(fiber); 12828 } 12829 }; 12830 12831 ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { 12832 // We do an initial pass to gather component names 12833 var componentWillMountUniqueNames = new Set(); 12834 12835 if (pendingComponentWillMountWarnings.length > 0) { 12836 pendingComponentWillMountWarnings.forEach(function (fiber) { 12837 componentWillMountUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component'); 12838 didWarnAboutUnsafeLifecycles.add(fiber.type); 12839 }); 12840 pendingComponentWillMountWarnings = []; 12841 } 12842 12843 var UNSAFE_componentWillMountUniqueNames = new Set(); 12844 12845 if (pendingUNSAFE_ComponentWillMountWarnings.length > 0) { 12846 pendingUNSAFE_ComponentWillMountWarnings.forEach(function (fiber) { 12847 UNSAFE_componentWillMountUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component'); 12848 didWarnAboutUnsafeLifecycles.add(fiber.type); 12849 }); 12850 pendingUNSAFE_ComponentWillMountWarnings = []; 12851 } 12852 12853 var componentWillReceivePropsUniqueNames = new Set(); 12854 12855 if (pendingComponentWillReceivePropsWarnings.length > 0) { 12856 pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { 12857 componentWillReceivePropsUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component'); 12858 didWarnAboutUnsafeLifecycles.add(fiber.type); 12859 }); 12860 pendingComponentWillReceivePropsWarnings = []; 12861 } 12862 12863 var UNSAFE_componentWillReceivePropsUniqueNames = new Set(); 12864 12865 if (pendingUNSAFE_ComponentWillReceivePropsWarnings.length > 0) { 12866 pendingUNSAFE_ComponentWillReceivePropsWarnings.forEach(function (fiber) { 12867 UNSAFE_componentWillReceivePropsUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component'); 12868 didWarnAboutUnsafeLifecycles.add(fiber.type); 12869 }); 12870 pendingUNSAFE_ComponentWillReceivePropsWarnings = []; 12871 } 12872 12873 var componentWillUpdateUniqueNames = new Set(); 12874 12875 if (pendingComponentWillUpdateWarnings.length > 0) { 12876 pendingComponentWillUpdateWarnings.forEach(function (fiber) { 12877 componentWillUpdateUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component'); 12878 didWarnAboutUnsafeLifecycles.add(fiber.type); 12879 }); 12880 pendingComponentWillUpdateWarnings = []; 12881 } 12882 12883 var UNSAFE_componentWillUpdateUniqueNames = new Set(); 12884 12885 if (pendingUNSAFE_ComponentWillUpdateWarnings.length > 0) { 12886 pendingUNSAFE_ComponentWillUpdateWarnings.forEach(function (fiber) { 12887 UNSAFE_componentWillUpdateUniqueNames.add(getComponentNameFromFiber(fiber) || 'Component'); 12888 didWarnAboutUnsafeLifecycles.add(fiber.type); 12889 }); 12890 pendingUNSAFE_ComponentWillUpdateWarnings = []; 12891 } // Finally, we flush all the warnings 12892 // UNSAFE_ ones before the deprecated ones, since they'll be 'louder' 12893 12894 12895 if (UNSAFE_componentWillMountUniqueNames.size > 0) { 12896 var sortedNames = setToSortedString(UNSAFE_componentWillMountUniqueNames); 12897 12898 error('Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' + '\nPlease update the following components: %s', sortedNames); 12899 } 12900 12901 if (UNSAFE_componentWillReceivePropsUniqueNames.size > 0) { 12902 var _sortedNames = setToSortedString(UNSAFE_componentWillReceivePropsUniqueNames); 12903 12904 error('Using UNSAFE_componentWillReceiveProps in strict mode is not recommended ' + 'and may indicate bugs in your code. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move data fetching code or side effects to componentDidUpdate.\n' + "* If you're updating state whenever props change, " + 'refactor your code to use memoization techniques or move it to ' + 'static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n' + '\nPlease update the following components: %s', _sortedNames); 12905 } 12906 12907 if (UNSAFE_componentWillUpdateUniqueNames.size > 0) { 12908 var _sortedNames2 = setToSortedString(UNSAFE_componentWillUpdateUniqueNames); 12909 12910 error('Using UNSAFE_componentWillUpdate in strict mode is not recommended ' + 'and may indicate bugs in your code. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move data fetching code or side effects to componentDidUpdate.\n' + '\nPlease update the following components: %s', _sortedNames2); 12911 } 12912 12913 if (componentWillMountUniqueNames.size > 0) { 12914 var _sortedNames3 = setToSortedString(componentWillMountUniqueNames); 12915 12916 warn('componentWillMount has been renamed, and is not recommended for use. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' + '* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' + 'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' + 'To rename all deprecated lifecycles to their new names, you can run ' + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + '\nPlease update the following components: %s', _sortedNames3); 12917 } 12918 12919 if (componentWillReceivePropsUniqueNames.size > 0) { 12920 var _sortedNames4 = setToSortedString(componentWillReceivePropsUniqueNames); 12921 12922 warn('componentWillReceiveProps has been renamed, and is not recommended for use. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move data fetching code or side effects to componentDidUpdate.\n' + "* If you're updating state whenever props change, refactor your " + 'code to use memoization techniques or move it to ' + 'static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state\n' + '* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' + 'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' + 'To rename all deprecated lifecycles to their new names, you can run ' + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + '\nPlease update the following components: %s', _sortedNames4); 12923 } 12924 12925 if (componentWillUpdateUniqueNames.size > 0) { 12926 var _sortedNames5 = setToSortedString(componentWillUpdateUniqueNames); 12927 12928 warn('componentWillUpdate has been renamed, and is not recommended for use. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move data fetching code or side effects to componentDidUpdate.\n' + '* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' + 'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' + 'To rename all deprecated lifecycles to their new names, you can run ' + '`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' + '\nPlease update the following components: %s', _sortedNames5); 12929 } 12930 }; 12931 12932 var pendingLegacyContextWarning = new Map(); // Tracks components we have already warned about. 12933 12934 var didWarnAboutLegacyContext = new Set(); 12935 12936 ReactStrictModeWarnings.recordLegacyContextWarning = function (fiber, instance) { 12937 var strictRoot = findStrictRoot(fiber); 12938 12939 if (strictRoot === null) { 12940 error('Expected to find a StrictMode component in a strict mode tree. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 12941 12942 return; 12943 } // Dedup strategy: Warn once per component. 12944 12945 12946 if (didWarnAboutLegacyContext.has(fiber.type)) { 12947 return; 12948 } 12949 12950 var warningsForRoot = pendingLegacyContextWarning.get(strictRoot); 12951 12952 if (fiber.type.contextTypes != null || fiber.type.childContextTypes != null || instance !== null && typeof instance.getChildContext === 'function') { 12953 if (warningsForRoot === undefined) { 12954 warningsForRoot = []; 12955 pendingLegacyContextWarning.set(strictRoot, warningsForRoot); 12956 } 12957 12958 warningsForRoot.push(fiber); 12959 } 12960 }; 12961 12962 ReactStrictModeWarnings.flushLegacyContextWarning = function () { 12963 pendingLegacyContextWarning.forEach(function (fiberArray, strictRoot) { 12964 if (fiberArray.length === 0) { 12965 return; 12966 } 12967 12968 var firstFiber = fiberArray[0]; 12969 var uniqueNames = new Set(); 12970 fiberArray.forEach(function (fiber) { 12971 uniqueNames.add(getComponentNameFromFiber(fiber) || 'Component'); 12972 didWarnAboutLegacyContext.add(fiber.type); 12973 }); 12974 var sortedNames = setToSortedString(uniqueNames); 12975 12976 try { 12977 setCurrentFiber(firstFiber); 12978 12979 error('Legacy context API has been detected within a strict-mode tree.' + '\n\nThe old API will be supported in all 16.x releases, but applications ' + 'using it should migrate to the new version.' + '\n\nPlease update the following components: %s' + '\n\nLearn more about this warning here: https://reactjs.org/link/legacy-context', sortedNames); 12980 } finally { 12981 resetCurrentFiber(); 12982 } 12983 }); 12984 }; 12985 12986 ReactStrictModeWarnings.discardPendingWarnings = function () { 12987 pendingComponentWillMountWarnings = []; 12988 pendingUNSAFE_ComponentWillMountWarnings = []; 12989 pendingComponentWillReceivePropsWarnings = []; 12990 pendingUNSAFE_ComponentWillReceivePropsWarnings = []; 12991 pendingComponentWillUpdateWarnings = []; 12992 pendingUNSAFE_ComponentWillUpdateWarnings = []; 12993 pendingLegacyContextWarning = new Map(); 12994 }; 12995 } 12996 12997 function resolveDefaultProps(Component, baseProps) { 12998 if (Component && Component.defaultProps) { 12999 // Resolve default props. Taken from ReactElement 13000 var props = assign({}, baseProps); 13001 var defaultProps = Component.defaultProps; 13002 13003 for (var propName in defaultProps) { 13004 if (props[propName] === undefined) { 13005 props[propName] = defaultProps[propName]; 13006 } 13007 } 13008 13009 return props; 13010 } 13011 13012 return baseProps; 13013 } 13014 13015 var valueCursor = createCursor(null); 13016 var rendererSigil; 13017 13018 { 13019 // Use this to detect multiple renderers using the same context 13020 rendererSigil = {}; 13021 } 13022 13023 var currentlyRenderingFiber = null; 13024 var lastContextDependency = null; 13025 var lastFullyObservedContext = null; 13026 var isDisallowedContextReadInDEV = false; 13027 function resetContextDependencies() { 13028 // This is called right before React yields execution, to ensure `readContext` 13029 // cannot be called outside the render phase. 13030 currentlyRenderingFiber = null; 13031 lastContextDependency = null; 13032 lastFullyObservedContext = null; 13033 13034 { 13035 isDisallowedContextReadInDEV = false; 13036 } 13037 } 13038 function enterDisallowedContextReadInDEV() { 13039 { 13040 isDisallowedContextReadInDEV = true; 13041 } 13042 } 13043 function exitDisallowedContextReadInDEV() { 13044 { 13045 isDisallowedContextReadInDEV = false; 13046 } 13047 } 13048 function pushProvider(providerFiber, context, nextValue) { 13049 { 13050 push(valueCursor, context._currentValue, providerFiber); 13051 context._currentValue = nextValue; 13052 13053 { 13054 if (context._currentRenderer !== undefined && context._currentRenderer !== null && context._currentRenderer !== rendererSigil) { 13055 error('Detected multiple renderers concurrently rendering the ' + 'same context provider. This is currently unsupported.'); 13056 } 13057 13058 context._currentRenderer = rendererSigil; 13059 } 13060 } 13061 } 13062 function popProvider(context, providerFiber) { 13063 var currentValue = valueCursor.current; 13064 pop(valueCursor, providerFiber); 13065 13066 { 13067 { 13068 context._currentValue = currentValue; 13069 } 13070 } 13071 } 13072 function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { 13073 // Update the child lanes of all the ancestors, including the alternates. 13074 var node = parent; 13075 13076 while (node !== null) { 13077 var alternate = node.alternate; 13078 13079 if (!isSubsetOfLanes(node.childLanes, renderLanes)) { 13080 node.childLanes = mergeLanes(node.childLanes, renderLanes); 13081 13082 if (alternate !== null) { 13083 alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); 13084 } 13085 } else if (alternate !== null && !isSubsetOfLanes(alternate.childLanes, renderLanes)) { 13086 alternate.childLanes = mergeLanes(alternate.childLanes, renderLanes); 13087 } 13088 13089 if (node === propagationRoot) { 13090 break; 13091 } 13092 13093 node = node.return; 13094 } 13095 13096 { 13097 if (node !== propagationRoot) { 13098 error('Expected to find the propagation root when scheduling context work. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 13099 } 13100 } 13101 } 13102 function propagateContextChange(workInProgress, context, renderLanes) { 13103 { 13104 propagateContextChange_eager(workInProgress, context, renderLanes); 13105 } 13106 } 13107 13108 function propagateContextChange_eager(workInProgress, context, renderLanes) { 13109 13110 var fiber = workInProgress.child; 13111 13112 if (fiber !== null) { 13113 // Set the return pointer of the child to the work-in-progress fiber. 13114 fiber.return = workInProgress; 13115 } 13116 13117 while (fiber !== null) { 13118 var nextFiber = void 0; // Visit this fiber. 13119 13120 var list = fiber.dependencies; 13121 13122 if (list !== null) { 13123 nextFiber = fiber.child; 13124 var dependency = list.firstContext; 13125 13126 while (dependency !== null) { 13127 // Check if the context matches. 13128 if (dependency.context === context) { 13129 // Match! Schedule an update on this fiber. 13130 if (fiber.tag === ClassComponent) { 13131 // Schedule a force update on the work-in-progress. 13132 var lane = pickArbitraryLane(renderLanes); 13133 var update = createUpdate(NoTimestamp, lane); 13134 update.tag = ForceUpdate; // TODO: Because we don't have a work-in-progress, this will add the 13135 // update to the current fiber, too, which means it will persist even if 13136 // this render is thrown away. Since it's a race condition, not sure it's 13137 // worth fixing. 13138 // Inlined `enqueueUpdate` to remove interleaved update check 13139 13140 var updateQueue = fiber.updateQueue; 13141 13142 if (updateQueue === null) ; else { 13143 var sharedQueue = updateQueue.shared; 13144 var pending = sharedQueue.pending; 13145 13146 if (pending === null) { 13147 // This is the first update. Create a circular list. 13148 update.next = update; 13149 } else { 13150 update.next = pending.next; 13151 pending.next = update; 13152 } 13153 13154 sharedQueue.pending = update; 13155 } 13156 } 13157 13158 fiber.lanes = mergeLanes(fiber.lanes, renderLanes); 13159 var alternate = fiber.alternate; 13160 13161 if (alternate !== null) { 13162 alternate.lanes = mergeLanes(alternate.lanes, renderLanes); 13163 } 13164 13165 scheduleContextWorkOnParentPath(fiber.return, renderLanes, workInProgress); // Mark the updated lanes on the list, too. 13166 13167 list.lanes = mergeLanes(list.lanes, renderLanes); // Since we already found a match, we can stop traversing the 13168 // dependency list. 13169 13170 break; 13171 } 13172 13173 dependency = dependency.next; 13174 } 13175 } else if (fiber.tag === ContextProvider) { 13176 // Don't scan deeper if this is a matching provider 13177 nextFiber = fiber.type === workInProgress.type ? null : fiber.child; 13178 } else if (fiber.tag === DehydratedFragment) { 13179 // If a dehydrated suspense boundary is in this subtree, we don't know 13180 // if it will have any context consumers in it. The best we can do is 13181 // mark it as having updates. 13182 var parentSuspense = fiber.return; 13183 13184 if (parentSuspense === null) { 13185 throw new Error('We just came from a parent so we must have had a parent. This is a bug in React.'); 13186 } 13187 13188 parentSuspense.lanes = mergeLanes(parentSuspense.lanes, renderLanes); 13189 var _alternate = parentSuspense.alternate; 13190 13191 if (_alternate !== null) { 13192 _alternate.lanes = mergeLanes(_alternate.lanes, renderLanes); 13193 } // This is intentionally passing this fiber as the parent 13194 // because we want to schedule this fiber as having work 13195 // on its children. We'll use the childLanes on 13196 // this fiber to indicate that a context has changed. 13197 13198 13199 scheduleContextWorkOnParentPath(parentSuspense, renderLanes, workInProgress); 13200 nextFiber = fiber.sibling; 13201 } else { 13202 // Traverse down. 13203 nextFiber = fiber.child; 13204 } 13205 13206 if (nextFiber !== null) { 13207 // Set the return pointer of the child to the work-in-progress fiber. 13208 nextFiber.return = fiber; 13209 } else { 13210 // No child. Traverse to next sibling. 13211 nextFiber = fiber; 13212 13213 while (nextFiber !== null) { 13214 if (nextFiber === workInProgress) { 13215 // We're back to the root of this subtree. Exit. 13216 nextFiber = null; 13217 break; 13218 } 13219 13220 var sibling = nextFiber.sibling; 13221 13222 if (sibling !== null) { 13223 // Set the return pointer of the sibling to the work-in-progress fiber. 13224 sibling.return = nextFiber.return; 13225 nextFiber = sibling; 13226 break; 13227 } // No more siblings. Traverse up. 13228 13229 13230 nextFiber = nextFiber.return; 13231 } 13232 } 13233 13234 fiber = nextFiber; 13235 } 13236 } 13237 function prepareToReadContext(workInProgress, renderLanes) { 13238 currentlyRenderingFiber = workInProgress; 13239 lastContextDependency = null; 13240 lastFullyObservedContext = null; 13241 var dependencies = workInProgress.dependencies; 13242 13243 if (dependencies !== null) { 13244 { 13245 var firstContext = dependencies.firstContext; 13246 13247 if (firstContext !== null) { 13248 if (includesSomeLane(dependencies.lanes, renderLanes)) { 13249 // Context list has a pending update. Mark that this fiber performed work. 13250 markWorkInProgressReceivedUpdate(); 13251 } // Reset the work-in-progress list 13252 13253 13254 dependencies.firstContext = null; 13255 } 13256 } 13257 } 13258 } 13259 function readContext(context) { 13260 { 13261 // This warning would fire if you read context inside a Hook like useMemo. 13262 // Unlike the class check below, it's not enforced in production for perf. 13263 if (isDisallowedContextReadInDEV) { 13264 error('Context can only be read while React is rendering. ' + 'In classes, you can read it in the render method or getDerivedStateFromProps. ' + 'In function components, you can read it directly in the function body, but not ' + 'inside Hooks like useReducer() or useMemo().'); 13265 } 13266 } 13267 13268 var value = context._currentValue ; 13269 13270 if (lastFullyObservedContext === context) ; else { 13271 var contextItem = { 13272 context: context, 13273 memoizedValue: value, 13274 next: null 13275 }; 13276 13277 if (lastContextDependency === null) { 13278 if (currentlyRenderingFiber === null) { 13279 throw new Error('Context can only be read while React is rendering. ' + 'In classes, you can read it in the render method or getDerivedStateFromProps. ' + 'In function components, you can read it directly in the function body, but not ' + 'inside Hooks like useReducer() or useMemo().'); 13280 } // This is the first dependency for this component. Create a new list. 13281 13282 13283 lastContextDependency = contextItem; 13284 currentlyRenderingFiber.dependencies = { 13285 lanes: NoLanes, 13286 firstContext: contextItem 13287 }; 13288 } else { 13289 // Append a new context item. 13290 lastContextDependency = lastContextDependency.next = contextItem; 13291 } 13292 } 13293 13294 return value; 13295 } 13296 13297 // render. When this render exits, either because it finishes or because it is 13298 // interrupted, the interleaved updates will be transferred onto the main part 13299 // of the queue. 13300 13301 var concurrentQueues = null; 13302 function pushConcurrentUpdateQueue(queue) { 13303 if (concurrentQueues === null) { 13304 concurrentQueues = [queue]; 13305 } else { 13306 concurrentQueues.push(queue); 13307 } 13308 } 13309 function finishQueueingConcurrentUpdates() { 13310 // Transfer the interleaved updates onto the main queue. Each queue has a 13311 // `pending` field and an `interleaved` field. When they are not null, they 13312 // point to the last node in a circular linked list. We need to append the 13313 // interleaved list to the end of the pending list by joining them into a 13314 // single, circular list. 13315 if (concurrentQueues !== null) { 13316 for (var i = 0; i < concurrentQueues.length; i++) { 13317 var queue = concurrentQueues[i]; 13318 var lastInterleavedUpdate = queue.interleaved; 13319 13320 if (lastInterleavedUpdate !== null) { 13321 queue.interleaved = null; 13322 var firstInterleavedUpdate = lastInterleavedUpdate.next; 13323 var lastPendingUpdate = queue.pending; 13324 13325 if (lastPendingUpdate !== null) { 13326 var firstPendingUpdate = lastPendingUpdate.next; 13327 lastPendingUpdate.next = firstInterleavedUpdate; 13328 lastInterleavedUpdate.next = firstPendingUpdate; 13329 } 13330 13331 queue.pending = lastInterleavedUpdate; 13332 } 13333 } 13334 13335 concurrentQueues = null; 13336 } 13337 } 13338 function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { 13339 var interleaved = queue.interleaved; 13340 13341 if (interleaved === null) { 13342 // This is the first update. Create a circular list. 13343 update.next = update; // At the end of the current render, this queue's interleaved updates will 13344 // be transferred to the pending queue. 13345 13346 pushConcurrentUpdateQueue(queue); 13347 } else { 13348 update.next = interleaved.next; 13349 interleaved.next = update; 13350 } 13351 13352 queue.interleaved = update; 13353 return markUpdateLaneFromFiberToRoot(fiber, lane); 13354 } 13355 function enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update, lane) { 13356 var interleaved = queue.interleaved; 13357 13358 if (interleaved === null) { 13359 // This is the first update. Create a circular list. 13360 update.next = update; // At the end of the current render, this queue's interleaved updates will 13361 // be transferred to the pending queue. 13362 13363 pushConcurrentUpdateQueue(queue); 13364 } else { 13365 update.next = interleaved.next; 13366 interleaved.next = update; 13367 } 13368 13369 queue.interleaved = update; 13370 } 13371 function enqueueConcurrentClassUpdate(fiber, queue, update, lane) { 13372 var interleaved = queue.interleaved; 13373 13374 if (interleaved === null) { 13375 // This is the first update. Create a circular list. 13376 update.next = update; // At the end of the current render, this queue's interleaved updates will 13377 // be transferred to the pending queue. 13378 13379 pushConcurrentUpdateQueue(queue); 13380 } else { 13381 update.next = interleaved.next; 13382 interleaved.next = update; 13383 } 13384 13385 queue.interleaved = update; 13386 return markUpdateLaneFromFiberToRoot(fiber, lane); 13387 } 13388 function enqueueConcurrentRenderForLane(fiber, lane) { 13389 return markUpdateLaneFromFiberToRoot(fiber, lane); 13390 } // Calling this function outside this module should only be done for backwards 13391 // compatibility and should always be accompanied by a warning. 13392 13393 var unsafe_markUpdateLaneFromFiberToRoot = markUpdateLaneFromFiberToRoot; 13394 13395 function markUpdateLaneFromFiberToRoot(sourceFiber, lane) { 13396 // Update the source fiber's lanes 13397 sourceFiber.lanes = mergeLanes(sourceFiber.lanes, lane); 13398 var alternate = sourceFiber.alternate; 13399 13400 if (alternate !== null) { 13401 alternate.lanes = mergeLanes(alternate.lanes, lane); 13402 } 13403 13404 { 13405 if (alternate === null && (sourceFiber.flags & (Placement | Hydrating)) !== NoFlags) { 13406 warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); 13407 } 13408 } // Walk the parent path to the root and update the child lanes. 13409 13410 13411 var node = sourceFiber; 13412 var parent = sourceFiber.return; 13413 13414 while (parent !== null) { 13415 parent.childLanes = mergeLanes(parent.childLanes, lane); 13416 alternate = parent.alternate; 13417 13418 if (alternate !== null) { 13419 alternate.childLanes = mergeLanes(alternate.childLanes, lane); 13420 } else { 13421 { 13422 if ((parent.flags & (Placement | Hydrating)) !== NoFlags) { 13423 warnAboutUpdateOnNotYetMountedFiberInDEV(sourceFiber); 13424 } 13425 } 13426 } 13427 13428 node = parent; 13429 parent = parent.return; 13430 } 13431 13432 if (node.tag === HostRoot) { 13433 var root = node.stateNode; 13434 return root; 13435 } else { 13436 return null; 13437 } 13438 } 13439 13440 var UpdateState = 0; 13441 var ReplaceState = 1; 13442 var ForceUpdate = 2; 13443 var CaptureUpdate = 3; // Global state that is reset at the beginning of calling `processUpdateQueue`. 13444 // It should only be read right after calling `processUpdateQueue`, via 13445 // `checkHasForceUpdateAfterProcessing`. 13446 13447 var hasForceUpdate = false; 13448 var didWarnUpdateInsideUpdate; 13449 var currentlyProcessingQueue; 13450 13451 { 13452 didWarnUpdateInsideUpdate = false; 13453 currentlyProcessingQueue = null; 13454 } 13455 13456 function initializeUpdateQueue(fiber) { 13457 var queue = { 13458 baseState: fiber.memoizedState, 13459 firstBaseUpdate: null, 13460 lastBaseUpdate: null, 13461 shared: { 13462 pending: null, 13463 interleaved: null, 13464 lanes: NoLanes 13465 }, 13466 effects: null 13467 }; 13468 fiber.updateQueue = queue; 13469 } 13470 function cloneUpdateQueue(current, workInProgress) { 13471 // Clone the update queue from current. Unless it's already a clone. 13472 var queue = workInProgress.updateQueue; 13473 var currentQueue = current.updateQueue; 13474 13475 if (queue === currentQueue) { 13476 var clone = { 13477 baseState: currentQueue.baseState, 13478 firstBaseUpdate: currentQueue.firstBaseUpdate, 13479 lastBaseUpdate: currentQueue.lastBaseUpdate, 13480 shared: currentQueue.shared, 13481 effects: currentQueue.effects 13482 }; 13483 workInProgress.updateQueue = clone; 13484 } 13485 } 13486 function createUpdate(eventTime, lane) { 13487 var update = { 13488 eventTime: eventTime, 13489 lane: lane, 13490 tag: UpdateState, 13491 payload: null, 13492 callback: null, 13493 next: null 13494 }; 13495 return update; 13496 } 13497 function enqueueUpdate(fiber, update, lane) { 13498 var updateQueue = fiber.updateQueue; 13499 13500 if (updateQueue === null) { 13501 // Only occurs if the fiber has been unmounted. 13502 return null; 13503 } 13504 13505 var sharedQueue = updateQueue.shared; 13506 13507 { 13508 if (currentlyProcessingQueue === sharedQueue && !didWarnUpdateInsideUpdate) { 13509 error('An update (setState, replaceState, or forceUpdate) was scheduled ' + 'from inside an update function. Update functions should be pure, ' + 'with zero side-effects. Consider using componentDidUpdate or a ' + 'callback.'); 13510 13511 didWarnUpdateInsideUpdate = true; 13512 } 13513 } 13514 13515 if (isUnsafeClassRenderPhaseUpdate()) { 13516 // This is an unsafe render phase update. Add directly to the update 13517 // queue so we can process it immediately during the current render. 13518 var pending = sharedQueue.pending; 13519 13520 if (pending === null) { 13521 // This is the first update. Create a circular list. 13522 update.next = update; 13523 } else { 13524 update.next = pending.next; 13525 pending.next = update; 13526 } 13527 13528 sharedQueue.pending = update; // Update the childLanes even though we're most likely already rendering 13529 // this fiber. This is for backwards compatibility in the case where you 13530 // update a different component during render phase than the one that is 13531 // currently renderings (a pattern that is accompanied by a warning). 13532 13533 return unsafe_markUpdateLaneFromFiberToRoot(fiber, lane); 13534 } else { 13535 return enqueueConcurrentClassUpdate(fiber, sharedQueue, update, lane); 13536 } 13537 } 13538 function entangleTransitions(root, fiber, lane) { 13539 var updateQueue = fiber.updateQueue; 13540 13541 if (updateQueue === null) { 13542 // Only occurs if the fiber has been unmounted. 13543 return; 13544 } 13545 13546 var sharedQueue = updateQueue.shared; 13547 13548 if (isTransitionLane(lane)) { 13549 var queueLanes = sharedQueue.lanes; // If any entangled lanes are no longer pending on the root, then they must 13550 // have finished. We can remove them from the shared queue, which represents 13551 // a superset of the actually pending lanes. In some cases we may entangle 13552 // more than we need to, but that's OK. In fact it's worse if we *don't* 13553 // entangle when we should. 13554 13555 queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. 13556 13557 var newQueueLanes = mergeLanes(queueLanes, lane); 13558 sharedQueue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if 13559 // the lane finished since the last time we entangled it. So we need to 13560 // entangle it again, just to be sure. 13561 13562 markRootEntangled(root, newQueueLanes); 13563 } 13564 } 13565 function enqueueCapturedUpdate(workInProgress, capturedUpdate) { 13566 // Captured updates are updates that are thrown by a child during the render 13567 // phase. They should be discarded if the render is aborted. Therefore, 13568 // we should only put them on the work-in-progress queue, not the current one. 13569 var queue = workInProgress.updateQueue; // Check if the work-in-progress queue is a clone. 13570 13571 var current = workInProgress.alternate; 13572 13573 if (current !== null) { 13574 var currentQueue = current.updateQueue; 13575 13576 if (queue === currentQueue) { 13577 // The work-in-progress queue is the same as current. This happens when 13578 // we bail out on a parent fiber that then captures an error thrown by 13579 // a child. Since we want to append the update only to the work-in 13580 // -progress queue, we need to clone the updates. We usually clone during 13581 // processUpdateQueue, but that didn't happen in this case because we 13582 // skipped over the parent when we bailed out. 13583 var newFirst = null; 13584 var newLast = null; 13585 var firstBaseUpdate = queue.firstBaseUpdate; 13586 13587 if (firstBaseUpdate !== null) { 13588 // Loop through the updates and clone them. 13589 var update = firstBaseUpdate; 13590 13591 do { 13592 var clone = { 13593 eventTime: update.eventTime, 13594 lane: update.lane, 13595 tag: update.tag, 13596 payload: update.payload, 13597 callback: update.callback, 13598 next: null 13599 }; 13600 13601 if (newLast === null) { 13602 newFirst = newLast = clone; 13603 } else { 13604 newLast.next = clone; 13605 newLast = clone; 13606 } 13607 13608 update = update.next; 13609 } while (update !== null); // Append the captured update the end of the cloned list. 13610 13611 13612 if (newLast === null) { 13613 newFirst = newLast = capturedUpdate; 13614 } else { 13615 newLast.next = capturedUpdate; 13616 newLast = capturedUpdate; 13617 } 13618 } else { 13619 // There are no base updates. 13620 newFirst = newLast = capturedUpdate; 13621 } 13622 13623 queue = { 13624 baseState: currentQueue.baseState, 13625 firstBaseUpdate: newFirst, 13626 lastBaseUpdate: newLast, 13627 shared: currentQueue.shared, 13628 effects: currentQueue.effects 13629 }; 13630 workInProgress.updateQueue = queue; 13631 return; 13632 } 13633 } // Append the update to the end of the list. 13634 13635 13636 var lastBaseUpdate = queue.lastBaseUpdate; 13637 13638 if (lastBaseUpdate === null) { 13639 queue.firstBaseUpdate = capturedUpdate; 13640 } else { 13641 lastBaseUpdate.next = capturedUpdate; 13642 } 13643 13644 queue.lastBaseUpdate = capturedUpdate; 13645 } 13646 13647 function getStateFromUpdate(workInProgress, queue, update, prevState, nextProps, instance) { 13648 switch (update.tag) { 13649 case ReplaceState: 13650 { 13651 var payload = update.payload; 13652 13653 if (typeof payload === 'function') { 13654 // Updater function 13655 { 13656 enterDisallowedContextReadInDEV(); 13657 } 13658 13659 var nextState = payload.call(instance, prevState, nextProps); 13660 13661 { 13662 if ( workInProgress.mode & StrictLegacyMode) { 13663 setIsStrictModeForDevtools(true); 13664 13665 try { 13666 payload.call(instance, prevState, nextProps); 13667 } finally { 13668 setIsStrictModeForDevtools(false); 13669 } 13670 } 13671 13672 exitDisallowedContextReadInDEV(); 13673 } 13674 13675 return nextState; 13676 } // State object 13677 13678 13679 return payload; 13680 } 13681 13682 case CaptureUpdate: 13683 { 13684 workInProgress.flags = workInProgress.flags & ~ShouldCapture | DidCapture; 13685 } 13686 // Intentional fallthrough 13687 13688 case UpdateState: 13689 { 13690 var _payload = update.payload; 13691 var partialState; 13692 13693 if (typeof _payload === 'function') { 13694 // Updater function 13695 { 13696 enterDisallowedContextReadInDEV(); 13697 } 13698 13699 partialState = _payload.call(instance, prevState, nextProps); 13700 13701 { 13702 if ( workInProgress.mode & StrictLegacyMode) { 13703 setIsStrictModeForDevtools(true); 13704 13705 try { 13706 _payload.call(instance, prevState, nextProps); 13707 } finally { 13708 setIsStrictModeForDevtools(false); 13709 } 13710 } 13711 13712 exitDisallowedContextReadInDEV(); 13713 } 13714 } else { 13715 // Partial state object 13716 partialState = _payload; 13717 } 13718 13719 if (partialState === null || partialState === undefined) { 13720 // Null and undefined are treated as no-ops. 13721 return prevState; 13722 } // Merge the partial state and the previous state. 13723 13724 13725 return assign({}, prevState, partialState); 13726 } 13727 13728 case ForceUpdate: 13729 { 13730 hasForceUpdate = true; 13731 return prevState; 13732 } 13733 } 13734 13735 return prevState; 13736 } 13737 13738 function processUpdateQueue(workInProgress, props, instance, renderLanes) { 13739 // This is always non-null on a ClassComponent or HostRoot 13740 var queue = workInProgress.updateQueue; 13741 hasForceUpdate = false; 13742 13743 { 13744 currentlyProcessingQueue = queue.shared; 13745 } 13746 13747 var firstBaseUpdate = queue.firstBaseUpdate; 13748 var lastBaseUpdate = queue.lastBaseUpdate; // Check if there are pending updates. If so, transfer them to the base queue. 13749 13750 var pendingQueue = queue.shared.pending; 13751 13752 if (pendingQueue !== null) { 13753 queue.shared.pending = null; // The pending queue is circular. Disconnect the pointer between first 13754 // and last so that it's non-circular. 13755 13756 var lastPendingUpdate = pendingQueue; 13757 var firstPendingUpdate = lastPendingUpdate.next; 13758 lastPendingUpdate.next = null; // Append pending updates to base queue 13759 13760 if (lastBaseUpdate === null) { 13761 firstBaseUpdate = firstPendingUpdate; 13762 } else { 13763 lastBaseUpdate.next = firstPendingUpdate; 13764 } 13765 13766 lastBaseUpdate = lastPendingUpdate; // If there's a current queue, and it's different from the base queue, then 13767 // we need to transfer the updates to that queue, too. Because the base 13768 // queue is a singly-linked list with no cycles, we can append to both 13769 // lists and take advantage of structural sharing. 13770 // TODO: Pass `current` as argument 13771 13772 var current = workInProgress.alternate; 13773 13774 if (current !== null) { 13775 // This is always non-null on a ClassComponent or HostRoot 13776 var currentQueue = current.updateQueue; 13777 var currentLastBaseUpdate = currentQueue.lastBaseUpdate; 13778 13779 if (currentLastBaseUpdate !== lastBaseUpdate) { 13780 if (currentLastBaseUpdate === null) { 13781 currentQueue.firstBaseUpdate = firstPendingUpdate; 13782 } else { 13783 currentLastBaseUpdate.next = firstPendingUpdate; 13784 } 13785 13786 currentQueue.lastBaseUpdate = lastPendingUpdate; 13787 } 13788 } 13789 } // These values may change as we process the queue. 13790 13791 13792 if (firstBaseUpdate !== null) { 13793 // Iterate through the list of updates to compute the result. 13794 var newState = queue.baseState; // TODO: Don't need to accumulate this. Instead, we can remove renderLanes 13795 // from the original lanes. 13796 13797 var newLanes = NoLanes; 13798 var newBaseState = null; 13799 var newFirstBaseUpdate = null; 13800 var newLastBaseUpdate = null; 13801 var update = firstBaseUpdate; 13802 13803 do { 13804 var updateLane = update.lane; 13805 var updateEventTime = update.eventTime; 13806 13807 if (!isSubsetOfLanes(renderLanes, updateLane)) { 13808 // Priority is insufficient. Skip this update. If this is the first 13809 // skipped update, the previous update/state is the new base 13810 // update/state. 13811 var clone = { 13812 eventTime: updateEventTime, 13813 lane: updateLane, 13814 tag: update.tag, 13815 payload: update.payload, 13816 callback: update.callback, 13817 next: null 13818 }; 13819 13820 if (newLastBaseUpdate === null) { 13821 newFirstBaseUpdate = newLastBaseUpdate = clone; 13822 newBaseState = newState; 13823 } else { 13824 newLastBaseUpdate = newLastBaseUpdate.next = clone; 13825 } // Update the remaining priority in the queue. 13826 13827 13828 newLanes = mergeLanes(newLanes, updateLane); 13829 } else { 13830 // This update does have sufficient priority. 13831 if (newLastBaseUpdate !== null) { 13832 var _clone = { 13833 eventTime: updateEventTime, 13834 // This update is going to be committed so we never want uncommit 13835 // it. Using NoLane works because 0 is a subset of all bitmasks, so 13836 // this will never be skipped by the check above. 13837 lane: NoLane, 13838 tag: update.tag, 13839 payload: update.payload, 13840 callback: update.callback, 13841 next: null 13842 }; 13843 newLastBaseUpdate = newLastBaseUpdate.next = _clone; 13844 } // Process this update. 13845 13846 13847 newState = getStateFromUpdate(workInProgress, queue, update, newState, props, instance); 13848 var callback = update.callback; 13849 13850 if (callback !== null && // If the update was already committed, we should not queue its 13851 // callback again. 13852 update.lane !== NoLane) { 13853 workInProgress.flags |= Callback; 13854 var effects = queue.effects; 13855 13856 if (effects === null) { 13857 queue.effects = [update]; 13858 } else { 13859 effects.push(update); 13860 } 13861 } 13862 } 13863 13864 update = update.next; 13865 13866 if (update === null) { 13867 pendingQueue = queue.shared.pending; 13868 13869 if (pendingQueue === null) { 13870 break; 13871 } else { 13872 // An update was scheduled from inside a reducer. Add the new 13873 // pending updates to the end of the list and keep processing. 13874 var _lastPendingUpdate = pendingQueue; // Intentionally unsound. Pending updates form a circular list, but we 13875 // unravel them when transferring them to the base queue. 13876 13877 var _firstPendingUpdate = _lastPendingUpdate.next; 13878 _lastPendingUpdate.next = null; 13879 update = _firstPendingUpdate; 13880 queue.lastBaseUpdate = _lastPendingUpdate; 13881 queue.shared.pending = null; 13882 } 13883 } 13884 } while (true); 13885 13886 if (newLastBaseUpdate === null) { 13887 newBaseState = newState; 13888 } 13889 13890 queue.baseState = newBaseState; 13891 queue.firstBaseUpdate = newFirstBaseUpdate; 13892 queue.lastBaseUpdate = newLastBaseUpdate; // Interleaved updates are stored on a separate queue. We aren't going to 13893 // process them during this render, but we do need to track which lanes 13894 // are remaining. 13895 13896 var lastInterleaved = queue.shared.interleaved; 13897 13898 if (lastInterleaved !== null) { 13899 var interleaved = lastInterleaved; 13900 13901 do { 13902 newLanes = mergeLanes(newLanes, interleaved.lane); 13903 interleaved = interleaved.next; 13904 } while (interleaved !== lastInterleaved); 13905 } else if (firstBaseUpdate === null) { 13906 // `queue.lanes` is used for entangling transitions. We can set it back to 13907 // zero once the queue is empty. 13908 queue.shared.lanes = NoLanes; 13909 } // Set the remaining expiration time to be whatever is remaining in the queue. 13910 // This should be fine because the only two other things that contribute to 13911 // expiration time are props and context. We're already in the middle of the 13912 // begin phase by the time we start processing the queue, so we've already 13913 // dealt with the props. Context in components that specify 13914 // shouldComponentUpdate is tricky; but we'll have to account for 13915 // that regardless. 13916 13917 13918 markSkippedUpdateLanes(newLanes); 13919 workInProgress.lanes = newLanes; 13920 workInProgress.memoizedState = newState; 13921 } 13922 13923 { 13924 currentlyProcessingQueue = null; 13925 } 13926 } 13927 13928 function callCallback(callback, context) { 13929 if (typeof callback !== 'function') { 13930 throw new Error('Invalid argument passed as callback. Expected a function. Instead ' + ("received: " + callback)); 13931 } 13932 13933 callback.call(context); 13934 } 13935 13936 function resetHasForceUpdateBeforeProcessing() { 13937 hasForceUpdate = false; 13938 } 13939 function checkHasForceUpdateAfterProcessing() { 13940 return hasForceUpdate; 13941 } 13942 function commitUpdateQueue(finishedWork, finishedQueue, instance) { 13943 // Commit the effects 13944 var effects = finishedQueue.effects; 13945 finishedQueue.effects = null; 13946 13947 if (effects !== null) { 13948 for (var i = 0; i < effects.length; i++) { 13949 var effect = effects[i]; 13950 var callback = effect.callback; 13951 13952 if (callback !== null) { 13953 effect.callback = null; 13954 callCallback(callback, instance); 13955 } 13956 } 13957 } 13958 } 13959 13960 var fakeInternalInstance = {}; // React.Component uses a shared frozen object by default. 13961 // We'll use it to determine whether we need to initialize legacy refs. 13962 13963 var emptyRefsObject = new React.Component().refs; 13964 var didWarnAboutStateAssignmentForComponent; 13965 var didWarnAboutUninitializedState; 13966 var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; 13967 var didWarnAboutLegacyLifecyclesAndDerivedState; 13968 var didWarnAboutUndefinedDerivedState; 13969 var warnOnUndefinedDerivedState; 13970 var warnOnInvalidCallback; 13971 var didWarnAboutDirectlyAssigningPropsToState; 13972 var didWarnAboutContextTypeAndContextTypes; 13973 var didWarnAboutInvalidateContextType; 13974 13975 { 13976 didWarnAboutStateAssignmentForComponent = new Set(); 13977 didWarnAboutUninitializedState = new Set(); 13978 didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); 13979 didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); 13980 didWarnAboutDirectlyAssigningPropsToState = new Set(); 13981 didWarnAboutUndefinedDerivedState = new Set(); 13982 didWarnAboutContextTypeAndContextTypes = new Set(); 13983 didWarnAboutInvalidateContextType = new Set(); 13984 var didWarnOnInvalidCallback = new Set(); 13985 13986 warnOnInvalidCallback = function (callback, callerName) { 13987 if (callback === null || typeof callback === 'function') { 13988 return; 13989 } 13990 13991 var key = callerName + '_' + callback; 13992 13993 if (!didWarnOnInvalidCallback.has(key)) { 13994 didWarnOnInvalidCallback.add(key); 13995 13996 error('%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback); 13997 } 13998 }; 13999 14000 warnOnUndefinedDerivedState = function (type, partialState) { 14001 if (partialState === undefined) { 14002 var componentName = getComponentNameFromType(type) || 'Component'; 14003 14004 if (!didWarnAboutUndefinedDerivedState.has(componentName)) { 14005 didWarnAboutUndefinedDerivedState.add(componentName); 14006 14007 error('%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' + 'You have returned undefined.', componentName); 14008 } 14009 } 14010 }; // This is so gross but it's at least non-critical and can be removed if 14011 // it causes problems. This is meant to give a nicer error message for 14012 // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, 14013 // ...)) which otherwise throws a "_processChildContext is not a function" 14014 // exception. 14015 14016 14017 Object.defineProperty(fakeInternalInstance, '_processChildContext', { 14018 enumerable: false, 14019 value: function () { 14020 throw new Error('_processChildContext is not available in React 16+. This likely ' + 'means you have multiple copies of React and are attempting to nest ' + 'a React 15 tree inside a React 16 tree using ' + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " + 'to make sure you have only one copy of React (and ideally, switch ' + 'to ReactDOM.createPortal).'); 14021 } 14022 }); 14023 Object.freeze(fakeInternalInstance); 14024 } 14025 14026 function applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, nextProps) { 14027 var prevState = workInProgress.memoizedState; 14028 var partialState = getDerivedStateFromProps(nextProps, prevState); 14029 14030 { 14031 if ( workInProgress.mode & StrictLegacyMode) { 14032 setIsStrictModeForDevtools(true); 14033 14034 try { 14035 // Invoke the function an extra time to help detect side-effects. 14036 partialState = getDerivedStateFromProps(nextProps, prevState); 14037 } finally { 14038 setIsStrictModeForDevtools(false); 14039 } 14040 } 14041 14042 warnOnUndefinedDerivedState(ctor, partialState); 14043 } // Merge the partial state and the previous state. 14044 14045 14046 var memoizedState = partialState === null || partialState === undefined ? prevState : assign({}, prevState, partialState); 14047 workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the 14048 // base state. 14049 14050 if (workInProgress.lanes === NoLanes) { 14051 // Queue is always non-null for classes 14052 var updateQueue = workInProgress.updateQueue; 14053 updateQueue.baseState = memoizedState; 14054 } 14055 } 14056 14057 var classComponentUpdater = { 14058 isMounted: isMounted, 14059 enqueueSetState: function (inst, payload, callback) { 14060 var fiber = get(inst); 14061 var eventTime = requestEventTime(); 14062 var lane = requestUpdateLane(fiber); 14063 var update = createUpdate(eventTime, lane); 14064 update.payload = payload; 14065 14066 if (callback !== undefined && callback !== null) { 14067 { 14068 warnOnInvalidCallback(callback, 'setState'); 14069 } 14070 14071 update.callback = callback; 14072 } 14073 14074 var root = enqueueUpdate(fiber, update, lane); 14075 14076 if (root !== null) { 14077 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 14078 entangleTransitions(root, fiber, lane); 14079 } 14080 14081 { 14082 markStateUpdateScheduled(fiber, lane); 14083 } 14084 }, 14085 enqueueReplaceState: function (inst, payload, callback) { 14086 var fiber = get(inst); 14087 var eventTime = requestEventTime(); 14088 var lane = requestUpdateLane(fiber); 14089 var update = createUpdate(eventTime, lane); 14090 update.tag = ReplaceState; 14091 update.payload = payload; 14092 14093 if (callback !== undefined && callback !== null) { 14094 { 14095 warnOnInvalidCallback(callback, 'replaceState'); 14096 } 14097 14098 update.callback = callback; 14099 } 14100 14101 var root = enqueueUpdate(fiber, update, lane); 14102 14103 if (root !== null) { 14104 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 14105 entangleTransitions(root, fiber, lane); 14106 } 14107 14108 { 14109 markStateUpdateScheduled(fiber, lane); 14110 } 14111 }, 14112 enqueueForceUpdate: function (inst, callback) { 14113 var fiber = get(inst); 14114 var eventTime = requestEventTime(); 14115 var lane = requestUpdateLane(fiber); 14116 var update = createUpdate(eventTime, lane); 14117 update.tag = ForceUpdate; 14118 14119 if (callback !== undefined && callback !== null) { 14120 { 14121 warnOnInvalidCallback(callback, 'forceUpdate'); 14122 } 14123 14124 update.callback = callback; 14125 } 14126 14127 var root = enqueueUpdate(fiber, update, lane); 14128 14129 if (root !== null) { 14130 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 14131 entangleTransitions(root, fiber, lane); 14132 } 14133 14134 { 14135 markForceUpdateScheduled(fiber, lane); 14136 } 14137 } 14138 }; 14139 14140 function checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext) { 14141 var instance = workInProgress.stateNode; 14142 14143 if (typeof instance.shouldComponentUpdate === 'function') { 14144 var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, nextContext); 14145 14146 { 14147 if ( workInProgress.mode & StrictLegacyMode) { 14148 setIsStrictModeForDevtools(true); 14149 14150 try { 14151 // Invoke the function an extra time to help detect side-effects. 14152 shouldUpdate = instance.shouldComponentUpdate(newProps, newState, nextContext); 14153 } finally { 14154 setIsStrictModeForDevtools(false); 14155 } 14156 } 14157 14158 if (shouldUpdate === undefined) { 14159 error('%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentNameFromType(ctor) || 'Component'); 14160 } 14161 } 14162 14163 return shouldUpdate; 14164 } 14165 14166 if (ctor.prototype && ctor.prototype.isPureReactComponent) { 14167 return !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState); 14168 } 14169 14170 return true; 14171 } 14172 14173 function checkClassInstance(workInProgress, ctor, newProps) { 14174 var instance = workInProgress.stateNode; 14175 14176 { 14177 var name = getComponentNameFromType(ctor) || 'Component'; 14178 var renderPresent = instance.render; 14179 14180 if (!renderPresent) { 14181 if (ctor.prototype && typeof ctor.prototype.render === 'function') { 14182 error('%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name); 14183 } else { 14184 error('%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name); 14185 } 14186 } 14187 14188 if (instance.getInitialState && !instance.getInitialState.isReactClassApproved && !instance.state) { 14189 error('getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', name); 14190 } 14191 14192 if (instance.getDefaultProps && !instance.getDefaultProps.isReactClassApproved) { 14193 error('getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', name); 14194 } 14195 14196 if (instance.propTypes) { 14197 error('propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name); 14198 } 14199 14200 if (instance.contextType) { 14201 error('contextType was defined as an instance property on %s. Use a static ' + 'property to define contextType instead.', name); 14202 } 14203 14204 { 14205 if (instance.contextTypes) { 14206 error('contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name); 14207 } 14208 14209 if (ctor.contextType && ctor.contextTypes && !didWarnAboutContextTypeAndContextTypes.has(ctor)) { 14210 didWarnAboutContextTypeAndContextTypes.add(ctor); 14211 14212 error('%s declares both contextTypes and contextType static properties. ' + 'The legacy contextTypes property will be ignored.', name); 14213 } 14214 } 14215 14216 if (typeof instance.componentShouldUpdate === 'function') { 14217 error('%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', name); 14218 } 14219 14220 if (ctor.prototype && ctor.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') { 14221 error('%s has a method called shouldComponentUpdate(). ' + 'shouldComponentUpdate should not be used when extending React.PureComponent. ' + 'Please extend React.Component if shouldComponentUpdate is used.', getComponentNameFromType(ctor) || 'A pure component'); 14222 } 14223 14224 if (typeof instance.componentDidUnmount === 'function') { 14225 error('%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name); 14226 } 14227 14228 if (typeof instance.componentDidReceiveProps === 'function') { 14229 error('%s has a method called ' + 'componentDidReceiveProps(). But there is no such lifecycle method. ' + 'If you meant to update the state in response to changing props, ' + 'use componentWillReceiveProps(). If you meant to fetch data or ' + 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().', name); 14230 } 14231 14232 if (typeof instance.componentWillRecieveProps === 'function') { 14233 error('%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name); 14234 } 14235 14236 if (typeof instance.UNSAFE_componentWillRecieveProps === 'function') { 14237 error('%s has a method called ' + 'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?', name); 14238 } 14239 14240 var hasMutatedProps = instance.props !== newProps; 14241 14242 if (instance.props !== undefined && hasMutatedProps) { 14243 error('%s(...): When calling super() in `%s`, make sure to pass ' + "up the same props that your component's constructor was passed.", name, name); 14244 } 14245 14246 if (instance.defaultProps) { 14247 error('Setting defaultProps as an instance property on %s is not supported and will be ignored.' + ' Instead, define defaultProps as a static property on %s.', name, name); 14248 } 14249 14250 if (typeof instance.getSnapshotBeforeUpdate === 'function' && typeof instance.componentDidUpdate !== 'function' && !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor)) { 14251 didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); 14252 14253 error('%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' + 'This component defines getSnapshotBeforeUpdate() only.', getComponentNameFromType(ctor)); 14254 } 14255 14256 if (typeof instance.getDerivedStateFromProps === 'function') { 14257 error('%s: getDerivedStateFromProps() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name); 14258 } 14259 14260 if (typeof instance.getDerivedStateFromError === 'function') { 14261 error('%s: getDerivedStateFromError() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name); 14262 } 14263 14264 if (typeof ctor.getSnapshotBeforeUpdate === 'function') { 14265 error('%s: getSnapshotBeforeUpdate() is defined as a static method ' + 'and will be ignored. Instead, declare it as an instance method.', name); 14266 } 14267 14268 var _state = instance.state; 14269 14270 if (_state && (typeof _state !== 'object' || isArray(_state))) { 14271 error('%s.state: must be set to an object or null', name); 14272 } 14273 14274 if (typeof instance.getChildContext === 'function' && typeof ctor.childContextTypes !== 'object') { 14275 error('%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', name); 14276 } 14277 } 14278 } 14279 14280 function adoptClassInstance(workInProgress, instance) { 14281 instance.updater = classComponentUpdater; 14282 workInProgress.stateNode = instance; // The instance needs access to the fiber so that it can schedule updates 14283 14284 set(instance, workInProgress); 14285 14286 { 14287 instance._reactInternalInstance = fakeInternalInstance; 14288 } 14289 } 14290 14291 function constructClassInstance(workInProgress, ctor, props) { 14292 var isLegacyContextConsumer = false; 14293 var unmaskedContext = emptyContextObject; 14294 var context = emptyContextObject; 14295 var contextType = ctor.contextType; 14296 14297 { 14298 if ('contextType' in ctor) { 14299 var isValid = // Allow null for conditional declaration 14300 contextType === null || contextType !== undefined && contextType.$$typeof === REACT_CONTEXT_TYPE && contextType._context === undefined; // Not a <Context.Consumer> 14301 14302 if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) { 14303 didWarnAboutInvalidateContextType.add(ctor); 14304 var addendum = ''; 14305 14306 if (contextType === undefined) { 14307 addendum = ' However, it is set to undefined. ' + 'This can be caused by a typo or by mixing up named and default imports. ' + 'This can also happen due to a circular dependency, so ' + 'try moving the createContext() call to a separate file.'; 14308 } else if (typeof contextType !== 'object') { 14309 addendum = ' However, it is set to a ' + typeof contextType + '.'; 14310 } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) { 14311 addendum = ' Did you accidentally pass the Context.Provider instead?'; 14312 } else if (contextType._context !== undefined) { 14313 // <Context.Consumer> 14314 addendum = ' Did you accidentally pass the Context.Consumer instead?'; 14315 } else { 14316 addendum = ' However, it is set to an object with keys {' + Object.keys(contextType).join(', ') + '}.'; 14317 } 14318 14319 error('%s defines an invalid contextType. ' + 'contextType should point to the Context object returned by React.createContext().%s', getComponentNameFromType(ctor) || 'Component', addendum); 14320 } 14321 } 14322 } 14323 14324 if (typeof contextType === 'object' && contextType !== null) { 14325 context = readContext(contextType); 14326 } else { 14327 unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); 14328 var contextTypes = ctor.contextTypes; 14329 isLegacyContextConsumer = contextTypes !== null && contextTypes !== undefined; 14330 context = isLegacyContextConsumer ? getMaskedContext(workInProgress, unmaskedContext) : emptyContextObject; 14331 } 14332 14333 var instance = new ctor(props, context); // Instantiate twice to help detect side-effects. 14334 14335 { 14336 if ( workInProgress.mode & StrictLegacyMode) { 14337 setIsStrictModeForDevtools(true); 14338 14339 try { 14340 instance = new ctor(props, context); // eslint-disable-line no-new 14341 } finally { 14342 setIsStrictModeForDevtools(false); 14343 } 14344 } 14345 } 14346 14347 var state = workInProgress.memoizedState = instance.state !== null && instance.state !== undefined ? instance.state : null; 14348 adoptClassInstance(workInProgress, instance); 14349 14350 { 14351 if (typeof ctor.getDerivedStateFromProps === 'function' && state === null) { 14352 var componentName = getComponentNameFromType(ctor) || 'Component'; 14353 14354 if (!didWarnAboutUninitializedState.has(componentName)) { 14355 didWarnAboutUninitializedState.add(componentName); 14356 14357 error('`%s` uses `getDerivedStateFromProps` but its initial state is ' + '%s. This is not recommended. Instead, define the initial state by ' + 'assigning an object to `this.state` in the constructor of `%s`. ' + 'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.', componentName, instance.state === null ? 'null' : 'undefined', componentName); 14358 } 14359 } // If new component APIs are defined, "unsafe" lifecycles won't be called. 14360 // Warn about these lifecycles if they are present. 14361 // Don't warn about react-lifecycles-compat polyfilled methods though. 14362 14363 14364 if (typeof ctor.getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function') { 14365 var foundWillMountName = null; 14366 var foundWillReceivePropsName = null; 14367 var foundWillUpdateName = null; 14368 14369 if (typeof instance.componentWillMount === 'function' && instance.componentWillMount.__suppressDeprecationWarning !== true) { 14370 foundWillMountName = 'componentWillMount'; 14371 } else if (typeof instance.UNSAFE_componentWillMount === 'function') { 14372 foundWillMountName = 'UNSAFE_componentWillMount'; 14373 } 14374 14375 if (typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) { 14376 foundWillReceivePropsName = 'componentWillReceiveProps'; 14377 } else if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') { 14378 foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps'; 14379 } 14380 14381 if (typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true) { 14382 foundWillUpdateName = 'componentWillUpdate'; 14383 } else if (typeof instance.UNSAFE_componentWillUpdate === 'function') { 14384 foundWillUpdateName = 'UNSAFE_componentWillUpdate'; 14385 } 14386 14387 if (foundWillMountName !== null || foundWillReceivePropsName !== null || foundWillUpdateName !== null) { 14388 var _componentName = getComponentNameFromType(ctor) || 'Component'; 14389 14390 var newApiName = typeof ctor.getDerivedStateFromProps === 'function' ? 'getDerivedStateFromProps()' : 'getSnapshotBeforeUpdate()'; 14391 14392 if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { 14393 didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); 14394 14395 error('Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' + '%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' + 'The above lifecycles should be removed. Learn more about this warning here:\n' + 'https://reactjs.org/link/unsafe-component-lifecycles', _componentName, newApiName, foundWillMountName !== null ? "\n " + foundWillMountName : '', foundWillReceivePropsName !== null ? "\n " + foundWillReceivePropsName : '', foundWillUpdateName !== null ? "\n " + foundWillUpdateName : ''); 14396 } 14397 } 14398 } 14399 } // Cache unmasked context so we can avoid recreating masked context unless necessary. 14400 // ReactFiberContext usually updates this cache but can't for newly-created instances. 14401 14402 14403 if (isLegacyContextConsumer) { 14404 cacheContext(workInProgress, unmaskedContext, context); 14405 } 14406 14407 return instance; 14408 } 14409 14410 function callComponentWillMount(workInProgress, instance) { 14411 var oldState = instance.state; 14412 14413 if (typeof instance.componentWillMount === 'function') { 14414 instance.componentWillMount(); 14415 } 14416 14417 if (typeof instance.UNSAFE_componentWillMount === 'function') { 14418 instance.UNSAFE_componentWillMount(); 14419 } 14420 14421 if (oldState !== instance.state) { 14422 { 14423 error('%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentNameFromFiber(workInProgress) || 'Component'); 14424 } 14425 14426 classComponentUpdater.enqueueReplaceState(instance, instance.state, null); 14427 } 14428 } 14429 14430 function callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext) { 14431 var oldState = instance.state; 14432 14433 if (typeof instance.componentWillReceiveProps === 'function') { 14434 instance.componentWillReceiveProps(newProps, nextContext); 14435 } 14436 14437 if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') { 14438 instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); 14439 } 14440 14441 if (instance.state !== oldState) { 14442 { 14443 var componentName = getComponentNameFromFiber(workInProgress) || 'Component'; 14444 14445 if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { 14446 didWarnAboutStateAssignmentForComponent.add(componentName); 14447 14448 error('%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', componentName); 14449 } 14450 } 14451 14452 classComponentUpdater.enqueueReplaceState(instance, instance.state, null); 14453 } 14454 } // Invokes the mount life-cycles on a previously never rendered instance. 14455 14456 14457 function mountClassInstance(workInProgress, ctor, newProps, renderLanes) { 14458 { 14459 checkClassInstance(workInProgress, ctor, newProps); 14460 } 14461 14462 var instance = workInProgress.stateNode; 14463 instance.props = newProps; 14464 instance.state = workInProgress.memoizedState; 14465 instance.refs = emptyRefsObject; 14466 initializeUpdateQueue(workInProgress); 14467 var contextType = ctor.contextType; 14468 14469 if (typeof contextType === 'object' && contextType !== null) { 14470 instance.context = readContext(contextType); 14471 } else { 14472 var unmaskedContext = getUnmaskedContext(workInProgress, ctor, true); 14473 instance.context = getMaskedContext(workInProgress, unmaskedContext); 14474 } 14475 14476 { 14477 if (instance.state === newProps) { 14478 var componentName = getComponentNameFromType(ctor) || 'Component'; 14479 14480 if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { 14481 didWarnAboutDirectlyAssigningPropsToState.add(componentName); 14482 14483 error('%s: It is not recommended to assign props directly to state ' + "because updates to props won't be reflected in state. " + 'In most cases, it is better to use props directly.', componentName); 14484 } 14485 } 14486 14487 if (workInProgress.mode & StrictLegacyMode) { 14488 ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, instance); 14489 } 14490 14491 { 14492 ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(workInProgress, instance); 14493 } 14494 } 14495 14496 instance.state = workInProgress.memoizedState; 14497 var getDerivedStateFromProps = ctor.getDerivedStateFromProps; 14498 14499 if (typeof getDerivedStateFromProps === 'function') { 14500 applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps); 14501 instance.state = workInProgress.memoizedState; 14502 } // In order to support react-lifecycles-compat polyfilled components, 14503 // Unsafe lifecycles should not be invoked for components using the new APIs. 14504 14505 14506 if (typeof ctor.getDerivedStateFromProps !== 'function' && typeof instance.getSnapshotBeforeUpdate !== 'function' && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) { 14507 callComponentWillMount(workInProgress, instance); // If we had additional state updates during this life-cycle, let's 14508 // process them now. 14509 14510 processUpdateQueue(workInProgress, newProps, instance, renderLanes); 14511 instance.state = workInProgress.memoizedState; 14512 } 14513 14514 if (typeof instance.componentDidMount === 'function') { 14515 var fiberFlags = Update; 14516 14517 { 14518 fiberFlags |= LayoutStatic; 14519 } 14520 14521 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 14522 fiberFlags |= MountLayoutDev; 14523 } 14524 14525 workInProgress.flags |= fiberFlags; 14526 } 14527 } 14528 14529 function resumeMountClassInstance(workInProgress, ctor, newProps, renderLanes) { 14530 var instance = workInProgress.stateNode; 14531 var oldProps = workInProgress.memoizedProps; 14532 instance.props = oldProps; 14533 var oldContext = instance.context; 14534 var contextType = ctor.contextType; 14535 var nextContext = emptyContextObject; 14536 14537 if (typeof contextType === 'object' && contextType !== null) { 14538 nextContext = readContext(contextType); 14539 } else { 14540 var nextLegacyUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true); 14541 nextContext = getMaskedContext(workInProgress, nextLegacyUnmaskedContext); 14542 } 14543 14544 var getDerivedStateFromProps = ctor.getDerivedStateFromProps; 14545 var hasNewLifecycles = typeof getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function'; // Note: During these life-cycles, instance.props/instance.state are what 14546 // ever the previously attempted to render - not the "current". However, 14547 // during componentDidUpdate we pass the "current" props. 14548 // In order to support react-lifecycles-compat polyfilled components, 14549 // Unsafe lifecycles should not be invoked for components using the new APIs. 14550 14551 if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === 'function' || typeof instance.componentWillReceiveProps === 'function')) { 14552 if (oldProps !== newProps || oldContext !== nextContext) { 14553 callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext); 14554 } 14555 } 14556 14557 resetHasForceUpdateBeforeProcessing(); 14558 var oldState = workInProgress.memoizedState; 14559 var newState = instance.state = oldState; 14560 processUpdateQueue(workInProgress, newProps, instance, renderLanes); 14561 newState = workInProgress.memoizedState; 14562 14563 if (oldProps === newProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing()) { 14564 // If an update was already in progress, we should schedule an Update 14565 // effect even though we're bailing out, so that cWU/cDU are called. 14566 if (typeof instance.componentDidMount === 'function') { 14567 var fiberFlags = Update; 14568 14569 { 14570 fiberFlags |= LayoutStatic; 14571 } 14572 14573 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 14574 fiberFlags |= MountLayoutDev; 14575 } 14576 14577 workInProgress.flags |= fiberFlags; 14578 } 14579 14580 return false; 14581 } 14582 14583 if (typeof getDerivedStateFromProps === 'function') { 14584 applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps); 14585 newState = workInProgress.memoizedState; 14586 } 14587 14588 var shouldUpdate = checkHasForceUpdateAfterProcessing() || checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext); 14589 14590 if (shouldUpdate) { 14591 // In order to support react-lifecycles-compat polyfilled components, 14592 // Unsafe lifecycles should not be invoked for components using the new APIs. 14593 if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) { 14594 if (typeof instance.componentWillMount === 'function') { 14595 instance.componentWillMount(); 14596 } 14597 14598 if (typeof instance.UNSAFE_componentWillMount === 'function') { 14599 instance.UNSAFE_componentWillMount(); 14600 } 14601 } 14602 14603 if (typeof instance.componentDidMount === 'function') { 14604 var _fiberFlags = Update; 14605 14606 { 14607 _fiberFlags |= LayoutStatic; 14608 } 14609 14610 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 14611 _fiberFlags |= MountLayoutDev; 14612 } 14613 14614 workInProgress.flags |= _fiberFlags; 14615 } 14616 } else { 14617 // If an update was already in progress, we should schedule an Update 14618 // effect even though we're bailing out, so that cWU/cDU are called. 14619 if (typeof instance.componentDidMount === 'function') { 14620 var _fiberFlags2 = Update; 14621 14622 { 14623 _fiberFlags2 |= LayoutStatic; 14624 } 14625 14626 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 14627 _fiberFlags2 |= MountLayoutDev; 14628 } 14629 14630 workInProgress.flags |= _fiberFlags2; 14631 } // If shouldComponentUpdate returned false, we should still update the 14632 // memoized state to indicate that this work can be reused. 14633 14634 14635 workInProgress.memoizedProps = newProps; 14636 workInProgress.memoizedState = newState; 14637 } // Update the existing instance's state, props, and context pointers even 14638 // if shouldComponentUpdate returns false. 14639 14640 14641 instance.props = newProps; 14642 instance.state = newState; 14643 instance.context = nextContext; 14644 return shouldUpdate; 14645 } // Invokes the update life-cycles and returns false if it shouldn't rerender. 14646 14647 14648 function updateClassInstance(current, workInProgress, ctor, newProps, renderLanes) { 14649 var instance = workInProgress.stateNode; 14650 cloneUpdateQueue(current, workInProgress); 14651 var unresolvedOldProps = workInProgress.memoizedProps; 14652 var oldProps = workInProgress.type === workInProgress.elementType ? unresolvedOldProps : resolveDefaultProps(workInProgress.type, unresolvedOldProps); 14653 instance.props = oldProps; 14654 var unresolvedNewProps = workInProgress.pendingProps; 14655 var oldContext = instance.context; 14656 var contextType = ctor.contextType; 14657 var nextContext = emptyContextObject; 14658 14659 if (typeof contextType === 'object' && contextType !== null) { 14660 nextContext = readContext(contextType); 14661 } else { 14662 var nextUnmaskedContext = getUnmaskedContext(workInProgress, ctor, true); 14663 nextContext = getMaskedContext(workInProgress, nextUnmaskedContext); 14664 } 14665 14666 var getDerivedStateFromProps = ctor.getDerivedStateFromProps; 14667 var hasNewLifecycles = typeof getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function'; // Note: During these life-cycles, instance.props/instance.state are what 14668 // ever the previously attempted to render - not the "current". However, 14669 // during componentDidUpdate we pass the "current" props. 14670 // In order to support react-lifecycles-compat polyfilled components, 14671 // Unsafe lifecycles should not be invoked for components using the new APIs. 14672 14673 if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillReceiveProps === 'function' || typeof instance.componentWillReceiveProps === 'function')) { 14674 if (unresolvedOldProps !== unresolvedNewProps || oldContext !== nextContext) { 14675 callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext); 14676 } 14677 } 14678 14679 resetHasForceUpdateBeforeProcessing(); 14680 var oldState = workInProgress.memoizedState; 14681 var newState = instance.state = oldState; 14682 processUpdateQueue(workInProgress, newProps, instance, renderLanes); 14683 newState = workInProgress.memoizedState; 14684 14685 if (unresolvedOldProps === unresolvedNewProps && oldState === newState && !hasContextChanged() && !checkHasForceUpdateAfterProcessing() && !(enableLazyContextPropagation )) { 14686 // If an update was already in progress, we should schedule an Update 14687 // effect even though we're bailing out, so that cWU/cDU are called. 14688 if (typeof instance.componentDidUpdate === 'function') { 14689 if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) { 14690 workInProgress.flags |= Update; 14691 } 14692 } 14693 14694 if (typeof instance.getSnapshotBeforeUpdate === 'function') { 14695 if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) { 14696 workInProgress.flags |= Snapshot; 14697 } 14698 } 14699 14700 return false; 14701 } 14702 14703 if (typeof getDerivedStateFromProps === 'function') { 14704 applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, newProps); 14705 newState = workInProgress.memoizedState; 14706 } 14707 14708 var shouldUpdate = checkHasForceUpdateAfterProcessing() || checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext) || // TODO: In some cases, we'll end up checking if context has changed twice, 14709 // both before and after `shouldComponentUpdate` has been called. Not ideal, 14710 // but I'm loath to refactor this function. This only happens for memoized 14711 // components so it's not that common. 14712 enableLazyContextPropagation ; 14713 14714 if (shouldUpdate) { 14715 // In order to support react-lifecycles-compat polyfilled components, 14716 // Unsafe lifecycles should not be invoked for components using the new APIs. 14717 if (!hasNewLifecycles && (typeof instance.UNSAFE_componentWillUpdate === 'function' || typeof instance.componentWillUpdate === 'function')) { 14718 if (typeof instance.componentWillUpdate === 'function') { 14719 instance.componentWillUpdate(newProps, newState, nextContext); 14720 } 14721 14722 if (typeof instance.UNSAFE_componentWillUpdate === 'function') { 14723 instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); 14724 } 14725 } 14726 14727 if (typeof instance.componentDidUpdate === 'function') { 14728 workInProgress.flags |= Update; 14729 } 14730 14731 if (typeof instance.getSnapshotBeforeUpdate === 'function') { 14732 workInProgress.flags |= Snapshot; 14733 } 14734 } else { 14735 // If an update was already in progress, we should schedule an Update 14736 // effect even though we're bailing out, so that cWU/cDU are called. 14737 if (typeof instance.componentDidUpdate === 'function') { 14738 if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) { 14739 workInProgress.flags |= Update; 14740 } 14741 } 14742 14743 if (typeof instance.getSnapshotBeforeUpdate === 'function') { 14744 if (unresolvedOldProps !== current.memoizedProps || oldState !== current.memoizedState) { 14745 workInProgress.flags |= Snapshot; 14746 } 14747 } // If shouldComponentUpdate returned false, we should still update the 14748 // memoized props/state to indicate that this work can be reused. 14749 14750 14751 workInProgress.memoizedProps = newProps; 14752 workInProgress.memoizedState = newState; 14753 } // Update the existing instance's state, props, and context pointers even 14754 // if shouldComponentUpdate returns false. 14755 14756 14757 instance.props = newProps; 14758 instance.state = newState; 14759 instance.context = nextContext; 14760 return shouldUpdate; 14761 } 14762 14763 var didWarnAboutMaps; 14764 var didWarnAboutGenerators; 14765 var didWarnAboutStringRefs; 14766 var ownerHasKeyUseWarning; 14767 var ownerHasFunctionTypeWarning; 14768 14769 var warnForMissingKey = function (child, returnFiber) {}; 14770 14771 { 14772 didWarnAboutMaps = false; 14773 didWarnAboutGenerators = false; 14774 didWarnAboutStringRefs = {}; 14775 /** 14776 * Warn if there's no key explicitly set on dynamic arrays of children or 14777 * object keys are not valid. This allows us to keep track of children between 14778 * updates. 14779 */ 14780 14781 ownerHasKeyUseWarning = {}; 14782 ownerHasFunctionTypeWarning = {}; 14783 14784 warnForMissingKey = function (child, returnFiber) { 14785 if (child === null || typeof child !== 'object') { 14786 return; 14787 } 14788 14789 if (!child._store || child._store.validated || child.key != null) { 14790 return; 14791 } 14792 14793 if (typeof child._store !== 'object') { 14794 throw new Error('React Component in warnForMissingKey should have a _store. ' + 'This error is likely caused by a bug in React. Please file an issue.'); 14795 } 14796 14797 child._store.validated = true; 14798 var componentName = getComponentNameFromFiber(returnFiber) || 'Component'; 14799 14800 if (ownerHasKeyUseWarning[componentName]) { 14801 return; 14802 } 14803 14804 ownerHasKeyUseWarning[componentName] = true; 14805 14806 error('Each child in a list should have a unique ' + '"key" prop. See https://reactjs.org/link/warning-keys for ' + 'more information.'); 14807 }; 14808 } 14809 14810 function coerceRef(returnFiber, current, element) { 14811 var mixedRef = element.ref; 14812 14813 if (mixedRef !== null && typeof mixedRef !== 'function' && typeof mixedRef !== 'object') { 14814 { 14815 // TODO: Clean this up once we turn on the string ref warning for 14816 // everyone, because the strict mode case will no longer be relevant 14817 if ((returnFiber.mode & StrictLegacyMode || warnAboutStringRefs) && // We warn in ReactElement.js if owner and self are equal for string refs 14818 // because these cannot be automatically converted to an arrow function 14819 // using a codemod. Therefore, we don't have to warn about string refs again. 14820 !(element._owner && element._self && element._owner.stateNode !== element._self)) { 14821 var componentName = getComponentNameFromFiber(returnFiber) || 'Component'; 14822 14823 if (!didWarnAboutStringRefs[componentName]) { 14824 { 14825 error('A string ref, "%s", has been found within a strict mode tree. ' + 'String refs are a source of potential bugs and should be avoided. ' + 'We recommend using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', mixedRef); 14826 } 14827 14828 didWarnAboutStringRefs[componentName] = true; 14829 } 14830 } 14831 } 14832 14833 if (element._owner) { 14834 var owner = element._owner; 14835 var inst; 14836 14837 if (owner) { 14838 var ownerFiber = owner; 14839 14840 if (ownerFiber.tag !== ClassComponent) { 14841 throw new Error('Function components cannot have string refs. ' + 'We recommend using useRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref'); 14842 } 14843 14844 inst = ownerFiber.stateNode; 14845 } 14846 14847 if (!inst) { 14848 throw new Error("Missing owner for string ref " + mixedRef + ". This error is likely caused by a " + 'bug in React. Please file an issue.'); 14849 } // Assigning this to a const so Flow knows it won't change in the closure 14850 14851 14852 var resolvedInst = inst; 14853 14854 { 14855 checkPropStringCoercion(mixedRef, 'ref'); 14856 } 14857 14858 var stringRef = '' + mixedRef; // Check if previous string ref matches new string ref 14859 14860 if (current !== null && current.ref !== null && typeof current.ref === 'function' && current.ref._stringRef === stringRef) { 14861 return current.ref; 14862 } 14863 14864 var ref = function (value) { 14865 var refs = resolvedInst.refs; 14866 14867 if (refs === emptyRefsObject) { 14868 // This is a lazy pooled frozen object, so we need to initialize. 14869 refs = resolvedInst.refs = {}; 14870 } 14871 14872 if (value === null) { 14873 delete refs[stringRef]; 14874 } else { 14875 refs[stringRef] = value; 14876 } 14877 }; 14878 14879 ref._stringRef = stringRef; 14880 return ref; 14881 } else { 14882 if (typeof mixedRef !== 'string') { 14883 throw new Error('Expected ref to be a function, a string, an object returned by React.createRef(), or null.'); 14884 } 14885 14886 if (!element._owner) { 14887 throw new Error("Element ref was specified as a string (" + mixedRef + ") but no owner was set. This could happen for one of" + ' the following reasons:\n' + '1. You may be adding a ref to a function component\n' + "2. You may be adding a ref to a component that was not created inside a component's render method\n" + '3. You have multiple copies of React loaded\n' + 'See https://reactjs.org/link/refs-must-have-owner for more information.'); 14888 } 14889 } 14890 } 14891 14892 return mixedRef; 14893 } 14894 14895 function throwOnInvalidObjectType(returnFiber, newChild) { 14896 var childString = Object.prototype.toString.call(newChild); 14897 throw new Error("Objects are not valid as a React child (found: " + (childString === '[object Object]' ? 'object with keys {' + Object.keys(newChild).join(', ') + '}' : childString) + "). " + 'If you meant to render a collection of children, use an array ' + 'instead.'); 14898 } 14899 14900 function warnOnFunctionType(returnFiber) { 14901 { 14902 var componentName = getComponentNameFromFiber(returnFiber) || 'Component'; 14903 14904 if (ownerHasFunctionTypeWarning[componentName]) { 14905 return; 14906 } 14907 14908 ownerHasFunctionTypeWarning[componentName] = true; 14909 14910 error('Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of <Component /> from render. ' + 'Or maybe you meant to call this function rather than return it.'); 14911 } 14912 } 14913 14914 function resolveLazy(lazyType) { 14915 var payload = lazyType._payload; 14916 var init = lazyType._init; 14917 return init(payload); 14918 } // This wrapper function exists because I expect to clone the code in each path 14919 // to be able to optimize each path individually by branching early. This needs 14920 // a compiler or we can do it manually. Helpers that don't need this branching 14921 // live outside of this function. 14922 14923 14924 function ChildReconciler(shouldTrackSideEffects) { 14925 function deleteChild(returnFiber, childToDelete) { 14926 if (!shouldTrackSideEffects) { 14927 // Noop. 14928 return; 14929 } 14930 14931 var deletions = returnFiber.deletions; 14932 14933 if (deletions === null) { 14934 returnFiber.deletions = [childToDelete]; 14935 returnFiber.flags |= ChildDeletion; 14936 } else { 14937 deletions.push(childToDelete); 14938 } 14939 } 14940 14941 function deleteRemainingChildren(returnFiber, currentFirstChild) { 14942 if (!shouldTrackSideEffects) { 14943 // Noop. 14944 return null; 14945 } // TODO: For the shouldClone case, this could be micro-optimized a bit by 14946 // assuming that after the first child we've already added everything. 14947 14948 14949 var childToDelete = currentFirstChild; 14950 14951 while (childToDelete !== null) { 14952 deleteChild(returnFiber, childToDelete); 14953 childToDelete = childToDelete.sibling; 14954 } 14955 14956 return null; 14957 } 14958 14959 function mapRemainingChildren(returnFiber, currentFirstChild) { 14960 // Add the remaining children to a temporary map so that we can find them by 14961 // keys quickly. Implicit (null) keys get added to this set with their index 14962 // instead. 14963 var existingChildren = new Map(); 14964 var existingChild = currentFirstChild; 14965 14966 while (existingChild !== null) { 14967 if (existingChild.key !== null) { 14968 existingChildren.set(existingChild.key, existingChild); 14969 } else { 14970 existingChildren.set(existingChild.index, existingChild); 14971 } 14972 14973 existingChild = existingChild.sibling; 14974 } 14975 14976 return existingChildren; 14977 } 14978 14979 function useFiber(fiber, pendingProps) { 14980 // We currently set sibling to null and index to 0 here because it is easy 14981 // to forget to do before returning it. E.g. for the single child case. 14982 var clone = createWorkInProgress(fiber, pendingProps); 14983 clone.index = 0; 14984 clone.sibling = null; 14985 return clone; 14986 } 14987 14988 function placeChild(newFiber, lastPlacedIndex, newIndex) { 14989 newFiber.index = newIndex; 14990 14991 if (!shouldTrackSideEffects) { 14992 // During hydration, the useId algorithm needs to know which fibers are 14993 // part of a list of children (arrays, iterators). 14994 newFiber.flags |= Forked; 14995 return lastPlacedIndex; 14996 } 14997 14998 var current = newFiber.alternate; 14999 15000 if (current !== null) { 15001 var oldIndex = current.index; 15002 15003 if (oldIndex < lastPlacedIndex) { 15004 // This is a move. 15005 newFiber.flags |= Placement; 15006 return lastPlacedIndex; 15007 } else { 15008 // This item can stay in place. 15009 return oldIndex; 15010 } 15011 } else { 15012 // This is an insertion. 15013 newFiber.flags |= Placement; 15014 return lastPlacedIndex; 15015 } 15016 } 15017 15018 function placeSingleChild(newFiber) { 15019 // This is simpler for the single child case. We only need to do a 15020 // placement for inserting new children. 15021 if (shouldTrackSideEffects && newFiber.alternate === null) { 15022 newFiber.flags |= Placement; 15023 } 15024 15025 return newFiber; 15026 } 15027 15028 function updateTextNode(returnFiber, current, textContent, lanes) { 15029 if (current === null || current.tag !== HostText) { 15030 // Insert 15031 var created = createFiberFromText(textContent, returnFiber.mode, lanes); 15032 created.return = returnFiber; 15033 return created; 15034 } else { 15035 // Update 15036 var existing = useFiber(current, textContent); 15037 existing.return = returnFiber; 15038 return existing; 15039 } 15040 } 15041 15042 function updateElement(returnFiber, current, element, lanes) { 15043 var elementType = element.type; 15044 15045 if (elementType === REACT_FRAGMENT_TYPE) { 15046 return updateFragment(returnFiber, current, element.props.children, lanes, element.key); 15047 } 15048 15049 if (current !== null) { 15050 if (current.elementType === elementType || ( // Keep this check inline so it only runs on the false path: 15051 isCompatibleFamilyForHotReloading(current, element) ) || // Lazy types should reconcile their resolved type. 15052 // We need to do this after the Hot Reloading check above, 15053 // because hot reloading has different semantics than prod because 15054 // it doesn't resuspend. So we can't let the call below suspend. 15055 typeof elementType === 'object' && elementType !== null && elementType.$$typeof === REACT_LAZY_TYPE && resolveLazy(elementType) === current.type) { 15056 // Move based on index 15057 var existing = useFiber(current, element.props); 15058 existing.ref = coerceRef(returnFiber, current, element); 15059 existing.return = returnFiber; 15060 15061 { 15062 existing._debugSource = element._source; 15063 existing._debugOwner = element._owner; 15064 } 15065 15066 return existing; 15067 } 15068 } // Insert 15069 15070 15071 var created = createFiberFromElement(element, returnFiber.mode, lanes); 15072 created.ref = coerceRef(returnFiber, current, element); 15073 created.return = returnFiber; 15074 return created; 15075 } 15076 15077 function updatePortal(returnFiber, current, portal, lanes) { 15078 if (current === null || current.tag !== HostPortal || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) { 15079 // Insert 15080 var created = createFiberFromPortal(portal, returnFiber.mode, lanes); 15081 created.return = returnFiber; 15082 return created; 15083 } else { 15084 // Update 15085 var existing = useFiber(current, portal.children || []); 15086 existing.return = returnFiber; 15087 return existing; 15088 } 15089 } 15090 15091 function updateFragment(returnFiber, current, fragment, lanes, key) { 15092 if (current === null || current.tag !== Fragment) { 15093 // Insert 15094 var created = createFiberFromFragment(fragment, returnFiber.mode, lanes, key); 15095 created.return = returnFiber; 15096 return created; 15097 } else { 15098 // Update 15099 var existing = useFiber(current, fragment); 15100 existing.return = returnFiber; 15101 return existing; 15102 } 15103 } 15104 15105 function createChild(returnFiber, newChild, lanes) { 15106 if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') { 15107 // Text nodes don't have keys. If the previous node is implicitly keyed 15108 // we can continue to replace it without aborting even if it is not a text 15109 // node. 15110 var created = createFiberFromText('' + newChild, returnFiber.mode, lanes); 15111 created.return = returnFiber; 15112 return created; 15113 } 15114 15115 if (typeof newChild === 'object' && newChild !== null) { 15116 switch (newChild.$$typeof) { 15117 case REACT_ELEMENT_TYPE: 15118 { 15119 var _created = createFiberFromElement(newChild, returnFiber.mode, lanes); 15120 15121 _created.ref = coerceRef(returnFiber, null, newChild); 15122 _created.return = returnFiber; 15123 return _created; 15124 } 15125 15126 case REACT_PORTAL_TYPE: 15127 { 15128 var _created2 = createFiberFromPortal(newChild, returnFiber.mode, lanes); 15129 15130 _created2.return = returnFiber; 15131 return _created2; 15132 } 15133 15134 case REACT_LAZY_TYPE: 15135 { 15136 var payload = newChild._payload; 15137 var init = newChild._init; 15138 return createChild(returnFiber, init(payload), lanes); 15139 } 15140 } 15141 15142 if (isArray(newChild) || getIteratorFn(newChild)) { 15143 var _created3 = createFiberFromFragment(newChild, returnFiber.mode, lanes, null); 15144 15145 _created3.return = returnFiber; 15146 return _created3; 15147 } 15148 15149 throwOnInvalidObjectType(returnFiber, newChild); 15150 } 15151 15152 { 15153 if (typeof newChild === 'function') { 15154 warnOnFunctionType(returnFiber); 15155 } 15156 } 15157 15158 return null; 15159 } 15160 15161 function updateSlot(returnFiber, oldFiber, newChild, lanes) { 15162 // Update the fiber if the keys match, otherwise return null. 15163 var key = oldFiber !== null ? oldFiber.key : null; 15164 15165 if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') { 15166 // Text nodes don't have keys. If the previous node is implicitly keyed 15167 // we can continue to replace it without aborting even if it is not a text 15168 // node. 15169 if (key !== null) { 15170 return null; 15171 } 15172 15173 return updateTextNode(returnFiber, oldFiber, '' + newChild, lanes); 15174 } 15175 15176 if (typeof newChild === 'object' && newChild !== null) { 15177 switch (newChild.$$typeof) { 15178 case REACT_ELEMENT_TYPE: 15179 { 15180 if (newChild.key === key) { 15181 return updateElement(returnFiber, oldFiber, newChild, lanes); 15182 } else { 15183 return null; 15184 } 15185 } 15186 15187 case REACT_PORTAL_TYPE: 15188 { 15189 if (newChild.key === key) { 15190 return updatePortal(returnFiber, oldFiber, newChild, lanes); 15191 } else { 15192 return null; 15193 } 15194 } 15195 15196 case REACT_LAZY_TYPE: 15197 { 15198 var payload = newChild._payload; 15199 var init = newChild._init; 15200 return updateSlot(returnFiber, oldFiber, init(payload), lanes); 15201 } 15202 } 15203 15204 if (isArray(newChild) || getIteratorFn(newChild)) { 15205 if (key !== null) { 15206 return null; 15207 } 15208 15209 return updateFragment(returnFiber, oldFiber, newChild, lanes, null); 15210 } 15211 15212 throwOnInvalidObjectType(returnFiber, newChild); 15213 } 15214 15215 { 15216 if (typeof newChild === 'function') { 15217 warnOnFunctionType(returnFiber); 15218 } 15219 } 15220 15221 return null; 15222 } 15223 15224 function updateFromMap(existingChildren, returnFiber, newIdx, newChild, lanes) { 15225 if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') { 15226 // Text nodes don't have keys, so we neither have to check the old nor 15227 // new node for the key. If both are text nodes, they match. 15228 var matchedFiber = existingChildren.get(newIdx) || null; 15229 return updateTextNode(returnFiber, matchedFiber, '' + newChild, lanes); 15230 } 15231 15232 if (typeof newChild === 'object' && newChild !== null) { 15233 switch (newChild.$$typeof) { 15234 case REACT_ELEMENT_TYPE: 15235 { 15236 var _matchedFiber = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null; 15237 15238 return updateElement(returnFiber, _matchedFiber, newChild, lanes); 15239 } 15240 15241 case REACT_PORTAL_TYPE: 15242 { 15243 var _matchedFiber2 = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null; 15244 15245 return updatePortal(returnFiber, _matchedFiber2, newChild, lanes); 15246 } 15247 15248 case REACT_LAZY_TYPE: 15249 var payload = newChild._payload; 15250 var init = newChild._init; 15251 return updateFromMap(existingChildren, returnFiber, newIdx, init(payload), lanes); 15252 } 15253 15254 if (isArray(newChild) || getIteratorFn(newChild)) { 15255 var _matchedFiber3 = existingChildren.get(newIdx) || null; 15256 15257 return updateFragment(returnFiber, _matchedFiber3, newChild, lanes, null); 15258 } 15259 15260 throwOnInvalidObjectType(returnFiber, newChild); 15261 } 15262 15263 { 15264 if (typeof newChild === 'function') { 15265 warnOnFunctionType(returnFiber); 15266 } 15267 } 15268 15269 return null; 15270 } 15271 /** 15272 * Warns if there is a duplicate or missing key 15273 */ 15274 15275 15276 function warnOnInvalidKey(child, knownKeys, returnFiber) { 15277 { 15278 if (typeof child !== 'object' || child === null) { 15279 return knownKeys; 15280 } 15281 15282 switch (child.$$typeof) { 15283 case REACT_ELEMENT_TYPE: 15284 case REACT_PORTAL_TYPE: 15285 warnForMissingKey(child, returnFiber); 15286 var key = child.key; 15287 15288 if (typeof key !== 'string') { 15289 break; 15290 } 15291 15292 if (knownKeys === null) { 15293 knownKeys = new Set(); 15294 knownKeys.add(key); 15295 break; 15296 } 15297 15298 if (!knownKeys.has(key)) { 15299 knownKeys.add(key); 15300 break; 15301 } 15302 15303 error('Encountered two children with the same key, `%s`. ' + 'Keys should be unique so that components maintain their identity ' + 'across updates. Non-unique keys may cause children to be ' + 'duplicated and/or omitted — the behavior is unsupported and ' + 'could change in a future version.', key); 15304 15305 break; 15306 15307 case REACT_LAZY_TYPE: 15308 var payload = child._payload; 15309 var init = child._init; 15310 warnOnInvalidKey(init(payload), knownKeys, returnFiber); 15311 break; 15312 } 15313 } 15314 15315 return knownKeys; 15316 } 15317 15318 function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, lanes) { 15319 // This algorithm can't optimize by searching from both ends since we 15320 // don't have backpointers on fibers. I'm trying to see how far we can get 15321 // with that model. If it ends up not being worth the tradeoffs, we can 15322 // add it later. 15323 // Even with a two ended optimization, we'd want to optimize for the case 15324 // where there are few changes and brute force the comparison instead of 15325 // going for the Map. It'd like to explore hitting that path first in 15326 // forward-only mode and only go for the Map once we notice that we need 15327 // lots of look ahead. This doesn't handle reversal as well as two ended 15328 // search but that's unusual. Besides, for the two ended optimization to 15329 // work on Iterables, we'd need to copy the whole set. 15330 // In this first iteration, we'll just live with hitting the bad case 15331 // (adding everything to a Map) in for every insert/move. 15332 // If you change this code, also update reconcileChildrenIterator() which 15333 // uses the same algorithm. 15334 { 15335 // First, validate keys. 15336 var knownKeys = null; 15337 15338 for (var i = 0; i < newChildren.length; i++) { 15339 var child = newChildren[i]; 15340 knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); 15341 } 15342 } 15343 15344 var resultingFirstChild = null; 15345 var previousNewFiber = null; 15346 var oldFiber = currentFirstChild; 15347 var lastPlacedIndex = 0; 15348 var newIdx = 0; 15349 var nextOldFiber = null; 15350 15351 for (; oldFiber !== null && newIdx < newChildren.length; newIdx++) { 15352 if (oldFiber.index > newIdx) { 15353 nextOldFiber = oldFiber; 15354 oldFiber = null; 15355 } else { 15356 nextOldFiber = oldFiber.sibling; 15357 } 15358 15359 var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], lanes); 15360 15361 if (newFiber === null) { 15362 // TODO: This breaks on empty slots like null children. That's 15363 // unfortunate because it triggers the slow path all the time. We need 15364 // a better way to communicate whether this was a miss or null, 15365 // boolean, undefined, etc. 15366 if (oldFiber === null) { 15367 oldFiber = nextOldFiber; 15368 } 15369 15370 break; 15371 } 15372 15373 if (shouldTrackSideEffects) { 15374 if (oldFiber && newFiber.alternate === null) { 15375 // We matched the slot, but we didn't reuse the existing fiber, so we 15376 // need to delete the existing child. 15377 deleteChild(returnFiber, oldFiber); 15378 } 15379 } 15380 15381 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); 15382 15383 if (previousNewFiber === null) { 15384 // TODO: Move out of the loop. This only happens for the first run. 15385 resultingFirstChild = newFiber; 15386 } else { 15387 // TODO: Defer siblings if we're not at the right index for this slot. 15388 // I.e. if we had null values before, then we want to defer this 15389 // for each null value. However, we also don't want to call updateSlot 15390 // with the previous one. 15391 previousNewFiber.sibling = newFiber; 15392 } 15393 15394 previousNewFiber = newFiber; 15395 oldFiber = nextOldFiber; 15396 } 15397 15398 if (newIdx === newChildren.length) { 15399 // We've reached the end of the new children. We can delete the rest. 15400 deleteRemainingChildren(returnFiber, oldFiber); 15401 15402 if (getIsHydrating()) { 15403 var numberOfForks = newIdx; 15404 pushTreeFork(returnFiber, numberOfForks); 15405 } 15406 15407 return resultingFirstChild; 15408 } 15409 15410 if (oldFiber === null) { 15411 // If we don't have any more existing children we can choose a fast path 15412 // since the rest will all be insertions. 15413 for (; newIdx < newChildren.length; newIdx++) { 15414 var _newFiber = createChild(returnFiber, newChildren[newIdx], lanes); 15415 15416 if (_newFiber === null) { 15417 continue; 15418 } 15419 15420 lastPlacedIndex = placeChild(_newFiber, lastPlacedIndex, newIdx); 15421 15422 if (previousNewFiber === null) { 15423 // TODO: Move out of the loop. This only happens for the first run. 15424 resultingFirstChild = _newFiber; 15425 } else { 15426 previousNewFiber.sibling = _newFiber; 15427 } 15428 15429 previousNewFiber = _newFiber; 15430 } 15431 15432 if (getIsHydrating()) { 15433 var _numberOfForks = newIdx; 15434 pushTreeFork(returnFiber, _numberOfForks); 15435 } 15436 15437 return resultingFirstChild; 15438 } // Add all children to a key map for quick lookups. 15439 15440 15441 var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. 15442 15443 for (; newIdx < newChildren.length; newIdx++) { 15444 var _newFiber2 = updateFromMap(existingChildren, returnFiber, newIdx, newChildren[newIdx], lanes); 15445 15446 if (_newFiber2 !== null) { 15447 if (shouldTrackSideEffects) { 15448 if (_newFiber2.alternate !== null) { 15449 // The new fiber is a work in progress, but if there exists a 15450 // current, that means that we reused the fiber. We need to delete 15451 // it from the child list so that we don't add it to the deletion 15452 // list. 15453 existingChildren.delete(_newFiber2.key === null ? newIdx : _newFiber2.key); 15454 } 15455 } 15456 15457 lastPlacedIndex = placeChild(_newFiber2, lastPlacedIndex, newIdx); 15458 15459 if (previousNewFiber === null) { 15460 resultingFirstChild = _newFiber2; 15461 } else { 15462 previousNewFiber.sibling = _newFiber2; 15463 } 15464 15465 previousNewFiber = _newFiber2; 15466 } 15467 } 15468 15469 if (shouldTrackSideEffects) { 15470 // Any existing children that weren't consumed above were deleted. We need 15471 // to add them to the deletion list. 15472 existingChildren.forEach(function (child) { 15473 return deleteChild(returnFiber, child); 15474 }); 15475 } 15476 15477 if (getIsHydrating()) { 15478 var _numberOfForks2 = newIdx; 15479 pushTreeFork(returnFiber, _numberOfForks2); 15480 } 15481 15482 return resultingFirstChild; 15483 } 15484 15485 function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildrenIterable, lanes) { 15486 // This is the same implementation as reconcileChildrenArray(), 15487 // but using the iterator instead. 15488 var iteratorFn = getIteratorFn(newChildrenIterable); 15489 15490 if (typeof iteratorFn !== 'function') { 15491 throw new Error('An object is not an iterable. This error is likely caused by a bug in ' + 'React. Please file an issue.'); 15492 } 15493 15494 { 15495 // We don't support rendering Generators because it's a mutation. 15496 // See https://github.com/facebook/react/issues/12995 15497 if (typeof Symbol === 'function' && // $FlowFixMe Flow doesn't know about toStringTag 15498 newChildrenIterable[Symbol.toStringTag] === 'Generator') { 15499 if (!didWarnAboutGenerators) { 15500 error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); 15501 } 15502 15503 didWarnAboutGenerators = true; 15504 } // Warn about using Maps as children 15505 15506 15507 if (newChildrenIterable.entries === iteratorFn) { 15508 if (!didWarnAboutMaps) { 15509 error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); 15510 } 15511 15512 didWarnAboutMaps = true; 15513 } // First, validate keys. 15514 // We'll get a different iterator later for the main pass. 15515 15516 15517 var _newChildren = iteratorFn.call(newChildrenIterable); 15518 15519 if (_newChildren) { 15520 var knownKeys = null; 15521 15522 var _step = _newChildren.next(); 15523 15524 for (; !_step.done; _step = _newChildren.next()) { 15525 var child = _step.value; 15526 knownKeys = warnOnInvalidKey(child, knownKeys, returnFiber); 15527 } 15528 } 15529 } 15530 15531 var newChildren = iteratorFn.call(newChildrenIterable); 15532 15533 if (newChildren == null) { 15534 throw new Error('An iterable object provided no iterator.'); 15535 } 15536 15537 var resultingFirstChild = null; 15538 var previousNewFiber = null; 15539 var oldFiber = currentFirstChild; 15540 var lastPlacedIndex = 0; 15541 var newIdx = 0; 15542 var nextOldFiber = null; 15543 var step = newChildren.next(); 15544 15545 for (; oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { 15546 if (oldFiber.index > newIdx) { 15547 nextOldFiber = oldFiber; 15548 oldFiber = null; 15549 } else { 15550 nextOldFiber = oldFiber.sibling; 15551 } 15552 15553 var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); 15554 15555 if (newFiber === null) { 15556 // TODO: This breaks on empty slots like null children. That's 15557 // unfortunate because it triggers the slow path all the time. We need 15558 // a better way to communicate whether this was a miss or null, 15559 // boolean, undefined, etc. 15560 if (oldFiber === null) { 15561 oldFiber = nextOldFiber; 15562 } 15563 15564 break; 15565 } 15566 15567 if (shouldTrackSideEffects) { 15568 if (oldFiber && newFiber.alternate === null) { 15569 // We matched the slot, but we didn't reuse the existing fiber, so we 15570 // need to delete the existing child. 15571 deleteChild(returnFiber, oldFiber); 15572 } 15573 } 15574 15575 lastPlacedIndex = placeChild(newFiber, lastPlacedIndex, newIdx); 15576 15577 if (previousNewFiber === null) { 15578 // TODO: Move out of the loop. This only happens for the first run. 15579 resultingFirstChild = newFiber; 15580 } else { 15581 // TODO: Defer siblings if we're not at the right index for this slot. 15582 // I.e. if we had null values before, then we want to defer this 15583 // for each null value. However, we also don't want to call updateSlot 15584 // with the previous one. 15585 previousNewFiber.sibling = newFiber; 15586 } 15587 15588 previousNewFiber = newFiber; 15589 oldFiber = nextOldFiber; 15590 } 15591 15592 if (step.done) { 15593 // We've reached the end of the new children. We can delete the rest. 15594 deleteRemainingChildren(returnFiber, oldFiber); 15595 15596 if (getIsHydrating()) { 15597 var numberOfForks = newIdx; 15598 pushTreeFork(returnFiber, numberOfForks); 15599 } 15600 15601 return resultingFirstChild; 15602 } 15603 15604 if (oldFiber === null) { 15605 // If we don't have any more existing children we can choose a fast path 15606 // since the rest will all be insertions. 15607 for (; !step.done; newIdx++, step = newChildren.next()) { 15608 var _newFiber3 = createChild(returnFiber, step.value, lanes); 15609 15610 if (_newFiber3 === null) { 15611 continue; 15612 } 15613 15614 lastPlacedIndex = placeChild(_newFiber3, lastPlacedIndex, newIdx); 15615 15616 if (previousNewFiber === null) { 15617 // TODO: Move out of the loop. This only happens for the first run. 15618 resultingFirstChild = _newFiber3; 15619 } else { 15620 previousNewFiber.sibling = _newFiber3; 15621 } 15622 15623 previousNewFiber = _newFiber3; 15624 } 15625 15626 if (getIsHydrating()) { 15627 var _numberOfForks3 = newIdx; 15628 pushTreeFork(returnFiber, _numberOfForks3); 15629 } 15630 15631 return resultingFirstChild; 15632 } // Add all children to a key map for quick lookups. 15633 15634 15635 var existingChildren = mapRemainingChildren(returnFiber, oldFiber); // Keep scanning and use the map to restore deleted items as moves. 15636 15637 for (; !step.done; newIdx++, step = newChildren.next()) { 15638 var _newFiber4 = updateFromMap(existingChildren, returnFiber, newIdx, step.value, lanes); 15639 15640 if (_newFiber4 !== null) { 15641 if (shouldTrackSideEffects) { 15642 if (_newFiber4.alternate !== null) { 15643 // The new fiber is a work in progress, but if there exists a 15644 // current, that means that we reused the fiber. We need to delete 15645 // it from the child list so that we don't add it to the deletion 15646 // list. 15647 existingChildren.delete(_newFiber4.key === null ? newIdx : _newFiber4.key); 15648 } 15649 } 15650 15651 lastPlacedIndex = placeChild(_newFiber4, lastPlacedIndex, newIdx); 15652 15653 if (previousNewFiber === null) { 15654 resultingFirstChild = _newFiber4; 15655 } else { 15656 previousNewFiber.sibling = _newFiber4; 15657 } 15658 15659 previousNewFiber = _newFiber4; 15660 } 15661 } 15662 15663 if (shouldTrackSideEffects) { 15664 // Any existing children that weren't consumed above were deleted. We need 15665 // to add them to the deletion list. 15666 existingChildren.forEach(function (child) { 15667 return deleteChild(returnFiber, child); 15668 }); 15669 } 15670 15671 if (getIsHydrating()) { 15672 var _numberOfForks4 = newIdx; 15673 pushTreeFork(returnFiber, _numberOfForks4); 15674 } 15675 15676 return resultingFirstChild; 15677 } 15678 15679 function reconcileSingleTextNode(returnFiber, currentFirstChild, textContent, lanes) { 15680 // There's no need to check for keys on text nodes since we don't have a 15681 // way to define them. 15682 if (currentFirstChild !== null && currentFirstChild.tag === HostText) { 15683 // We already have an existing node so let's just update it and delete 15684 // the rest. 15685 deleteRemainingChildren(returnFiber, currentFirstChild.sibling); 15686 var existing = useFiber(currentFirstChild, textContent); 15687 existing.return = returnFiber; 15688 return existing; 15689 } // The existing first child is not a text node so we need to create one 15690 // and delete the existing ones. 15691 15692 15693 deleteRemainingChildren(returnFiber, currentFirstChild); 15694 var created = createFiberFromText(textContent, returnFiber.mode, lanes); 15695 created.return = returnFiber; 15696 return created; 15697 } 15698 15699 function reconcileSingleElement(returnFiber, currentFirstChild, element, lanes) { 15700 var key = element.key; 15701 var child = currentFirstChild; 15702 15703 while (child !== null) { 15704 // TODO: If key === null and child.key === null, then this only applies to 15705 // the first item in the list. 15706 if (child.key === key) { 15707 var elementType = element.type; 15708 15709 if (elementType === REACT_FRAGMENT_TYPE) { 15710 if (child.tag === Fragment) { 15711 deleteRemainingChildren(returnFiber, child.sibling); 15712 var existing = useFiber(child, element.props.children); 15713 existing.return = returnFiber; 15714 15715 { 15716 existing._debugSource = element._source; 15717 existing._debugOwner = element._owner; 15718 } 15719 15720 return existing; 15721 } 15722 } else { 15723 if (child.elementType === elementType || ( // Keep this check inline so it only runs on the false path: 15724 isCompatibleFamilyForHotReloading(child, element) ) || // Lazy types should reconcile their resolved type. 15725 // We need to do this after the Hot Reloading check above, 15726 // because hot reloading has different semantics than prod because 15727 // it doesn't resuspend. So we can't let the call below suspend. 15728 typeof elementType === 'object' && elementType !== null && elementType.$$typeof === REACT_LAZY_TYPE && resolveLazy(elementType) === child.type) { 15729 deleteRemainingChildren(returnFiber, child.sibling); 15730 15731 var _existing = useFiber(child, element.props); 15732 15733 _existing.ref = coerceRef(returnFiber, child, element); 15734 _existing.return = returnFiber; 15735 15736 { 15737 _existing._debugSource = element._source; 15738 _existing._debugOwner = element._owner; 15739 } 15740 15741 return _existing; 15742 } 15743 } // Didn't match. 15744 15745 15746 deleteRemainingChildren(returnFiber, child); 15747 break; 15748 } else { 15749 deleteChild(returnFiber, child); 15750 } 15751 15752 child = child.sibling; 15753 } 15754 15755 if (element.type === REACT_FRAGMENT_TYPE) { 15756 var created = createFiberFromFragment(element.props.children, returnFiber.mode, lanes, element.key); 15757 created.return = returnFiber; 15758 return created; 15759 } else { 15760 var _created4 = createFiberFromElement(element, returnFiber.mode, lanes); 15761 15762 _created4.ref = coerceRef(returnFiber, currentFirstChild, element); 15763 _created4.return = returnFiber; 15764 return _created4; 15765 } 15766 } 15767 15768 function reconcileSinglePortal(returnFiber, currentFirstChild, portal, lanes) { 15769 var key = portal.key; 15770 var child = currentFirstChild; 15771 15772 while (child !== null) { 15773 // TODO: If key === null and child.key === null, then this only applies to 15774 // the first item in the list. 15775 if (child.key === key) { 15776 if (child.tag === HostPortal && child.stateNode.containerInfo === portal.containerInfo && child.stateNode.implementation === portal.implementation) { 15777 deleteRemainingChildren(returnFiber, child.sibling); 15778 var existing = useFiber(child, portal.children || []); 15779 existing.return = returnFiber; 15780 return existing; 15781 } else { 15782 deleteRemainingChildren(returnFiber, child); 15783 break; 15784 } 15785 } else { 15786 deleteChild(returnFiber, child); 15787 } 15788 15789 child = child.sibling; 15790 } 15791 15792 var created = createFiberFromPortal(portal, returnFiber.mode, lanes); 15793 created.return = returnFiber; 15794 return created; 15795 } // This API will tag the children with the side-effect of the reconciliation 15796 // itself. They will be added to the side-effect list as we pass through the 15797 // children and the parent. 15798 15799 15800 function reconcileChildFibers(returnFiber, currentFirstChild, newChild, lanes) { 15801 // This function is not recursive. 15802 // If the top level item is an array, we treat it as a set of children, 15803 // not as a fragment. Nested arrays on the other hand will be treated as 15804 // fragment nodes. Recursion happens at the normal flow. 15805 // Handle top level unkeyed fragments as if they were arrays. 15806 // This leads to an ambiguity between <>{[...]}</> and <>...</>. 15807 // We treat the ambiguous cases above the same. 15808 var isUnkeyedTopLevelFragment = typeof newChild === 'object' && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE && newChild.key === null; 15809 15810 if (isUnkeyedTopLevelFragment) { 15811 newChild = newChild.props.children; 15812 } // Handle object types 15813 15814 15815 if (typeof newChild === 'object' && newChild !== null) { 15816 switch (newChild.$$typeof) { 15817 case REACT_ELEMENT_TYPE: 15818 return placeSingleChild(reconcileSingleElement(returnFiber, currentFirstChild, newChild, lanes)); 15819 15820 case REACT_PORTAL_TYPE: 15821 return placeSingleChild(reconcileSinglePortal(returnFiber, currentFirstChild, newChild, lanes)); 15822 15823 case REACT_LAZY_TYPE: 15824 var payload = newChild._payload; 15825 var init = newChild._init; // TODO: This function is supposed to be non-recursive. 15826 15827 return reconcileChildFibers(returnFiber, currentFirstChild, init(payload), lanes); 15828 } 15829 15830 if (isArray(newChild)) { 15831 return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, lanes); 15832 } 15833 15834 if (getIteratorFn(newChild)) { 15835 return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, lanes); 15836 } 15837 15838 throwOnInvalidObjectType(returnFiber, newChild); 15839 } 15840 15841 if (typeof newChild === 'string' && newChild !== '' || typeof newChild === 'number') { 15842 return placeSingleChild(reconcileSingleTextNode(returnFiber, currentFirstChild, '' + newChild, lanes)); 15843 } 15844 15845 { 15846 if (typeof newChild === 'function') { 15847 warnOnFunctionType(returnFiber); 15848 } 15849 } // Remaining cases are all treated as empty. 15850 15851 15852 return deleteRemainingChildren(returnFiber, currentFirstChild); 15853 } 15854 15855 return reconcileChildFibers; 15856 } 15857 15858 var reconcileChildFibers = ChildReconciler(true); 15859 var mountChildFibers = ChildReconciler(false); 15860 function cloneChildFibers(current, workInProgress) { 15861 if (current !== null && workInProgress.child !== current.child) { 15862 throw new Error('Resuming work not yet implemented.'); 15863 } 15864 15865 if (workInProgress.child === null) { 15866 return; 15867 } 15868 15869 var currentChild = workInProgress.child; 15870 var newChild = createWorkInProgress(currentChild, currentChild.pendingProps); 15871 workInProgress.child = newChild; 15872 newChild.return = workInProgress; 15873 15874 while (currentChild.sibling !== null) { 15875 currentChild = currentChild.sibling; 15876 newChild = newChild.sibling = createWorkInProgress(currentChild, currentChild.pendingProps); 15877 newChild.return = workInProgress; 15878 } 15879 15880 newChild.sibling = null; 15881 } // Reset a workInProgress child set to prepare it for a second pass. 15882 15883 function resetChildFibers(workInProgress, lanes) { 15884 var child = workInProgress.child; 15885 15886 while (child !== null) { 15887 resetWorkInProgress(child, lanes); 15888 child = child.sibling; 15889 } 15890 } 15891 15892 var NO_CONTEXT = {}; 15893 var contextStackCursor$1 = createCursor(NO_CONTEXT); 15894 var contextFiberStackCursor = createCursor(NO_CONTEXT); 15895 var rootInstanceStackCursor = createCursor(NO_CONTEXT); 15896 15897 function requiredContext(c) { 15898 if (c === NO_CONTEXT) { 15899 throw new Error('Expected host context to exist. This error is likely caused by a bug ' + 'in React. Please file an issue.'); 15900 } 15901 15902 return c; 15903 } 15904 15905 function getRootHostContainer() { 15906 var rootInstance = requiredContext(rootInstanceStackCursor.current); 15907 return rootInstance; 15908 } 15909 15910 function pushHostContainer(fiber, nextRootInstance) { 15911 // Push current root instance onto the stack; 15912 // This allows us to reset root when portals are popped. 15913 push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. 15914 // This enables us to pop only Fibers that provide unique contexts. 15915 15916 push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. 15917 // However, we can't just call getRootHostContext() and push it because 15918 // we'd have a different number of entries on the stack depending on 15919 // whether getRootHostContext() throws somewhere in renderer code or not. 15920 // So we push an empty value first. This lets us safely unwind on errors. 15921 15922 push(contextStackCursor$1, NO_CONTEXT, fiber); 15923 var nextRootContext = getRootHostContext(nextRootInstance); // Now that we know this function doesn't throw, replace it. 15924 15925 pop(contextStackCursor$1, fiber); 15926 push(contextStackCursor$1, nextRootContext, fiber); 15927 } 15928 15929 function popHostContainer(fiber) { 15930 pop(contextStackCursor$1, fiber); 15931 pop(contextFiberStackCursor, fiber); 15932 pop(rootInstanceStackCursor, fiber); 15933 } 15934 15935 function getHostContext() { 15936 var context = requiredContext(contextStackCursor$1.current); 15937 return context; 15938 } 15939 15940 function pushHostContext(fiber) { 15941 var rootInstance = requiredContext(rootInstanceStackCursor.current); 15942 var context = requiredContext(contextStackCursor$1.current); 15943 var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. 15944 15945 if (context === nextContext) { 15946 return; 15947 } // Track the context and the Fiber that provided it. 15948 // This enables us to pop only Fibers that provide unique contexts. 15949 15950 15951 push(contextFiberStackCursor, fiber, fiber); 15952 push(contextStackCursor$1, nextContext, fiber); 15953 } 15954 15955 function popHostContext(fiber) { 15956 // Do not pop unless this Fiber provided the current context. 15957 // pushHostContext() only pushes Fibers that provide unique contexts. 15958 if (contextFiberStackCursor.current !== fiber) { 15959 return; 15960 } 15961 15962 pop(contextStackCursor$1, fiber); 15963 pop(contextFiberStackCursor, fiber); 15964 } 15965 15966 var DefaultSuspenseContext = 0; // The Suspense Context is split into two parts. The lower bits is 15967 // inherited deeply down the subtree. The upper bits only affect 15968 // this immediate suspense boundary and gets reset each new 15969 // boundary or suspense list. 15970 15971 var SubtreeSuspenseContextMask = 1; // Subtree Flags: 15972 // InvisibleParentSuspenseContext indicates that one of our parent Suspense 15973 // boundaries is not currently showing visible main content. 15974 // Either because it is already showing a fallback or is not mounted at all. 15975 // We can use this to determine if it is desirable to trigger a fallback at 15976 // the parent. If not, then we might need to trigger undesirable boundaries 15977 // and/or suspend the commit to avoid hiding the parent content. 15978 15979 var InvisibleParentSuspenseContext = 1; // Shallow Flags: 15980 // ForceSuspenseFallback can be used by SuspenseList to force newly added 15981 // items into their fallback state during one of the render passes. 15982 15983 var ForceSuspenseFallback = 2; 15984 var suspenseStackCursor = createCursor(DefaultSuspenseContext); 15985 function hasSuspenseContext(parentContext, flag) { 15986 return (parentContext & flag) !== 0; 15987 } 15988 function setDefaultShallowSuspenseContext(parentContext) { 15989 return parentContext & SubtreeSuspenseContextMask; 15990 } 15991 function setShallowSuspenseContext(parentContext, shallowContext) { 15992 return parentContext & SubtreeSuspenseContextMask | shallowContext; 15993 } 15994 function addSubtreeSuspenseContext(parentContext, subtreeContext) { 15995 return parentContext | subtreeContext; 15996 } 15997 function pushSuspenseContext(fiber, newContext) { 15998 push(suspenseStackCursor, newContext, fiber); 15999 } 16000 function popSuspenseContext(fiber) { 16001 pop(suspenseStackCursor, fiber); 16002 } 16003 16004 function shouldCaptureSuspense(workInProgress, hasInvisibleParent) { 16005 // If it was the primary children that just suspended, capture and render the 16006 // fallback. Otherwise, don't capture and bubble to the next boundary. 16007 var nextState = workInProgress.memoizedState; 16008 16009 if (nextState !== null) { 16010 if (nextState.dehydrated !== null) { 16011 // A dehydrated boundary always captures. 16012 return true; 16013 } 16014 16015 return false; 16016 } 16017 16018 var props = workInProgress.memoizedProps; // Regular boundaries always capture. 16019 16020 { 16021 return true; 16022 } // If it's a boundary we should avoid, then we prefer to bubble up to the 16023 } 16024 function findFirstSuspended(row) { 16025 var node = row; 16026 16027 while (node !== null) { 16028 if (node.tag === SuspenseComponent) { 16029 var state = node.memoizedState; 16030 16031 if (state !== null) { 16032 var dehydrated = state.dehydrated; 16033 16034 if (dehydrated === null || isSuspenseInstancePending(dehydrated) || isSuspenseInstanceFallback(dehydrated)) { 16035 return node; 16036 } 16037 } 16038 } else if (node.tag === SuspenseListComponent && // revealOrder undefined can't be trusted because it don't 16039 // keep track of whether it suspended or not. 16040 node.memoizedProps.revealOrder !== undefined) { 16041 var didSuspend = (node.flags & DidCapture) !== NoFlags; 16042 16043 if (didSuspend) { 16044 return node; 16045 } 16046 } else if (node.child !== null) { 16047 node.child.return = node; 16048 node = node.child; 16049 continue; 16050 } 16051 16052 if (node === row) { 16053 return null; 16054 } 16055 16056 while (node.sibling === null) { 16057 if (node.return === null || node.return === row) { 16058 return null; 16059 } 16060 16061 node = node.return; 16062 } 16063 16064 node.sibling.return = node.return; 16065 node = node.sibling; 16066 } 16067 16068 return null; 16069 } 16070 16071 var NoFlags$1 = 16072 /* */ 16073 0; // Represents whether effect should fire. 16074 16075 var HasEffect = 16076 /* */ 16077 1; // Represents the phase in which the effect (not the clean-up) fires. 16078 16079 var Insertion = 16080 /* */ 16081 2; 16082 var Layout = 16083 /* */ 16084 4; 16085 var Passive$1 = 16086 /* */ 16087 8; 16088 16089 // and should be reset before starting a new render. 16090 // This tracks which mutable sources need to be reset after a render. 16091 16092 var workInProgressSources = []; 16093 function resetWorkInProgressVersions() { 16094 for (var i = 0; i < workInProgressSources.length; i++) { 16095 var mutableSource = workInProgressSources[i]; 16096 16097 { 16098 mutableSource._workInProgressVersionPrimary = null; 16099 } 16100 } 16101 16102 workInProgressSources.length = 0; 16103 } 16104 // This ensures that the version used for server rendering matches the one 16105 // that is eventually read during hydration. 16106 // If they don't match there's a potential tear and a full deopt render is required. 16107 16108 function registerMutableSourceForHydration(root, mutableSource) { 16109 var getVersion = mutableSource._getVersion; 16110 var version = getVersion(mutableSource._source); // TODO Clear this data once all pending hydration work is finished. 16111 // Retaining it forever may interfere with GC. 16112 16113 if (root.mutableSourceEagerHydrationData == null) { 16114 root.mutableSourceEagerHydrationData = [mutableSource, version]; 16115 } else { 16116 root.mutableSourceEagerHydrationData.push(mutableSource, version); 16117 } 16118 } 16119 16120 var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher, 16121 ReactCurrentBatchConfig$2 = ReactSharedInternals.ReactCurrentBatchConfig; 16122 var didWarnAboutMismatchedHooksForComponent; 16123 var didWarnUncachedGetSnapshot; 16124 16125 { 16126 didWarnAboutMismatchedHooksForComponent = new Set(); 16127 } 16128 16129 // These are set right before calling the component. 16130 var renderLanes = NoLanes; // The work-in-progress fiber. I've named it differently to distinguish it from 16131 // the work-in-progress hook. 16132 16133 var currentlyRenderingFiber$1 = null; // Hooks are stored as a linked list on the fiber's memoizedState field. The 16134 // current hook list is the list that belongs to the current fiber. The 16135 // work-in-progress hook list is a new list that will be added to the 16136 // work-in-progress fiber. 16137 16138 var currentHook = null; 16139 var workInProgressHook = null; // Whether an update was scheduled at any point during the render phase. This 16140 // does not get reset if we do another render pass; only when we're completely 16141 // finished evaluating this component. This is an optimization so we know 16142 // whether we need to clear render phase updates after a throw. 16143 16144 var didScheduleRenderPhaseUpdate = false; // Where an update was scheduled only during the current render pass. This 16145 // gets reset after each attempt. 16146 // TODO: Maybe there's some way to consolidate this with 16147 // `didScheduleRenderPhaseUpdate`. Or with `numberOfReRenders`. 16148 16149 var didScheduleRenderPhaseUpdateDuringThisPass = false; // Counts the number of useId hooks in this component. 16150 16151 var localIdCounter = 0; // Used for ids that are generated completely client-side (i.e. not during 16152 // hydration). This counter is global, so client ids are not stable across 16153 // render attempts. 16154 16155 var globalClientIdCounter = 0; 16156 var RE_RENDER_LIMIT = 25; // In DEV, this is the name of the currently executing primitive hook 16157 16158 var currentHookNameInDev = null; // In DEV, this list ensures that hooks are called in the same order between renders. 16159 // The list stores the order of hooks used during the initial render (mount). 16160 // Subsequent renders (updates) reference this list. 16161 16162 var hookTypesDev = null; 16163 var hookTypesUpdateIndexDev = -1; // In DEV, this tracks whether currently rendering component needs to ignore 16164 // the dependencies for Hooks that need them (e.g. useEffect or useMemo). 16165 // When true, such Hooks will always be "remounted". Only used during hot reload. 16166 16167 var ignorePreviousDependencies = false; 16168 16169 function mountHookTypesDev() { 16170 { 16171 var hookName = currentHookNameInDev; 16172 16173 if (hookTypesDev === null) { 16174 hookTypesDev = [hookName]; 16175 } else { 16176 hookTypesDev.push(hookName); 16177 } 16178 } 16179 } 16180 16181 function updateHookTypesDev() { 16182 { 16183 var hookName = currentHookNameInDev; 16184 16185 if (hookTypesDev !== null) { 16186 hookTypesUpdateIndexDev++; 16187 16188 if (hookTypesDev[hookTypesUpdateIndexDev] !== hookName) { 16189 warnOnHookMismatchInDev(hookName); 16190 } 16191 } 16192 } 16193 } 16194 16195 function checkDepsAreArrayDev(deps) { 16196 { 16197 if (deps !== undefined && deps !== null && !isArray(deps)) { 16198 // Verify deps, but only on mount to avoid extra checks. 16199 // It's unlikely their type would change as usually you define them inline. 16200 error('%s received a final argument that is not an array (instead, received `%s`). When ' + 'specified, the final argument must be an array.', currentHookNameInDev, typeof deps); 16201 } 16202 } 16203 } 16204 16205 function warnOnHookMismatchInDev(currentHookName) { 16206 { 16207 var componentName = getComponentNameFromFiber(currentlyRenderingFiber$1); 16208 16209 if (!didWarnAboutMismatchedHooksForComponent.has(componentName)) { 16210 didWarnAboutMismatchedHooksForComponent.add(componentName); 16211 16212 if (hookTypesDev !== null) { 16213 var table = ''; 16214 var secondColumnStart = 30; 16215 16216 for (var i = 0; i <= hookTypesUpdateIndexDev; i++) { 16217 var oldHookName = hookTypesDev[i]; 16218 var newHookName = i === hookTypesUpdateIndexDev ? currentHookName : oldHookName; 16219 var row = i + 1 + ". " + oldHookName; // Extra space so second column lines up 16220 // lol @ IE not supporting String#repeat 16221 16222 while (row.length < secondColumnStart) { 16223 row += ' '; 16224 } 16225 16226 row += newHookName + '\n'; 16227 table += row; 16228 } 16229 16230 error('React has detected a change in the order of Hooks called by %s. ' + 'This will lead to bugs and errors if not fixed. ' + 'For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks\n\n' + ' Previous render Next render\n' + ' ------------------------------------------------------\n' + '%s' + ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n', componentName, table); 16231 } 16232 } 16233 } 16234 } 16235 16236 function throwInvalidHookError() { 16237 throw new Error('Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' + ' one of the following reasons:\n' + '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' + '2. You might be breaking the Rules of Hooks\n' + '3. You might have more than one copy of React in the same app\n' + 'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.'); 16238 } 16239 16240 function areHookInputsEqual(nextDeps, prevDeps) { 16241 { 16242 if (ignorePreviousDependencies) { 16243 // Only true when this component is being hot reloaded. 16244 return false; 16245 } 16246 } 16247 16248 if (prevDeps === null) { 16249 { 16250 error('%s received a final argument during this render, but not during ' + 'the previous render. Even though the final argument is optional, ' + 'its type cannot change between renders.', currentHookNameInDev); 16251 } 16252 16253 return false; 16254 } 16255 16256 { 16257 // Don't bother comparing lengths in prod because these arrays should be 16258 // passed inline. 16259 if (nextDeps.length !== prevDeps.length) { 16260 error('The final argument passed to %s changed size between renders. The ' + 'order and size of this array must remain constant.\n\n' + 'Previous: %s\n' + 'Incoming: %s', currentHookNameInDev, "[" + prevDeps.join(', ') + "]", "[" + nextDeps.join(', ') + "]"); 16261 } 16262 } 16263 16264 for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { 16265 if (objectIs(nextDeps[i], prevDeps[i])) { 16266 continue; 16267 } 16268 16269 return false; 16270 } 16271 16272 return true; 16273 } 16274 16275 function renderWithHooks(current, workInProgress, Component, props, secondArg, nextRenderLanes) { 16276 renderLanes = nextRenderLanes; 16277 currentlyRenderingFiber$1 = workInProgress; 16278 16279 { 16280 hookTypesDev = current !== null ? current._debugHookTypes : null; 16281 hookTypesUpdateIndexDev = -1; // Used for hot reloading: 16282 16283 ignorePreviousDependencies = current !== null && current.type !== workInProgress.type; 16284 } 16285 16286 workInProgress.memoizedState = null; 16287 workInProgress.updateQueue = null; 16288 workInProgress.lanes = NoLanes; // The following should have already been reset 16289 // currentHook = null; 16290 // workInProgressHook = null; 16291 // didScheduleRenderPhaseUpdate = false; 16292 // localIdCounter = 0; 16293 // TODO Warn if no hooks are used at all during mount, then some are used during update. 16294 // Currently we will identify the update render as a mount because memoizedState === null. 16295 // This is tricky because it's valid for certain types of components (e.g. React.lazy) 16296 // Using memoizedState to differentiate between mount/update only works if at least one stateful hook is used. 16297 // Non-stateful hooks (e.g. context) don't get added to memoizedState, 16298 // so memoizedState would be null during updates and mounts. 16299 16300 { 16301 if (current !== null && current.memoizedState !== null) { 16302 ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV; 16303 } else if (hookTypesDev !== null) { 16304 // This dispatcher handles an edge case where a component is updating, 16305 // but no stateful hooks have been used. 16306 // We want to match the production code behavior (which will use HooksDispatcherOnMount), 16307 // but with the extra DEV validation to ensure hooks ordering hasn't changed. 16308 // This dispatcher does that. 16309 ReactCurrentDispatcher$1.current = HooksDispatcherOnMountWithHookTypesInDEV; 16310 } else { 16311 ReactCurrentDispatcher$1.current = HooksDispatcherOnMountInDEV; 16312 } 16313 } 16314 16315 var children = Component(props, secondArg); // Check if there was a render phase update 16316 16317 if (didScheduleRenderPhaseUpdateDuringThisPass) { 16318 // Keep rendering in a loop for as long as render phase updates continue to 16319 // be scheduled. Use a counter to prevent infinite loops. 16320 var numberOfReRenders = 0; 16321 16322 do { 16323 didScheduleRenderPhaseUpdateDuringThisPass = false; 16324 localIdCounter = 0; 16325 16326 if (numberOfReRenders >= RE_RENDER_LIMIT) { 16327 throw new Error('Too many re-renders. React limits the number of renders to prevent ' + 'an infinite loop.'); 16328 } 16329 16330 numberOfReRenders += 1; 16331 16332 { 16333 // Even when hot reloading, allow dependencies to stabilize 16334 // after first render to prevent infinite render phase updates. 16335 ignorePreviousDependencies = false; 16336 } // Start over from the beginning of the list 16337 16338 16339 currentHook = null; 16340 workInProgressHook = null; 16341 workInProgress.updateQueue = null; 16342 16343 { 16344 // Also validate hook order for cascading updates. 16345 hookTypesUpdateIndexDev = -1; 16346 } 16347 16348 ReactCurrentDispatcher$1.current = HooksDispatcherOnRerenderInDEV ; 16349 children = Component(props, secondArg); 16350 } while (didScheduleRenderPhaseUpdateDuringThisPass); 16351 } // We can assume the previous dispatcher is always this one, since we set it 16352 // at the beginning of the render phase and there's no re-entrance. 16353 16354 16355 ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; 16356 16357 { 16358 workInProgress._debugHookTypes = hookTypesDev; 16359 } // This check uses currentHook so that it works the same in DEV and prod bundles. 16360 // hookTypesDev could catch more cases (e.g. context) but only in DEV bundles. 16361 16362 16363 var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; 16364 renderLanes = NoLanes; 16365 currentlyRenderingFiber$1 = null; 16366 currentHook = null; 16367 workInProgressHook = null; 16368 16369 { 16370 currentHookNameInDev = null; 16371 hookTypesDev = null; 16372 hookTypesUpdateIndexDev = -1; // Confirm that a static flag was not added or removed since the last 16373 // render. If this fires, it suggests that we incorrectly reset the static 16374 // flags in some other part of the codebase. This has happened before, for 16375 // example, in the SuspenseList implementation. 16376 16377 if (current !== null && (current.flags & StaticMask) !== (workInProgress.flags & StaticMask) && // Disable this warning in legacy mode, because legacy Suspense is weird 16378 // and creates false positives. To make this work in legacy mode, we'd 16379 // need to mark fibers that commit in an incomplete state, somehow. For 16380 // now I'll disable the warning that most of the bugs that would trigger 16381 // it are either exclusive to concurrent mode or exist in both. 16382 (current.mode & ConcurrentMode) !== NoMode) { 16383 error('Internal React error: Expected static flag was missing. Please ' + 'notify the React team.'); 16384 } 16385 } 16386 16387 didScheduleRenderPhaseUpdate = false; // This is reset by checkDidRenderIdHook 16388 // localIdCounter = 0; 16389 16390 if (didRenderTooFewHooks) { 16391 throw new Error('Rendered fewer hooks than expected. This may be caused by an accidental ' + 'early return statement.'); 16392 } 16393 16394 return children; 16395 } 16396 function checkDidRenderIdHook() { 16397 // This should be called immediately after every renderWithHooks call. 16398 // Conceptually, it's part of the return value of renderWithHooks; it's only a 16399 // separate function to avoid using an array tuple. 16400 var didRenderIdHook = localIdCounter !== 0; 16401 localIdCounter = 0; 16402 return didRenderIdHook; 16403 } 16404 function bailoutHooks(current, workInProgress, lanes) { 16405 workInProgress.updateQueue = current.updateQueue; // TODO: Don't need to reset the flags here, because they're reset in the 16406 // complete phase (bubbleProperties). 16407 16408 if ( (workInProgress.mode & StrictEffectsMode) !== NoMode) { 16409 workInProgress.flags &= ~(MountPassiveDev | MountLayoutDev | Passive | Update); 16410 } else { 16411 workInProgress.flags &= ~(Passive | Update); 16412 } 16413 16414 current.lanes = removeLanes(current.lanes, lanes); 16415 } 16416 function resetHooksAfterThrow() { 16417 // We can assume the previous dispatcher is always this one, since we set it 16418 // at the beginning of the render phase and there's no re-entrance. 16419 ReactCurrentDispatcher$1.current = ContextOnlyDispatcher; 16420 16421 if (didScheduleRenderPhaseUpdate) { 16422 // There were render phase updates. These are only valid for this render 16423 // phase, which we are now aborting. Remove the updates from the queues so 16424 // they do not persist to the next render. Do not remove updates from hooks 16425 // that weren't processed. 16426 // 16427 // Only reset the updates from the queue if it has a clone. If it does 16428 // not have a clone, that means it wasn't processed, and the updates were 16429 // scheduled before we entered the render phase. 16430 var hook = currentlyRenderingFiber$1.memoizedState; 16431 16432 while (hook !== null) { 16433 var queue = hook.queue; 16434 16435 if (queue !== null) { 16436 queue.pending = null; 16437 } 16438 16439 hook = hook.next; 16440 } 16441 16442 didScheduleRenderPhaseUpdate = false; 16443 } 16444 16445 renderLanes = NoLanes; 16446 currentlyRenderingFiber$1 = null; 16447 currentHook = null; 16448 workInProgressHook = null; 16449 16450 { 16451 hookTypesDev = null; 16452 hookTypesUpdateIndexDev = -1; 16453 currentHookNameInDev = null; 16454 isUpdatingOpaqueValueInRenderPhase = false; 16455 } 16456 16457 didScheduleRenderPhaseUpdateDuringThisPass = false; 16458 localIdCounter = 0; 16459 } 16460 16461 function mountWorkInProgressHook() { 16462 var hook = { 16463 memoizedState: null, 16464 baseState: null, 16465 baseQueue: null, 16466 queue: null, 16467 next: null 16468 }; 16469 16470 if (workInProgressHook === null) { 16471 // This is the first hook in the list 16472 currentlyRenderingFiber$1.memoizedState = workInProgressHook = hook; 16473 } else { 16474 // Append to the end of the list 16475 workInProgressHook = workInProgressHook.next = hook; 16476 } 16477 16478 return workInProgressHook; 16479 } 16480 16481 function updateWorkInProgressHook() { 16482 // This function is used both for updates and for re-renders triggered by a 16483 // render phase update. It assumes there is either a current hook we can 16484 // clone, or a work-in-progress hook from a previous render pass that we can 16485 // use as a base. When we reach the end of the base list, we must switch to 16486 // the dispatcher used for mounts. 16487 var nextCurrentHook; 16488 16489 if (currentHook === null) { 16490 var current = currentlyRenderingFiber$1.alternate; 16491 16492 if (current !== null) { 16493 nextCurrentHook = current.memoizedState; 16494 } else { 16495 nextCurrentHook = null; 16496 } 16497 } else { 16498 nextCurrentHook = currentHook.next; 16499 } 16500 16501 var nextWorkInProgressHook; 16502 16503 if (workInProgressHook === null) { 16504 nextWorkInProgressHook = currentlyRenderingFiber$1.memoizedState; 16505 } else { 16506 nextWorkInProgressHook = workInProgressHook.next; 16507 } 16508 16509 if (nextWorkInProgressHook !== null) { 16510 // There's already a work-in-progress. Reuse it. 16511 workInProgressHook = nextWorkInProgressHook; 16512 nextWorkInProgressHook = workInProgressHook.next; 16513 currentHook = nextCurrentHook; 16514 } else { 16515 // Clone from the current hook. 16516 if (nextCurrentHook === null) { 16517 throw new Error('Rendered more hooks than during the previous render.'); 16518 } 16519 16520 currentHook = nextCurrentHook; 16521 var newHook = { 16522 memoizedState: currentHook.memoizedState, 16523 baseState: currentHook.baseState, 16524 baseQueue: currentHook.baseQueue, 16525 queue: currentHook.queue, 16526 next: null 16527 }; 16528 16529 if (workInProgressHook === null) { 16530 // This is the first hook in the list. 16531 currentlyRenderingFiber$1.memoizedState = workInProgressHook = newHook; 16532 } else { 16533 // Append to the end of the list. 16534 workInProgressHook = workInProgressHook.next = newHook; 16535 } 16536 } 16537 16538 return workInProgressHook; 16539 } 16540 16541 function createFunctionComponentUpdateQueue() { 16542 return { 16543 lastEffect: null, 16544 stores: null 16545 }; 16546 } 16547 16548 function basicStateReducer(state, action) { 16549 // $FlowFixMe: Flow doesn't like mixed types 16550 return typeof action === 'function' ? action(state) : action; 16551 } 16552 16553 function mountReducer(reducer, initialArg, init) { 16554 var hook = mountWorkInProgressHook(); 16555 var initialState; 16556 16557 if (init !== undefined) { 16558 initialState = init(initialArg); 16559 } else { 16560 initialState = initialArg; 16561 } 16562 16563 hook.memoizedState = hook.baseState = initialState; 16564 var queue = { 16565 pending: null, 16566 interleaved: null, 16567 lanes: NoLanes, 16568 dispatch: null, 16569 lastRenderedReducer: reducer, 16570 lastRenderedState: initialState 16571 }; 16572 hook.queue = queue; 16573 var dispatch = queue.dispatch = dispatchReducerAction.bind(null, currentlyRenderingFiber$1, queue); 16574 return [hook.memoizedState, dispatch]; 16575 } 16576 16577 function updateReducer(reducer, initialArg, init) { 16578 var hook = updateWorkInProgressHook(); 16579 var queue = hook.queue; 16580 16581 if (queue === null) { 16582 throw new Error('Should have a queue. This is likely a bug in React. Please file an issue.'); 16583 } 16584 16585 queue.lastRenderedReducer = reducer; 16586 var current = currentHook; // The last rebase update that is NOT part of the base state. 16587 16588 var baseQueue = current.baseQueue; // The last pending update that hasn't been processed yet. 16589 16590 var pendingQueue = queue.pending; 16591 16592 if (pendingQueue !== null) { 16593 // We have new updates that haven't been processed yet. 16594 // We'll add them to the base queue. 16595 if (baseQueue !== null) { 16596 // Merge the pending queue and the base queue. 16597 var baseFirst = baseQueue.next; 16598 var pendingFirst = pendingQueue.next; 16599 baseQueue.next = pendingFirst; 16600 pendingQueue.next = baseFirst; 16601 } 16602 16603 { 16604 if (current.baseQueue !== baseQueue) { 16605 // Internal invariant that should never happen, but feasibly could in 16606 // the future if we implement resuming, or some form of that. 16607 error('Internal error: Expected work-in-progress queue to be a clone. ' + 'This is a bug in React.'); 16608 } 16609 } 16610 16611 current.baseQueue = baseQueue = pendingQueue; 16612 queue.pending = null; 16613 } 16614 16615 if (baseQueue !== null) { 16616 // We have a queue to process. 16617 var first = baseQueue.next; 16618 var newState = current.baseState; 16619 var newBaseState = null; 16620 var newBaseQueueFirst = null; 16621 var newBaseQueueLast = null; 16622 var update = first; 16623 16624 do { 16625 var updateLane = update.lane; 16626 16627 if (!isSubsetOfLanes(renderLanes, updateLane)) { 16628 // Priority is insufficient. Skip this update. If this is the first 16629 // skipped update, the previous update/state is the new base 16630 // update/state. 16631 var clone = { 16632 lane: updateLane, 16633 action: update.action, 16634 hasEagerState: update.hasEagerState, 16635 eagerState: update.eagerState, 16636 next: null 16637 }; 16638 16639 if (newBaseQueueLast === null) { 16640 newBaseQueueFirst = newBaseQueueLast = clone; 16641 newBaseState = newState; 16642 } else { 16643 newBaseQueueLast = newBaseQueueLast.next = clone; 16644 } // Update the remaining priority in the queue. 16645 // TODO: Don't need to accumulate this. Instead, we can remove 16646 // renderLanes from the original lanes. 16647 16648 16649 currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, updateLane); 16650 markSkippedUpdateLanes(updateLane); 16651 } else { 16652 // This update does have sufficient priority. 16653 if (newBaseQueueLast !== null) { 16654 var _clone = { 16655 // This update is going to be committed so we never want uncommit 16656 // it. Using NoLane works because 0 is a subset of all bitmasks, so 16657 // this will never be skipped by the check above. 16658 lane: NoLane, 16659 action: update.action, 16660 hasEagerState: update.hasEagerState, 16661 eagerState: update.eagerState, 16662 next: null 16663 }; 16664 newBaseQueueLast = newBaseQueueLast.next = _clone; 16665 } // Process this update. 16666 16667 16668 if (update.hasEagerState) { 16669 // If this update is a state update (not a reducer) and was processed eagerly, 16670 // we can use the eagerly computed state 16671 newState = update.eagerState; 16672 } else { 16673 var action = update.action; 16674 newState = reducer(newState, action); 16675 } 16676 } 16677 16678 update = update.next; 16679 } while (update !== null && update !== first); 16680 16681 if (newBaseQueueLast === null) { 16682 newBaseState = newState; 16683 } else { 16684 newBaseQueueLast.next = newBaseQueueFirst; 16685 } // Mark that the fiber performed work, but only if the new state is 16686 // different from the current state. 16687 16688 16689 if (!objectIs(newState, hook.memoizedState)) { 16690 markWorkInProgressReceivedUpdate(); 16691 } 16692 16693 hook.memoizedState = newState; 16694 hook.baseState = newBaseState; 16695 hook.baseQueue = newBaseQueueLast; 16696 queue.lastRenderedState = newState; 16697 } // Interleaved updates are stored on a separate queue. We aren't going to 16698 // process them during this render, but we do need to track which lanes 16699 // are remaining. 16700 16701 16702 var lastInterleaved = queue.interleaved; 16703 16704 if (lastInterleaved !== null) { 16705 var interleaved = lastInterleaved; 16706 16707 do { 16708 var interleavedLane = interleaved.lane; 16709 currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, interleavedLane); 16710 markSkippedUpdateLanes(interleavedLane); 16711 interleaved = interleaved.next; 16712 } while (interleaved !== lastInterleaved); 16713 } else if (baseQueue === null) { 16714 // `queue.lanes` is used for entangling transitions. We can set it back to 16715 // zero once the queue is empty. 16716 queue.lanes = NoLanes; 16717 } 16718 16719 var dispatch = queue.dispatch; 16720 return [hook.memoizedState, dispatch]; 16721 } 16722 16723 function rerenderReducer(reducer, initialArg, init) { 16724 var hook = updateWorkInProgressHook(); 16725 var queue = hook.queue; 16726 16727 if (queue === null) { 16728 throw new Error('Should have a queue. This is likely a bug in React. Please file an issue.'); 16729 } 16730 16731 queue.lastRenderedReducer = reducer; // This is a re-render. Apply the new render phase updates to the previous 16732 // work-in-progress hook. 16733 16734 var dispatch = queue.dispatch; 16735 var lastRenderPhaseUpdate = queue.pending; 16736 var newState = hook.memoizedState; 16737 16738 if (lastRenderPhaseUpdate !== null) { 16739 // The queue doesn't persist past this render pass. 16740 queue.pending = null; 16741 var firstRenderPhaseUpdate = lastRenderPhaseUpdate.next; 16742 var update = firstRenderPhaseUpdate; 16743 16744 do { 16745 // Process this render phase update. We don't have to check the 16746 // priority because it will always be the same as the current 16747 // render's. 16748 var action = update.action; 16749 newState = reducer(newState, action); 16750 update = update.next; 16751 } while (update !== firstRenderPhaseUpdate); // Mark that the fiber performed work, but only if the new state is 16752 // different from the current state. 16753 16754 16755 if (!objectIs(newState, hook.memoizedState)) { 16756 markWorkInProgressReceivedUpdate(); 16757 } 16758 16759 hook.memoizedState = newState; // Don't persist the state accumulated from the render phase updates to 16760 // the base state unless the queue is empty. 16761 // TODO: Not sure if this is the desired semantics, but it's what we 16762 // do for gDSFP. I can't remember why. 16763 16764 if (hook.baseQueue === null) { 16765 hook.baseState = newState; 16766 } 16767 16768 queue.lastRenderedState = newState; 16769 } 16770 16771 return [newState, dispatch]; 16772 } 16773 16774 function mountMutableSource(source, getSnapshot, subscribe) { 16775 { 16776 return undefined; 16777 } 16778 } 16779 16780 function updateMutableSource(source, getSnapshot, subscribe) { 16781 { 16782 return undefined; 16783 } 16784 } 16785 16786 function mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { 16787 var fiber = currentlyRenderingFiber$1; 16788 var hook = mountWorkInProgressHook(); 16789 var nextSnapshot; 16790 var isHydrating = getIsHydrating(); 16791 16792 if (isHydrating) { 16793 if (getServerSnapshot === undefined) { 16794 throw new Error('Missing getServerSnapshot, which is required for ' + 'server-rendered content. Will revert to client rendering.'); 16795 } 16796 16797 nextSnapshot = getServerSnapshot(); 16798 16799 { 16800 if (!didWarnUncachedGetSnapshot) { 16801 if (nextSnapshot !== getServerSnapshot()) { 16802 error('The result of getServerSnapshot should be cached to avoid an infinite loop'); 16803 16804 didWarnUncachedGetSnapshot = true; 16805 } 16806 } 16807 } 16808 } else { 16809 nextSnapshot = getSnapshot(); 16810 16811 { 16812 if (!didWarnUncachedGetSnapshot) { 16813 var cachedSnapshot = getSnapshot(); 16814 16815 if (!objectIs(nextSnapshot, cachedSnapshot)) { 16816 error('The result of getSnapshot should be cached to avoid an infinite loop'); 16817 16818 didWarnUncachedGetSnapshot = true; 16819 } 16820 } 16821 } // Unless we're rendering a blocking lane, schedule a consistency check. 16822 // Right before committing, we will walk the tree and check if any of the 16823 // stores were mutated. 16824 // 16825 // We won't do this if we're hydrating server-rendered content, because if 16826 // the content is stale, it's already visible anyway. Instead we'll patch 16827 // it up in a passive effect. 16828 16829 16830 var root = getWorkInProgressRoot(); 16831 16832 if (root === null) { 16833 throw new Error('Expected a work-in-progress root. This is a bug in React. Please file an issue.'); 16834 } 16835 16836 if (!includesBlockingLane(root, renderLanes)) { 16837 pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); 16838 } 16839 } // Read the current snapshot from the store on every render. This breaks the 16840 // normal rules of React, and only works because store updates are 16841 // always synchronous. 16842 16843 16844 hook.memoizedState = nextSnapshot; 16845 var inst = { 16846 value: nextSnapshot, 16847 getSnapshot: getSnapshot 16848 }; 16849 hook.queue = inst; // Schedule an effect to subscribe to the store. 16850 16851 mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Schedule an effect to update the mutable instance fields. We will update 16852 // this whenever subscribe, getSnapshot, or value changes. Because there's no 16853 // clean-up function, and we track the deps correctly, we can call pushEffect 16854 // directly, without storing any additional state. For the same reason, we 16855 // don't need to set a static flag, either. 16856 // TODO: We can move this to the passive phase once we add a pre-commit 16857 // consistency check. See the next comment. 16858 16859 fiber.flags |= Passive; 16860 pushEffect(HasEffect | Passive$1, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), undefined, null); 16861 return nextSnapshot; 16862 } 16863 16864 function updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { 16865 var fiber = currentlyRenderingFiber$1; 16866 var hook = updateWorkInProgressHook(); // Read the current snapshot from the store on every render. This breaks the 16867 // normal rules of React, and only works because store updates are 16868 // always synchronous. 16869 16870 var nextSnapshot = getSnapshot(); 16871 16872 { 16873 if (!didWarnUncachedGetSnapshot) { 16874 var cachedSnapshot = getSnapshot(); 16875 16876 if (!objectIs(nextSnapshot, cachedSnapshot)) { 16877 error('The result of getSnapshot should be cached to avoid an infinite loop'); 16878 16879 didWarnUncachedGetSnapshot = true; 16880 } 16881 } 16882 } 16883 16884 var prevSnapshot = hook.memoizedState; 16885 var snapshotChanged = !objectIs(prevSnapshot, nextSnapshot); 16886 16887 if (snapshotChanged) { 16888 hook.memoizedState = nextSnapshot; 16889 markWorkInProgressReceivedUpdate(); 16890 } 16891 16892 var inst = hook.queue; 16893 updateEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [subscribe]); // Whenever getSnapshot or subscribe changes, we need to check in the 16894 // commit phase if there was an interleaved mutation. In concurrent mode 16895 // this can happen all the time, but even in synchronous mode, an earlier 16896 // effect may have mutated the store. 16897 16898 if (inst.getSnapshot !== getSnapshot || snapshotChanged || // Check if the susbcribe function changed. We can save some memory by 16899 // checking whether we scheduled a subscription effect above. 16900 workInProgressHook !== null && workInProgressHook.memoizedState.tag & HasEffect) { 16901 fiber.flags |= Passive; 16902 pushEffect(HasEffect | Passive$1, updateStoreInstance.bind(null, fiber, inst, nextSnapshot, getSnapshot), undefined, null); // Unless we're rendering a blocking lane, schedule a consistency check. 16903 // Right before committing, we will walk the tree and check if any of the 16904 // stores were mutated. 16905 16906 var root = getWorkInProgressRoot(); 16907 16908 if (root === null) { 16909 throw new Error('Expected a work-in-progress root. This is a bug in React. Please file an issue.'); 16910 } 16911 16912 if (!includesBlockingLane(root, renderLanes)) { 16913 pushStoreConsistencyCheck(fiber, getSnapshot, nextSnapshot); 16914 } 16915 } 16916 16917 return nextSnapshot; 16918 } 16919 16920 function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { 16921 fiber.flags |= StoreConsistency; 16922 var check = { 16923 getSnapshot: getSnapshot, 16924 value: renderedSnapshot 16925 }; 16926 var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; 16927 16928 if (componentUpdateQueue === null) { 16929 componentUpdateQueue = createFunctionComponentUpdateQueue(); 16930 currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; 16931 componentUpdateQueue.stores = [check]; 16932 } else { 16933 var stores = componentUpdateQueue.stores; 16934 16935 if (stores === null) { 16936 componentUpdateQueue.stores = [check]; 16937 } else { 16938 stores.push(check); 16939 } 16940 } 16941 } 16942 16943 function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { 16944 // These are updated in the passive phase 16945 inst.value = nextSnapshot; 16946 inst.getSnapshot = getSnapshot; // Something may have been mutated in between render and commit. This could 16947 // have been in an event that fired before the passive effects, or it could 16948 // have been in a layout effect. In that case, we would have used the old 16949 // snapsho and getSnapshot values to bail out. We need to check one more time. 16950 16951 if (checkIfSnapshotChanged(inst)) { 16952 // Force a re-render. 16953 forceStoreRerender(fiber); 16954 } 16955 } 16956 16957 function subscribeToStore(fiber, inst, subscribe) { 16958 var handleStoreChange = function () { 16959 // The store changed. Check if the snapshot changed since the last time we 16960 // read from the store. 16961 if (checkIfSnapshotChanged(inst)) { 16962 // Force a re-render. 16963 forceStoreRerender(fiber); 16964 } 16965 }; // Subscribe to the store and return a clean-up function. 16966 16967 16968 return subscribe(handleStoreChange); 16969 } 16970 16971 function checkIfSnapshotChanged(inst) { 16972 var latestGetSnapshot = inst.getSnapshot; 16973 var prevValue = inst.value; 16974 16975 try { 16976 var nextValue = latestGetSnapshot(); 16977 return !objectIs(prevValue, nextValue); 16978 } catch (error) { 16979 return true; 16980 } 16981 } 16982 16983 function forceStoreRerender(fiber) { 16984 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 16985 16986 if (root !== null) { 16987 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 16988 } 16989 } 16990 16991 function mountState(initialState) { 16992 var hook = mountWorkInProgressHook(); 16993 16994 if (typeof initialState === 'function') { 16995 // $FlowFixMe: Flow doesn't like mixed types 16996 initialState = initialState(); 16997 } 16998 16999 hook.memoizedState = hook.baseState = initialState; 17000 var queue = { 17001 pending: null, 17002 interleaved: null, 17003 lanes: NoLanes, 17004 dispatch: null, 17005 lastRenderedReducer: basicStateReducer, 17006 lastRenderedState: initialState 17007 }; 17008 hook.queue = queue; 17009 var dispatch = queue.dispatch = dispatchSetState.bind(null, currentlyRenderingFiber$1, queue); 17010 return [hook.memoizedState, dispatch]; 17011 } 17012 17013 function updateState(initialState) { 17014 return updateReducer(basicStateReducer); 17015 } 17016 17017 function rerenderState(initialState) { 17018 return rerenderReducer(basicStateReducer); 17019 } 17020 17021 function pushEffect(tag, create, destroy, deps) { 17022 var effect = { 17023 tag: tag, 17024 create: create, 17025 destroy: destroy, 17026 deps: deps, 17027 // Circular 17028 next: null 17029 }; 17030 var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue; 17031 17032 if (componentUpdateQueue === null) { 17033 componentUpdateQueue = createFunctionComponentUpdateQueue(); 17034 currentlyRenderingFiber$1.updateQueue = componentUpdateQueue; 17035 componentUpdateQueue.lastEffect = effect.next = effect; 17036 } else { 17037 var lastEffect = componentUpdateQueue.lastEffect; 17038 17039 if (lastEffect === null) { 17040 componentUpdateQueue.lastEffect = effect.next = effect; 17041 } else { 17042 var firstEffect = lastEffect.next; 17043 lastEffect.next = effect; 17044 effect.next = firstEffect; 17045 componentUpdateQueue.lastEffect = effect; 17046 } 17047 } 17048 17049 return effect; 17050 } 17051 17052 function mountRef(initialValue) { 17053 var hook = mountWorkInProgressHook(); 17054 17055 { 17056 var _ref2 = { 17057 current: initialValue 17058 }; 17059 hook.memoizedState = _ref2; 17060 return _ref2; 17061 } 17062 } 17063 17064 function updateRef(initialValue) { 17065 var hook = updateWorkInProgressHook(); 17066 return hook.memoizedState; 17067 } 17068 17069 function mountEffectImpl(fiberFlags, hookFlags, create, deps) { 17070 var hook = mountWorkInProgressHook(); 17071 var nextDeps = deps === undefined ? null : deps; 17072 currentlyRenderingFiber$1.flags |= fiberFlags; 17073 hook.memoizedState = pushEffect(HasEffect | hookFlags, create, undefined, nextDeps); 17074 } 17075 17076 function updateEffectImpl(fiberFlags, hookFlags, create, deps) { 17077 var hook = updateWorkInProgressHook(); 17078 var nextDeps = deps === undefined ? null : deps; 17079 var destroy = undefined; 17080 17081 if (currentHook !== null) { 17082 var prevEffect = currentHook.memoizedState; 17083 destroy = prevEffect.destroy; 17084 17085 if (nextDeps !== null) { 17086 var prevDeps = prevEffect.deps; 17087 17088 if (areHookInputsEqual(nextDeps, prevDeps)) { 17089 hook.memoizedState = pushEffect(hookFlags, create, destroy, nextDeps); 17090 return; 17091 } 17092 } 17093 } 17094 17095 currentlyRenderingFiber$1.flags |= fiberFlags; 17096 hook.memoizedState = pushEffect(HasEffect | hookFlags, create, destroy, nextDeps); 17097 } 17098 17099 function mountEffect(create, deps) { 17100 if ( (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { 17101 return mountEffectImpl(MountPassiveDev | Passive | PassiveStatic, Passive$1, create, deps); 17102 } else { 17103 return mountEffectImpl(Passive | PassiveStatic, Passive$1, create, deps); 17104 } 17105 } 17106 17107 function updateEffect(create, deps) { 17108 return updateEffectImpl(Passive, Passive$1, create, deps); 17109 } 17110 17111 function mountInsertionEffect(create, deps) { 17112 return mountEffectImpl(Update, Insertion, create, deps); 17113 } 17114 17115 function updateInsertionEffect(create, deps) { 17116 return updateEffectImpl(Update, Insertion, create, deps); 17117 } 17118 17119 function mountLayoutEffect(create, deps) { 17120 var fiberFlags = Update; 17121 17122 { 17123 fiberFlags |= LayoutStatic; 17124 } 17125 17126 if ( (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { 17127 fiberFlags |= MountLayoutDev; 17128 } 17129 17130 return mountEffectImpl(fiberFlags, Layout, create, deps); 17131 } 17132 17133 function updateLayoutEffect(create, deps) { 17134 return updateEffectImpl(Update, Layout, create, deps); 17135 } 17136 17137 function imperativeHandleEffect(create, ref) { 17138 if (typeof ref === 'function') { 17139 var refCallback = ref; 17140 17141 var _inst = create(); 17142 17143 refCallback(_inst); 17144 return function () { 17145 refCallback(null); 17146 }; 17147 } else if (ref !== null && ref !== undefined) { 17148 var refObject = ref; 17149 17150 { 17151 if (!refObject.hasOwnProperty('current')) { 17152 error('Expected useImperativeHandle() first argument to either be a ' + 'ref callback or React.createRef() object. Instead received: %s.', 'an object with keys {' + Object.keys(refObject).join(', ') + '}'); 17153 } 17154 } 17155 17156 var _inst2 = create(); 17157 17158 refObject.current = _inst2; 17159 return function () { 17160 refObject.current = null; 17161 }; 17162 } 17163 } 17164 17165 function mountImperativeHandle(ref, create, deps) { 17166 { 17167 if (typeof create !== 'function') { 17168 error('Expected useImperativeHandle() second argument to be a function ' + 'that creates a handle. Instead received: %s.', create !== null ? typeof create : 'null'); 17169 } 17170 } // TODO: If deps are provided, should we skip comparing the ref itself? 17171 17172 17173 var effectDeps = deps !== null && deps !== undefined ? deps.concat([ref]) : null; 17174 var fiberFlags = Update; 17175 17176 { 17177 fiberFlags |= LayoutStatic; 17178 } 17179 17180 if ( (currentlyRenderingFiber$1.mode & StrictEffectsMode) !== NoMode) { 17181 fiberFlags |= MountLayoutDev; 17182 } 17183 17184 return mountEffectImpl(fiberFlags, Layout, imperativeHandleEffect.bind(null, create, ref), effectDeps); 17185 } 17186 17187 function updateImperativeHandle(ref, create, deps) { 17188 { 17189 if (typeof create !== 'function') { 17190 error('Expected useImperativeHandle() second argument to be a function ' + 'that creates a handle. Instead received: %s.', create !== null ? typeof create : 'null'); 17191 } 17192 } // TODO: If deps are provided, should we skip comparing the ref itself? 17193 17194 17195 var effectDeps = deps !== null && deps !== undefined ? deps.concat([ref]) : null; 17196 return updateEffectImpl(Update, Layout, imperativeHandleEffect.bind(null, create, ref), effectDeps); 17197 } 17198 17199 function mountDebugValue(value, formatterFn) {// This hook is normally a no-op. 17200 // The react-debug-hooks package injects its own implementation 17201 // so that e.g. DevTools can display custom hook values. 17202 } 17203 17204 var updateDebugValue = mountDebugValue; 17205 17206 function mountCallback(callback, deps) { 17207 var hook = mountWorkInProgressHook(); 17208 var nextDeps = deps === undefined ? null : deps; 17209 hook.memoizedState = [callback, nextDeps]; 17210 return callback; 17211 } 17212 17213 function updateCallback(callback, deps) { 17214 var hook = updateWorkInProgressHook(); 17215 var nextDeps = deps === undefined ? null : deps; 17216 var prevState = hook.memoizedState; 17217 17218 if (prevState !== null) { 17219 if (nextDeps !== null) { 17220 var prevDeps = prevState[1]; 17221 17222 if (areHookInputsEqual(nextDeps, prevDeps)) { 17223 return prevState[0]; 17224 } 17225 } 17226 } 17227 17228 hook.memoizedState = [callback, nextDeps]; 17229 return callback; 17230 } 17231 17232 function mountMemo(nextCreate, deps) { 17233 var hook = mountWorkInProgressHook(); 17234 var nextDeps = deps === undefined ? null : deps; 17235 var nextValue = nextCreate(); 17236 hook.memoizedState = [nextValue, nextDeps]; 17237 return nextValue; 17238 } 17239 17240 function updateMemo(nextCreate, deps) { 17241 var hook = updateWorkInProgressHook(); 17242 var nextDeps = deps === undefined ? null : deps; 17243 var prevState = hook.memoizedState; 17244 17245 if (prevState !== null) { 17246 // Assume these are defined. If they're not, areHookInputsEqual will warn. 17247 if (nextDeps !== null) { 17248 var prevDeps = prevState[1]; 17249 17250 if (areHookInputsEqual(nextDeps, prevDeps)) { 17251 return prevState[0]; 17252 } 17253 } 17254 } 17255 17256 var nextValue = nextCreate(); 17257 hook.memoizedState = [nextValue, nextDeps]; 17258 return nextValue; 17259 } 17260 17261 function mountDeferredValue(value) { 17262 var hook = mountWorkInProgressHook(); 17263 hook.memoizedState = value; 17264 return value; 17265 } 17266 17267 function updateDeferredValue(value) { 17268 var hook = updateWorkInProgressHook(); 17269 var resolvedCurrentHook = currentHook; 17270 var prevValue = resolvedCurrentHook.memoizedState; 17271 return updateDeferredValueImpl(hook, prevValue, value); 17272 } 17273 17274 function rerenderDeferredValue(value) { 17275 var hook = updateWorkInProgressHook(); 17276 17277 if (currentHook === null) { 17278 // This is a rerender during a mount. 17279 hook.memoizedState = value; 17280 return value; 17281 } else { 17282 // This is a rerender during an update. 17283 var prevValue = currentHook.memoizedState; 17284 return updateDeferredValueImpl(hook, prevValue, value); 17285 } 17286 } 17287 17288 function updateDeferredValueImpl(hook, prevValue, value) { 17289 var shouldDeferValue = !includesOnlyNonUrgentLanes(renderLanes); 17290 17291 if (shouldDeferValue) { 17292 // This is an urgent update. If the value has changed, keep using the 17293 // previous value and spawn a deferred render to update it later. 17294 if (!objectIs(value, prevValue)) { 17295 // Schedule a deferred render 17296 var deferredLane = claimNextTransitionLane(); 17297 currentlyRenderingFiber$1.lanes = mergeLanes(currentlyRenderingFiber$1.lanes, deferredLane); 17298 markSkippedUpdateLanes(deferredLane); // Set this to true to indicate that the rendered value is inconsistent 17299 // from the latest value. The name "baseState" doesn't really match how we 17300 // use it because we're reusing a state hook field instead of creating a 17301 // new one. 17302 17303 hook.baseState = true; 17304 } // Reuse the previous value 17305 17306 17307 return prevValue; 17308 } else { 17309 // This is not an urgent update, so we can use the latest value regardless 17310 // of what it is. No need to defer it. 17311 // However, if we're currently inside a spawned render, then we need to mark 17312 // this as an update to prevent the fiber from bailing out. 17313 // 17314 // `baseState` is true when the current value is different from the rendered 17315 // value. The name doesn't really match how we use it because we're reusing 17316 // a state hook field instead of creating a new one. 17317 if (hook.baseState) { 17318 // Flip this back to false. 17319 hook.baseState = false; 17320 markWorkInProgressReceivedUpdate(); 17321 } 17322 17323 hook.memoizedState = value; 17324 return value; 17325 } 17326 } 17327 17328 function startTransition(setPending, callback, options) { 17329 var previousPriority = getCurrentUpdatePriority(); 17330 setCurrentUpdatePriority(higherEventPriority(previousPriority, ContinuousEventPriority)); 17331 setPending(true); 17332 var prevTransition = ReactCurrentBatchConfig$2.transition; 17333 ReactCurrentBatchConfig$2.transition = {}; 17334 var currentTransition = ReactCurrentBatchConfig$2.transition; 17335 17336 { 17337 ReactCurrentBatchConfig$2.transition._updatedFibers = new Set(); 17338 } 17339 17340 try { 17341 setPending(false); 17342 callback(); 17343 } finally { 17344 setCurrentUpdatePriority(previousPriority); 17345 ReactCurrentBatchConfig$2.transition = prevTransition; 17346 17347 { 17348 if (prevTransition === null && currentTransition._updatedFibers) { 17349 var updatedFibersCount = currentTransition._updatedFibers.size; 17350 17351 if (updatedFibersCount > 10) { 17352 warn('Detected a large number of updates inside startTransition. ' + 'If this is due to a subscription please re-write it to use React provided hooks. ' + 'Otherwise concurrent mode guarantees are off the table.'); 17353 } 17354 17355 currentTransition._updatedFibers.clear(); 17356 } 17357 } 17358 } 17359 } 17360 17361 function mountTransition() { 17362 var _mountState = mountState(false), 17363 isPending = _mountState[0], 17364 setPending = _mountState[1]; // The `start` method never changes. 17365 17366 17367 var start = startTransition.bind(null, setPending); 17368 var hook = mountWorkInProgressHook(); 17369 hook.memoizedState = start; 17370 return [isPending, start]; 17371 } 17372 17373 function updateTransition() { 17374 var _updateState = updateState(), 17375 isPending = _updateState[0]; 17376 17377 var hook = updateWorkInProgressHook(); 17378 var start = hook.memoizedState; 17379 return [isPending, start]; 17380 } 17381 17382 function rerenderTransition() { 17383 var _rerenderState = rerenderState(), 17384 isPending = _rerenderState[0]; 17385 17386 var hook = updateWorkInProgressHook(); 17387 var start = hook.memoizedState; 17388 return [isPending, start]; 17389 } 17390 17391 var isUpdatingOpaqueValueInRenderPhase = false; 17392 function getIsUpdatingOpaqueValueInRenderPhaseInDEV() { 17393 { 17394 return isUpdatingOpaqueValueInRenderPhase; 17395 } 17396 } 17397 17398 function mountId() { 17399 var hook = mountWorkInProgressHook(); 17400 var root = getWorkInProgressRoot(); // TODO: In Fizz, id generation is specific to each server config. Maybe we 17401 // should do this in Fiber, too? Deferring this decision for now because 17402 // there's no other place to store the prefix except for an internal field on 17403 // the public createRoot object, which the fiber tree does not currently have 17404 // a reference to. 17405 17406 var identifierPrefix = root.identifierPrefix; 17407 var id; 17408 17409 if (getIsHydrating()) { 17410 var treeId = getTreeId(); // Use a captial R prefix for server-generated ids. 17411 17412 id = ':' + identifierPrefix + 'R' + treeId; // Unless this is the first id at this level, append a number at the end 17413 // that represents the position of this useId hook among all the useId 17414 // hooks for this fiber. 17415 17416 var localId = localIdCounter++; 17417 17418 if (localId > 0) { 17419 id += 'H' + localId.toString(32); 17420 } 17421 17422 id += ':'; 17423 } else { 17424 // Use a lowercase r prefix for client-generated ids. 17425 var globalClientId = globalClientIdCounter++; 17426 id = ':' + identifierPrefix + 'r' + globalClientId.toString(32) + ':'; 17427 } 17428 17429 hook.memoizedState = id; 17430 return id; 17431 } 17432 17433 function updateId() { 17434 var hook = updateWorkInProgressHook(); 17435 var id = hook.memoizedState; 17436 return id; 17437 } 17438 17439 function dispatchReducerAction(fiber, queue, action) { 17440 { 17441 if (typeof arguments[3] === 'function') { 17442 error("State updates from the useState() and useReducer() Hooks don't support the " + 'second callback argument. To execute a side effect after ' + 'rendering, declare it in the component body with useEffect().'); 17443 } 17444 } 17445 17446 var lane = requestUpdateLane(fiber); 17447 var update = { 17448 lane: lane, 17449 action: action, 17450 hasEagerState: false, 17451 eagerState: null, 17452 next: null 17453 }; 17454 17455 if (isRenderPhaseUpdate(fiber)) { 17456 enqueueRenderPhaseUpdate(queue, update); 17457 } else { 17458 var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); 17459 17460 if (root !== null) { 17461 var eventTime = requestEventTime(); 17462 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 17463 entangleTransitionUpdate(root, queue, lane); 17464 } 17465 } 17466 17467 markUpdateInDevTools(fiber, lane); 17468 } 17469 17470 function dispatchSetState(fiber, queue, action) { 17471 { 17472 if (typeof arguments[3] === 'function') { 17473 error("State updates from the useState() and useReducer() Hooks don't support the " + 'second callback argument. To execute a side effect after ' + 'rendering, declare it in the component body with useEffect().'); 17474 } 17475 } 17476 17477 var lane = requestUpdateLane(fiber); 17478 var update = { 17479 lane: lane, 17480 action: action, 17481 hasEagerState: false, 17482 eagerState: null, 17483 next: null 17484 }; 17485 17486 if (isRenderPhaseUpdate(fiber)) { 17487 enqueueRenderPhaseUpdate(queue, update); 17488 } else { 17489 var alternate = fiber.alternate; 17490 17491 if (fiber.lanes === NoLanes && (alternate === null || alternate.lanes === NoLanes)) { 17492 // The queue is currently empty, which means we can eagerly compute the 17493 // next state before entering the render phase. If the new state is the 17494 // same as the current state, we may be able to bail out entirely. 17495 var lastRenderedReducer = queue.lastRenderedReducer; 17496 17497 if (lastRenderedReducer !== null) { 17498 var prevDispatcher; 17499 17500 { 17501 prevDispatcher = ReactCurrentDispatcher$1.current; 17502 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17503 } 17504 17505 try { 17506 var currentState = queue.lastRenderedState; 17507 var eagerState = lastRenderedReducer(currentState, action); // Stash the eagerly computed state, and the reducer used to compute 17508 // it, on the update object. If the reducer hasn't changed by the 17509 // time we enter the render phase, then the eager state can be used 17510 // without calling the reducer again. 17511 17512 update.hasEagerState = true; 17513 update.eagerState = eagerState; 17514 17515 if (objectIs(eagerState, currentState)) { 17516 // Fast path. We can bail out without scheduling React to re-render. 17517 // It's still possible that we'll need to rebase this update later, 17518 // if the component re-renders for a different reason and by that 17519 // time the reducer has changed. 17520 // TODO: Do we still need to entangle transitions in this case? 17521 enqueueConcurrentHookUpdateAndEagerlyBailout(fiber, queue, update, lane); 17522 return; 17523 } 17524 } catch (error) {// Suppress the error. It will throw again in the render phase. 17525 } finally { 17526 { 17527 ReactCurrentDispatcher$1.current = prevDispatcher; 17528 } 17529 } 17530 } 17531 } 17532 17533 var root = enqueueConcurrentHookUpdate(fiber, queue, update, lane); 17534 17535 if (root !== null) { 17536 var eventTime = requestEventTime(); 17537 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 17538 entangleTransitionUpdate(root, queue, lane); 17539 } 17540 } 17541 17542 markUpdateInDevTools(fiber, lane); 17543 } 17544 17545 function isRenderPhaseUpdate(fiber) { 17546 var alternate = fiber.alternate; 17547 return fiber === currentlyRenderingFiber$1 || alternate !== null && alternate === currentlyRenderingFiber$1; 17548 } 17549 17550 function enqueueRenderPhaseUpdate(queue, update) { 17551 // This is a render phase update. Stash it in a lazily-created map of 17552 // queue -> linked list of updates. After this render pass, we'll restart 17553 // and apply the stashed updates on top of the work-in-progress hook. 17554 didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true; 17555 var pending = queue.pending; 17556 17557 if (pending === null) { 17558 // This is the first update. Create a circular list. 17559 update.next = update; 17560 } else { 17561 update.next = pending.next; 17562 pending.next = update; 17563 } 17564 17565 queue.pending = update; 17566 } // TODO: Move to ReactFiberConcurrentUpdates? 17567 17568 17569 function entangleTransitionUpdate(root, queue, lane) { 17570 if (isTransitionLane(lane)) { 17571 var queueLanes = queue.lanes; // If any entangled lanes are no longer pending on the root, then they 17572 // must have finished. We can remove them from the shared queue, which 17573 // represents a superset of the actually pending lanes. In some cases we 17574 // may entangle more than we need to, but that's OK. In fact it's worse if 17575 // we *don't* entangle when we should. 17576 17577 queueLanes = intersectLanes(queueLanes, root.pendingLanes); // Entangle the new transition lane with the other transition lanes. 17578 17579 var newQueueLanes = mergeLanes(queueLanes, lane); 17580 queue.lanes = newQueueLanes; // Even if queue.lanes already include lane, we don't know for certain if 17581 // the lane finished since the last time we entangled it. So we need to 17582 // entangle it again, just to be sure. 17583 17584 markRootEntangled(root, newQueueLanes); 17585 } 17586 } 17587 17588 function markUpdateInDevTools(fiber, lane, action) { 17589 17590 { 17591 markStateUpdateScheduled(fiber, lane); 17592 } 17593 } 17594 17595 var ContextOnlyDispatcher = { 17596 readContext: readContext, 17597 useCallback: throwInvalidHookError, 17598 useContext: throwInvalidHookError, 17599 useEffect: throwInvalidHookError, 17600 useImperativeHandle: throwInvalidHookError, 17601 useInsertionEffect: throwInvalidHookError, 17602 useLayoutEffect: throwInvalidHookError, 17603 useMemo: throwInvalidHookError, 17604 useReducer: throwInvalidHookError, 17605 useRef: throwInvalidHookError, 17606 useState: throwInvalidHookError, 17607 useDebugValue: throwInvalidHookError, 17608 useDeferredValue: throwInvalidHookError, 17609 useTransition: throwInvalidHookError, 17610 useMutableSource: throwInvalidHookError, 17611 useSyncExternalStore: throwInvalidHookError, 17612 useId: throwInvalidHookError, 17613 unstable_isNewReconciler: enableNewReconciler 17614 }; 17615 17616 var HooksDispatcherOnMountInDEV = null; 17617 var HooksDispatcherOnMountWithHookTypesInDEV = null; 17618 var HooksDispatcherOnUpdateInDEV = null; 17619 var HooksDispatcherOnRerenderInDEV = null; 17620 var InvalidNestedHooksDispatcherOnMountInDEV = null; 17621 var InvalidNestedHooksDispatcherOnUpdateInDEV = null; 17622 var InvalidNestedHooksDispatcherOnRerenderInDEV = null; 17623 17624 { 17625 var warnInvalidContextAccess = function () { 17626 error('Context can only be read while React is rendering. ' + 'In classes, you can read it in the render method or getDerivedStateFromProps. ' + 'In function components, you can read it directly in the function body, but not ' + 'inside Hooks like useReducer() or useMemo().'); 17627 }; 17628 17629 var warnInvalidHookAccess = function () { 17630 error('Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' + 'You can only call Hooks at the top level of your React function. ' + 'For more information, see ' + 'https://reactjs.org/link/rules-of-hooks'); 17631 }; 17632 17633 HooksDispatcherOnMountInDEV = { 17634 readContext: function (context) { 17635 return readContext(context); 17636 }, 17637 useCallback: function (callback, deps) { 17638 currentHookNameInDev = 'useCallback'; 17639 mountHookTypesDev(); 17640 checkDepsAreArrayDev(deps); 17641 return mountCallback(callback, deps); 17642 }, 17643 useContext: function (context) { 17644 currentHookNameInDev = 'useContext'; 17645 mountHookTypesDev(); 17646 return readContext(context); 17647 }, 17648 useEffect: function (create, deps) { 17649 currentHookNameInDev = 'useEffect'; 17650 mountHookTypesDev(); 17651 checkDepsAreArrayDev(deps); 17652 return mountEffect(create, deps); 17653 }, 17654 useImperativeHandle: function (ref, create, deps) { 17655 currentHookNameInDev = 'useImperativeHandle'; 17656 mountHookTypesDev(); 17657 checkDepsAreArrayDev(deps); 17658 return mountImperativeHandle(ref, create, deps); 17659 }, 17660 useInsertionEffect: function (create, deps) { 17661 currentHookNameInDev = 'useInsertionEffect'; 17662 mountHookTypesDev(); 17663 checkDepsAreArrayDev(deps); 17664 return mountInsertionEffect(create, deps); 17665 }, 17666 useLayoutEffect: function (create, deps) { 17667 currentHookNameInDev = 'useLayoutEffect'; 17668 mountHookTypesDev(); 17669 checkDepsAreArrayDev(deps); 17670 return mountLayoutEffect(create, deps); 17671 }, 17672 useMemo: function (create, deps) { 17673 currentHookNameInDev = 'useMemo'; 17674 mountHookTypesDev(); 17675 checkDepsAreArrayDev(deps); 17676 var prevDispatcher = ReactCurrentDispatcher$1.current; 17677 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17678 17679 try { 17680 return mountMemo(create, deps); 17681 } finally { 17682 ReactCurrentDispatcher$1.current = prevDispatcher; 17683 } 17684 }, 17685 useReducer: function (reducer, initialArg, init) { 17686 currentHookNameInDev = 'useReducer'; 17687 mountHookTypesDev(); 17688 var prevDispatcher = ReactCurrentDispatcher$1.current; 17689 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17690 17691 try { 17692 return mountReducer(reducer, initialArg, init); 17693 } finally { 17694 ReactCurrentDispatcher$1.current = prevDispatcher; 17695 } 17696 }, 17697 useRef: function (initialValue) { 17698 currentHookNameInDev = 'useRef'; 17699 mountHookTypesDev(); 17700 return mountRef(initialValue); 17701 }, 17702 useState: function (initialState) { 17703 currentHookNameInDev = 'useState'; 17704 mountHookTypesDev(); 17705 var prevDispatcher = ReactCurrentDispatcher$1.current; 17706 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17707 17708 try { 17709 return mountState(initialState); 17710 } finally { 17711 ReactCurrentDispatcher$1.current = prevDispatcher; 17712 } 17713 }, 17714 useDebugValue: function (value, formatterFn) { 17715 currentHookNameInDev = 'useDebugValue'; 17716 mountHookTypesDev(); 17717 return mountDebugValue(); 17718 }, 17719 useDeferredValue: function (value) { 17720 currentHookNameInDev = 'useDeferredValue'; 17721 mountHookTypesDev(); 17722 return mountDeferredValue(value); 17723 }, 17724 useTransition: function () { 17725 currentHookNameInDev = 'useTransition'; 17726 mountHookTypesDev(); 17727 return mountTransition(); 17728 }, 17729 useMutableSource: function (source, getSnapshot, subscribe) { 17730 currentHookNameInDev = 'useMutableSource'; 17731 mountHookTypesDev(); 17732 return mountMutableSource(); 17733 }, 17734 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17735 currentHookNameInDev = 'useSyncExternalStore'; 17736 mountHookTypesDev(); 17737 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); 17738 }, 17739 useId: function () { 17740 currentHookNameInDev = 'useId'; 17741 mountHookTypesDev(); 17742 return mountId(); 17743 }, 17744 unstable_isNewReconciler: enableNewReconciler 17745 }; 17746 17747 HooksDispatcherOnMountWithHookTypesInDEV = { 17748 readContext: function (context) { 17749 return readContext(context); 17750 }, 17751 useCallback: function (callback, deps) { 17752 currentHookNameInDev = 'useCallback'; 17753 updateHookTypesDev(); 17754 return mountCallback(callback, deps); 17755 }, 17756 useContext: function (context) { 17757 currentHookNameInDev = 'useContext'; 17758 updateHookTypesDev(); 17759 return readContext(context); 17760 }, 17761 useEffect: function (create, deps) { 17762 currentHookNameInDev = 'useEffect'; 17763 updateHookTypesDev(); 17764 return mountEffect(create, deps); 17765 }, 17766 useImperativeHandle: function (ref, create, deps) { 17767 currentHookNameInDev = 'useImperativeHandle'; 17768 updateHookTypesDev(); 17769 return mountImperativeHandle(ref, create, deps); 17770 }, 17771 useInsertionEffect: function (create, deps) { 17772 currentHookNameInDev = 'useInsertionEffect'; 17773 updateHookTypesDev(); 17774 return mountInsertionEffect(create, deps); 17775 }, 17776 useLayoutEffect: function (create, deps) { 17777 currentHookNameInDev = 'useLayoutEffect'; 17778 updateHookTypesDev(); 17779 return mountLayoutEffect(create, deps); 17780 }, 17781 useMemo: function (create, deps) { 17782 currentHookNameInDev = 'useMemo'; 17783 updateHookTypesDev(); 17784 var prevDispatcher = ReactCurrentDispatcher$1.current; 17785 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17786 17787 try { 17788 return mountMemo(create, deps); 17789 } finally { 17790 ReactCurrentDispatcher$1.current = prevDispatcher; 17791 } 17792 }, 17793 useReducer: function (reducer, initialArg, init) { 17794 currentHookNameInDev = 'useReducer'; 17795 updateHookTypesDev(); 17796 var prevDispatcher = ReactCurrentDispatcher$1.current; 17797 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17798 17799 try { 17800 return mountReducer(reducer, initialArg, init); 17801 } finally { 17802 ReactCurrentDispatcher$1.current = prevDispatcher; 17803 } 17804 }, 17805 useRef: function (initialValue) { 17806 currentHookNameInDev = 'useRef'; 17807 updateHookTypesDev(); 17808 return mountRef(initialValue); 17809 }, 17810 useState: function (initialState) { 17811 currentHookNameInDev = 'useState'; 17812 updateHookTypesDev(); 17813 var prevDispatcher = ReactCurrentDispatcher$1.current; 17814 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 17815 17816 try { 17817 return mountState(initialState); 17818 } finally { 17819 ReactCurrentDispatcher$1.current = prevDispatcher; 17820 } 17821 }, 17822 useDebugValue: function (value, formatterFn) { 17823 currentHookNameInDev = 'useDebugValue'; 17824 updateHookTypesDev(); 17825 return mountDebugValue(); 17826 }, 17827 useDeferredValue: function (value) { 17828 currentHookNameInDev = 'useDeferredValue'; 17829 updateHookTypesDev(); 17830 return mountDeferredValue(value); 17831 }, 17832 useTransition: function () { 17833 currentHookNameInDev = 'useTransition'; 17834 updateHookTypesDev(); 17835 return mountTransition(); 17836 }, 17837 useMutableSource: function (source, getSnapshot, subscribe) { 17838 currentHookNameInDev = 'useMutableSource'; 17839 updateHookTypesDev(); 17840 return mountMutableSource(); 17841 }, 17842 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17843 currentHookNameInDev = 'useSyncExternalStore'; 17844 updateHookTypesDev(); 17845 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); 17846 }, 17847 useId: function () { 17848 currentHookNameInDev = 'useId'; 17849 updateHookTypesDev(); 17850 return mountId(); 17851 }, 17852 unstable_isNewReconciler: enableNewReconciler 17853 }; 17854 17855 HooksDispatcherOnUpdateInDEV = { 17856 readContext: function (context) { 17857 return readContext(context); 17858 }, 17859 useCallback: function (callback, deps) { 17860 currentHookNameInDev = 'useCallback'; 17861 updateHookTypesDev(); 17862 return updateCallback(callback, deps); 17863 }, 17864 useContext: function (context) { 17865 currentHookNameInDev = 'useContext'; 17866 updateHookTypesDev(); 17867 return readContext(context); 17868 }, 17869 useEffect: function (create, deps) { 17870 currentHookNameInDev = 'useEffect'; 17871 updateHookTypesDev(); 17872 return updateEffect(create, deps); 17873 }, 17874 useImperativeHandle: function (ref, create, deps) { 17875 currentHookNameInDev = 'useImperativeHandle'; 17876 updateHookTypesDev(); 17877 return updateImperativeHandle(ref, create, deps); 17878 }, 17879 useInsertionEffect: function (create, deps) { 17880 currentHookNameInDev = 'useInsertionEffect'; 17881 updateHookTypesDev(); 17882 return updateInsertionEffect(create, deps); 17883 }, 17884 useLayoutEffect: function (create, deps) { 17885 currentHookNameInDev = 'useLayoutEffect'; 17886 updateHookTypesDev(); 17887 return updateLayoutEffect(create, deps); 17888 }, 17889 useMemo: function (create, deps) { 17890 currentHookNameInDev = 'useMemo'; 17891 updateHookTypesDev(); 17892 var prevDispatcher = ReactCurrentDispatcher$1.current; 17893 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17894 17895 try { 17896 return updateMemo(create, deps); 17897 } finally { 17898 ReactCurrentDispatcher$1.current = prevDispatcher; 17899 } 17900 }, 17901 useReducer: function (reducer, initialArg, init) { 17902 currentHookNameInDev = 'useReducer'; 17903 updateHookTypesDev(); 17904 var prevDispatcher = ReactCurrentDispatcher$1.current; 17905 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17906 17907 try { 17908 return updateReducer(reducer, initialArg, init); 17909 } finally { 17910 ReactCurrentDispatcher$1.current = prevDispatcher; 17911 } 17912 }, 17913 useRef: function (initialValue) { 17914 currentHookNameInDev = 'useRef'; 17915 updateHookTypesDev(); 17916 return updateRef(); 17917 }, 17918 useState: function (initialState) { 17919 currentHookNameInDev = 'useState'; 17920 updateHookTypesDev(); 17921 var prevDispatcher = ReactCurrentDispatcher$1.current; 17922 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 17923 17924 try { 17925 return updateState(initialState); 17926 } finally { 17927 ReactCurrentDispatcher$1.current = prevDispatcher; 17928 } 17929 }, 17930 useDebugValue: function (value, formatterFn) { 17931 currentHookNameInDev = 'useDebugValue'; 17932 updateHookTypesDev(); 17933 return updateDebugValue(); 17934 }, 17935 useDeferredValue: function (value) { 17936 currentHookNameInDev = 'useDeferredValue'; 17937 updateHookTypesDev(); 17938 return updateDeferredValue(value); 17939 }, 17940 useTransition: function () { 17941 currentHookNameInDev = 'useTransition'; 17942 updateHookTypesDev(); 17943 return updateTransition(); 17944 }, 17945 useMutableSource: function (source, getSnapshot, subscribe) { 17946 currentHookNameInDev = 'useMutableSource'; 17947 updateHookTypesDev(); 17948 return updateMutableSource(); 17949 }, 17950 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 17951 currentHookNameInDev = 'useSyncExternalStore'; 17952 updateHookTypesDev(); 17953 return updateSyncExternalStore(subscribe, getSnapshot); 17954 }, 17955 useId: function () { 17956 currentHookNameInDev = 'useId'; 17957 updateHookTypesDev(); 17958 return updateId(); 17959 }, 17960 unstable_isNewReconciler: enableNewReconciler 17961 }; 17962 17963 HooksDispatcherOnRerenderInDEV = { 17964 readContext: function (context) { 17965 return readContext(context); 17966 }, 17967 useCallback: function (callback, deps) { 17968 currentHookNameInDev = 'useCallback'; 17969 updateHookTypesDev(); 17970 return updateCallback(callback, deps); 17971 }, 17972 useContext: function (context) { 17973 currentHookNameInDev = 'useContext'; 17974 updateHookTypesDev(); 17975 return readContext(context); 17976 }, 17977 useEffect: function (create, deps) { 17978 currentHookNameInDev = 'useEffect'; 17979 updateHookTypesDev(); 17980 return updateEffect(create, deps); 17981 }, 17982 useImperativeHandle: function (ref, create, deps) { 17983 currentHookNameInDev = 'useImperativeHandle'; 17984 updateHookTypesDev(); 17985 return updateImperativeHandle(ref, create, deps); 17986 }, 17987 useInsertionEffect: function (create, deps) { 17988 currentHookNameInDev = 'useInsertionEffect'; 17989 updateHookTypesDev(); 17990 return updateInsertionEffect(create, deps); 17991 }, 17992 useLayoutEffect: function (create, deps) { 17993 currentHookNameInDev = 'useLayoutEffect'; 17994 updateHookTypesDev(); 17995 return updateLayoutEffect(create, deps); 17996 }, 17997 useMemo: function (create, deps) { 17998 currentHookNameInDev = 'useMemo'; 17999 updateHookTypesDev(); 18000 var prevDispatcher = ReactCurrentDispatcher$1.current; 18001 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; 18002 18003 try { 18004 return updateMemo(create, deps); 18005 } finally { 18006 ReactCurrentDispatcher$1.current = prevDispatcher; 18007 } 18008 }, 18009 useReducer: function (reducer, initialArg, init) { 18010 currentHookNameInDev = 'useReducer'; 18011 updateHookTypesDev(); 18012 var prevDispatcher = ReactCurrentDispatcher$1.current; 18013 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; 18014 18015 try { 18016 return rerenderReducer(reducer, initialArg, init); 18017 } finally { 18018 ReactCurrentDispatcher$1.current = prevDispatcher; 18019 } 18020 }, 18021 useRef: function (initialValue) { 18022 currentHookNameInDev = 'useRef'; 18023 updateHookTypesDev(); 18024 return updateRef(); 18025 }, 18026 useState: function (initialState) { 18027 currentHookNameInDev = 'useState'; 18028 updateHookTypesDev(); 18029 var prevDispatcher = ReactCurrentDispatcher$1.current; 18030 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnRerenderInDEV; 18031 18032 try { 18033 return rerenderState(initialState); 18034 } finally { 18035 ReactCurrentDispatcher$1.current = prevDispatcher; 18036 } 18037 }, 18038 useDebugValue: function (value, formatterFn) { 18039 currentHookNameInDev = 'useDebugValue'; 18040 updateHookTypesDev(); 18041 return updateDebugValue(); 18042 }, 18043 useDeferredValue: function (value) { 18044 currentHookNameInDev = 'useDeferredValue'; 18045 updateHookTypesDev(); 18046 return rerenderDeferredValue(value); 18047 }, 18048 useTransition: function () { 18049 currentHookNameInDev = 'useTransition'; 18050 updateHookTypesDev(); 18051 return rerenderTransition(); 18052 }, 18053 useMutableSource: function (source, getSnapshot, subscribe) { 18054 currentHookNameInDev = 'useMutableSource'; 18055 updateHookTypesDev(); 18056 return updateMutableSource(); 18057 }, 18058 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 18059 currentHookNameInDev = 'useSyncExternalStore'; 18060 updateHookTypesDev(); 18061 return updateSyncExternalStore(subscribe, getSnapshot); 18062 }, 18063 useId: function () { 18064 currentHookNameInDev = 'useId'; 18065 updateHookTypesDev(); 18066 return updateId(); 18067 }, 18068 unstable_isNewReconciler: enableNewReconciler 18069 }; 18070 18071 InvalidNestedHooksDispatcherOnMountInDEV = { 18072 readContext: function (context) { 18073 warnInvalidContextAccess(); 18074 return readContext(context); 18075 }, 18076 useCallback: function (callback, deps) { 18077 currentHookNameInDev = 'useCallback'; 18078 warnInvalidHookAccess(); 18079 mountHookTypesDev(); 18080 return mountCallback(callback, deps); 18081 }, 18082 useContext: function (context) { 18083 currentHookNameInDev = 'useContext'; 18084 warnInvalidHookAccess(); 18085 mountHookTypesDev(); 18086 return readContext(context); 18087 }, 18088 useEffect: function (create, deps) { 18089 currentHookNameInDev = 'useEffect'; 18090 warnInvalidHookAccess(); 18091 mountHookTypesDev(); 18092 return mountEffect(create, deps); 18093 }, 18094 useImperativeHandle: function (ref, create, deps) { 18095 currentHookNameInDev = 'useImperativeHandle'; 18096 warnInvalidHookAccess(); 18097 mountHookTypesDev(); 18098 return mountImperativeHandle(ref, create, deps); 18099 }, 18100 useInsertionEffect: function (create, deps) { 18101 currentHookNameInDev = 'useInsertionEffect'; 18102 warnInvalidHookAccess(); 18103 mountHookTypesDev(); 18104 return mountInsertionEffect(create, deps); 18105 }, 18106 useLayoutEffect: function (create, deps) { 18107 currentHookNameInDev = 'useLayoutEffect'; 18108 warnInvalidHookAccess(); 18109 mountHookTypesDev(); 18110 return mountLayoutEffect(create, deps); 18111 }, 18112 useMemo: function (create, deps) { 18113 currentHookNameInDev = 'useMemo'; 18114 warnInvalidHookAccess(); 18115 mountHookTypesDev(); 18116 var prevDispatcher = ReactCurrentDispatcher$1.current; 18117 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 18118 18119 try { 18120 return mountMemo(create, deps); 18121 } finally { 18122 ReactCurrentDispatcher$1.current = prevDispatcher; 18123 } 18124 }, 18125 useReducer: function (reducer, initialArg, init) { 18126 currentHookNameInDev = 'useReducer'; 18127 warnInvalidHookAccess(); 18128 mountHookTypesDev(); 18129 var prevDispatcher = ReactCurrentDispatcher$1.current; 18130 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 18131 18132 try { 18133 return mountReducer(reducer, initialArg, init); 18134 } finally { 18135 ReactCurrentDispatcher$1.current = prevDispatcher; 18136 } 18137 }, 18138 useRef: function (initialValue) { 18139 currentHookNameInDev = 'useRef'; 18140 warnInvalidHookAccess(); 18141 mountHookTypesDev(); 18142 return mountRef(initialValue); 18143 }, 18144 useState: function (initialState) { 18145 currentHookNameInDev = 'useState'; 18146 warnInvalidHookAccess(); 18147 mountHookTypesDev(); 18148 var prevDispatcher = ReactCurrentDispatcher$1.current; 18149 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV; 18150 18151 try { 18152 return mountState(initialState); 18153 } finally { 18154 ReactCurrentDispatcher$1.current = prevDispatcher; 18155 } 18156 }, 18157 useDebugValue: function (value, formatterFn) { 18158 currentHookNameInDev = 'useDebugValue'; 18159 warnInvalidHookAccess(); 18160 mountHookTypesDev(); 18161 return mountDebugValue(); 18162 }, 18163 useDeferredValue: function (value) { 18164 currentHookNameInDev = 'useDeferredValue'; 18165 warnInvalidHookAccess(); 18166 mountHookTypesDev(); 18167 return mountDeferredValue(value); 18168 }, 18169 useTransition: function () { 18170 currentHookNameInDev = 'useTransition'; 18171 warnInvalidHookAccess(); 18172 mountHookTypesDev(); 18173 return mountTransition(); 18174 }, 18175 useMutableSource: function (source, getSnapshot, subscribe) { 18176 currentHookNameInDev = 'useMutableSource'; 18177 warnInvalidHookAccess(); 18178 mountHookTypesDev(); 18179 return mountMutableSource(); 18180 }, 18181 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 18182 currentHookNameInDev = 'useSyncExternalStore'; 18183 warnInvalidHookAccess(); 18184 mountHookTypesDev(); 18185 return mountSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); 18186 }, 18187 useId: function () { 18188 currentHookNameInDev = 'useId'; 18189 warnInvalidHookAccess(); 18190 mountHookTypesDev(); 18191 return mountId(); 18192 }, 18193 unstable_isNewReconciler: enableNewReconciler 18194 }; 18195 18196 InvalidNestedHooksDispatcherOnUpdateInDEV = { 18197 readContext: function (context) { 18198 warnInvalidContextAccess(); 18199 return readContext(context); 18200 }, 18201 useCallback: function (callback, deps) { 18202 currentHookNameInDev = 'useCallback'; 18203 warnInvalidHookAccess(); 18204 updateHookTypesDev(); 18205 return updateCallback(callback, deps); 18206 }, 18207 useContext: function (context) { 18208 currentHookNameInDev = 'useContext'; 18209 warnInvalidHookAccess(); 18210 updateHookTypesDev(); 18211 return readContext(context); 18212 }, 18213 useEffect: function (create, deps) { 18214 currentHookNameInDev = 'useEffect'; 18215 warnInvalidHookAccess(); 18216 updateHookTypesDev(); 18217 return updateEffect(create, deps); 18218 }, 18219 useImperativeHandle: function (ref, create, deps) { 18220 currentHookNameInDev = 'useImperativeHandle'; 18221 warnInvalidHookAccess(); 18222 updateHookTypesDev(); 18223 return updateImperativeHandle(ref, create, deps); 18224 }, 18225 useInsertionEffect: function (create, deps) { 18226 currentHookNameInDev = 'useInsertionEffect'; 18227 warnInvalidHookAccess(); 18228 updateHookTypesDev(); 18229 return updateInsertionEffect(create, deps); 18230 }, 18231 useLayoutEffect: function (create, deps) { 18232 currentHookNameInDev = 'useLayoutEffect'; 18233 warnInvalidHookAccess(); 18234 updateHookTypesDev(); 18235 return updateLayoutEffect(create, deps); 18236 }, 18237 useMemo: function (create, deps) { 18238 currentHookNameInDev = 'useMemo'; 18239 warnInvalidHookAccess(); 18240 updateHookTypesDev(); 18241 var prevDispatcher = ReactCurrentDispatcher$1.current; 18242 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 18243 18244 try { 18245 return updateMemo(create, deps); 18246 } finally { 18247 ReactCurrentDispatcher$1.current = prevDispatcher; 18248 } 18249 }, 18250 useReducer: function (reducer, initialArg, init) { 18251 currentHookNameInDev = 'useReducer'; 18252 warnInvalidHookAccess(); 18253 updateHookTypesDev(); 18254 var prevDispatcher = ReactCurrentDispatcher$1.current; 18255 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 18256 18257 try { 18258 return updateReducer(reducer, initialArg, init); 18259 } finally { 18260 ReactCurrentDispatcher$1.current = prevDispatcher; 18261 } 18262 }, 18263 useRef: function (initialValue) { 18264 currentHookNameInDev = 'useRef'; 18265 warnInvalidHookAccess(); 18266 updateHookTypesDev(); 18267 return updateRef(); 18268 }, 18269 useState: function (initialState) { 18270 currentHookNameInDev = 'useState'; 18271 warnInvalidHookAccess(); 18272 updateHookTypesDev(); 18273 var prevDispatcher = ReactCurrentDispatcher$1.current; 18274 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 18275 18276 try { 18277 return updateState(initialState); 18278 } finally { 18279 ReactCurrentDispatcher$1.current = prevDispatcher; 18280 } 18281 }, 18282 useDebugValue: function (value, formatterFn) { 18283 currentHookNameInDev = 'useDebugValue'; 18284 warnInvalidHookAccess(); 18285 updateHookTypesDev(); 18286 return updateDebugValue(); 18287 }, 18288 useDeferredValue: function (value) { 18289 currentHookNameInDev = 'useDeferredValue'; 18290 warnInvalidHookAccess(); 18291 updateHookTypesDev(); 18292 return updateDeferredValue(value); 18293 }, 18294 useTransition: function () { 18295 currentHookNameInDev = 'useTransition'; 18296 warnInvalidHookAccess(); 18297 updateHookTypesDev(); 18298 return updateTransition(); 18299 }, 18300 useMutableSource: function (source, getSnapshot, subscribe) { 18301 currentHookNameInDev = 'useMutableSource'; 18302 warnInvalidHookAccess(); 18303 updateHookTypesDev(); 18304 return updateMutableSource(); 18305 }, 18306 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 18307 currentHookNameInDev = 'useSyncExternalStore'; 18308 warnInvalidHookAccess(); 18309 updateHookTypesDev(); 18310 return updateSyncExternalStore(subscribe, getSnapshot); 18311 }, 18312 useId: function () { 18313 currentHookNameInDev = 'useId'; 18314 warnInvalidHookAccess(); 18315 updateHookTypesDev(); 18316 return updateId(); 18317 }, 18318 unstable_isNewReconciler: enableNewReconciler 18319 }; 18320 18321 InvalidNestedHooksDispatcherOnRerenderInDEV = { 18322 readContext: function (context) { 18323 warnInvalidContextAccess(); 18324 return readContext(context); 18325 }, 18326 useCallback: function (callback, deps) { 18327 currentHookNameInDev = 'useCallback'; 18328 warnInvalidHookAccess(); 18329 updateHookTypesDev(); 18330 return updateCallback(callback, deps); 18331 }, 18332 useContext: function (context) { 18333 currentHookNameInDev = 'useContext'; 18334 warnInvalidHookAccess(); 18335 updateHookTypesDev(); 18336 return readContext(context); 18337 }, 18338 useEffect: function (create, deps) { 18339 currentHookNameInDev = 'useEffect'; 18340 warnInvalidHookAccess(); 18341 updateHookTypesDev(); 18342 return updateEffect(create, deps); 18343 }, 18344 useImperativeHandle: function (ref, create, deps) { 18345 currentHookNameInDev = 'useImperativeHandle'; 18346 warnInvalidHookAccess(); 18347 updateHookTypesDev(); 18348 return updateImperativeHandle(ref, create, deps); 18349 }, 18350 useInsertionEffect: function (create, deps) { 18351 currentHookNameInDev = 'useInsertionEffect'; 18352 warnInvalidHookAccess(); 18353 updateHookTypesDev(); 18354 return updateInsertionEffect(create, deps); 18355 }, 18356 useLayoutEffect: function (create, deps) { 18357 currentHookNameInDev = 'useLayoutEffect'; 18358 warnInvalidHookAccess(); 18359 updateHookTypesDev(); 18360 return updateLayoutEffect(create, deps); 18361 }, 18362 useMemo: function (create, deps) { 18363 currentHookNameInDev = 'useMemo'; 18364 warnInvalidHookAccess(); 18365 updateHookTypesDev(); 18366 var prevDispatcher = ReactCurrentDispatcher$1.current; 18367 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 18368 18369 try { 18370 return updateMemo(create, deps); 18371 } finally { 18372 ReactCurrentDispatcher$1.current = prevDispatcher; 18373 } 18374 }, 18375 useReducer: function (reducer, initialArg, init) { 18376 currentHookNameInDev = 'useReducer'; 18377 warnInvalidHookAccess(); 18378 updateHookTypesDev(); 18379 var prevDispatcher = ReactCurrentDispatcher$1.current; 18380 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 18381 18382 try { 18383 return rerenderReducer(reducer, initialArg, init); 18384 } finally { 18385 ReactCurrentDispatcher$1.current = prevDispatcher; 18386 } 18387 }, 18388 useRef: function (initialValue) { 18389 currentHookNameInDev = 'useRef'; 18390 warnInvalidHookAccess(); 18391 updateHookTypesDev(); 18392 return updateRef(); 18393 }, 18394 useState: function (initialState) { 18395 currentHookNameInDev = 'useState'; 18396 warnInvalidHookAccess(); 18397 updateHookTypesDev(); 18398 var prevDispatcher = ReactCurrentDispatcher$1.current; 18399 ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnUpdateInDEV; 18400 18401 try { 18402 return rerenderState(initialState); 18403 } finally { 18404 ReactCurrentDispatcher$1.current = prevDispatcher; 18405 } 18406 }, 18407 useDebugValue: function (value, formatterFn) { 18408 currentHookNameInDev = 'useDebugValue'; 18409 warnInvalidHookAccess(); 18410 updateHookTypesDev(); 18411 return updateDebugValue(); 18412 }, 18413 useDeferredValue: function (value) { 18414 currentHookNameInDev = 'useDeferredValue'; 18415 warnInvalidHookAccess(); 18416 updateHookTypesDev(); 18417 return rerenderDeferredValue(value); 18418 }, 18419 useTransition: function () { 18420 currentHookNameInDev = 'useTransition'; 18421 warnInvalidHookAccess(); 18422 updateHookTypesDev(); 18423 return rerenderTransition(); 18424 }, 18425 useMutableSource: function (source, getSnapshot, subscribe) { 18426 currentHookNameInDev = 'useMutableSource'; 18427 warnInvalidHookAccess(); 18428 updateHookTypesDev(); 18429 return updateMutableSource(); 18430 }, 18431 useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) { 18432 currentHookNameInDev = 'useSyncExternalStore'; 18433 warnInvalidHookAccess(); 18434 updateHookTypesDev(); 18435 return updateSyncExternalStore(subscribe, getSnapshot); 18436 }, 18437 useId: function () { 18438 currentHookNameInDev = 'useId'; 18439 warnInvalidHookAccess(); 18440 updateHookTypesDev(); 18441 return updateId(); 18442 }, 18443 unstable_isNewReconciler: enableNewReconciler 18444 }; 18445 } 18446 18447 var now$1 = unstable_now; 18448 var commitTime = 0; 18449 var layoutEffectStartTime = -1; 18450 var profilerStartTime = -1; 18451 var passiveEffectStartTime = -1; 18452 /** 18453 * Tracks whether the current update was a nested/cascading update (scheduled from a layout effect). 18454 * 18455 * The overall sequence is: 18456 * 1. render 18457 * 2. commit (and call `onRender`, `onCommit`) 18458 * 3. check for nested updates 18459 * 4. flush passive effects (and call `onPostCommit`) 18460 * 18461 * Nested updates are identified in step 3 above, 18462 * but step 4 still applies to the work that was just committed. 18463 * We use two flags to track nested updates then: 18464 * one tracks whether the upcoming update is a nested update, 18465 * and the other tracks whether the current update was a nested update. 18466 * The first value gets synced to the second at the start of the render phase. 18467 */ 18468 18469 var currentUpdateIsNested = false; 18470 var nestedUpdateScheduled = false; 18471 18472 function isCurrentUpdateNested() { 18473 return currentUpdateIsNested; 18474 } 18475 18476 function markNestedUpdateScheduled() { 18477 { 18478 nestedUpdateScheduled = true; 18479 } 18480 } 18481 18482 function resetNestedUpdateFlag() { 18483 { 18484 currentUpdateIsNested = false; 18485 nestedUpdateScheduled = false; 18486 } 18487 } 18488 18489 function syncNestedUpdateFlag() { 18490 { 18491 currentUpdateIsNested = nestedUpdateScheduled; 18492 nestedUpdateScheduled = false; 18493 } 18494 } 18495 18496 function getCommitTime() { 18497 return commitTime; 18498 } 18499 18500 function recordCommitTime() { 18501 18502 commitTime = now$1(); 18503 } 18504 18505 function startProfilerTimer(fiber) { 18506 18507 profilerStartTime = now$1(); 18508 18509 if (fiber.actualStartTime < 0) { 18510 fiber.actualStartTime = now$1(); 18511 } 18512 } 18513 18514 function stopProfilerTimerIfRunning(fiber) { 18515 18516 profilerStartTime = -1; 18517 } 18518 18519 function stopProfilerTimerIfRunningAndRecordDelta(fiber, overrideBaseTime) { 18520 18521 if (profilerStartTime >= 0) { 18522 var elapsedTime = now$1() - profilerStartTime; 18523 fiber.actualDuration += elapsedTime; 18524 18525 if (overrideBaseTime) { 18526 fiber.selfBaseDuration = elapsedTime; 18527 } 18528 18529 profilerStartTime = -1; 18530 } 18531 } 18532 18533 function recordLayoutEffectDuration(fiber) { 18534 18535 if (layoutEffectStartTime >= 0) { 18536 var elapsedTime = now$1() - layoutEffectStartTime; 18537 layoutEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor 18538 // Or the root (for the DevTools Profiler to read) 18539 18540 var parentFiber = fiber.return; 18541 18542 while (parentFiber !== null) { 18543 switch (parentFiber.tag) { 18544 case HostRoot: 18545 var root = parentFiber.stateNode; 18546 root.effectDuration += elapsedTime; 18547 return; 18548 18549 case Profiler: 18550 var parentStateNode = parentFiber.stateNode; 18551 parentStateNode.effectDuration += elapsedTime; 18552 return; 18553 } 18554 18555 parentFiber = parentFiber.return; 18556 } 18557 } 18558 } 18559 18560 function recordPassiveEffectDuration(fiber) { 18561 18562 if (passiveEffectStartTime >= 0) { 18563 var elapsedTime = now$1() - passiveEffectStartTime; 18564 passiveEffectStartTime = -1; // Store duration on the next nearest Profiler ancestor 18565 // Or the root (for the DevTools Profiler to read) 18566 18567 var parentFiber = fiber.return; 18568 18569 while (parentFiber !== null) { 18570 switch (parentFiber.tag) { 18571 case HostRoot: 18572 var root = parentFiber.stateNode; 18573 18574 if (root !== null) { 18575 root.passiveEffectDuration += elapsedTime; 18576 } 18577 18578 return; 18579 18580 case Profiler: 18581 var parentStateNode = parentFiber.stateNode; 18582 18583 if (parentStateNode !== null) { 18584 // Detached fibers have their state node cleared out. 18585 // In this case, the return pointer is also cleared out, 18586 // so we won't be able to report the time spent in this Profiler's subtree. 18587 parentStateNode.passiveEffectDuration += elapsedTime; 18588 } 18589 18590 return; 18591 } 18592 18593 parentFiber = parentFiber.return; 18594 } 18595 } 18596 } 18597 18598 function startLayoutEffectTimer() { 18599 18600 layoutEffectStartTime = now$1(); 18601 } 18602 18603 function startPassiveEffectTimer() { 18604 18605 passiveEffectStartTime = now$1(); 18606 } 18607 18608 function transferActualDuration(fiber) { 18609 // Transfer time spent rendering these children so we don't lose it 18610 // after we rerender. This is used as a helper in special cases 18611 // where we should count the work of multiple passes. 18612 var child = fiber.child; 18613 18614 while (child) { 18615 fiber.actualDuration += child.actualDuration; 18616 child = child.sibling; 18617 } 18618 } 18619 18620 function createCapturedValueAtFiber(value, source) { 18621 // If the value is an error, call this function immediately after it is thrown 18622 // so the stack is accurate. 18623 return { 18624 value: value, 18625 source: source, 18626 stack: getStackByFiberInDevAndProd(source), 18627 digest: null 18628 }; 18629 } 18630 function createCapturedValue(value, digest, stack) { 18631 return { 18632 value: value, 18633 source: null, 18634 stack: stack != null ? stack : null, 18635 digest: digest != null ? digest : null 18636 }; 18637 } 18638 18639 // This module is forked in different environments. 18640 // By default, return `true` to log errors to the console. 18641 // Forks can return `false` if this isn't desirable. 18642 function showErrorDialog(boundary, errorInfo) { 18643 return true; 18644 } 18645 18646 function logCapturedError(boundary, errorInfo) { 18647 try { 18648 var logError = showErrorDialog(boundary, errorInfo); // Allow injected showErrorDialog() to prevent default console.error logging. 18649 // This enables renderers like ReactNative to better manage redbox behavior. 18650 18651 if (logError === false) { 18652 return; 18653 } 18654 18655 var error = errorInfo.value; 18656 18657 if (true) { 18658 var source = errorInfo.source; 18659 var stack = errorInfo.stack; 18660 var componentStack = stack !== null ? stack : ''; // Browsers support silencing uncaught errors by calling 18661 // `preventDefault()` in window `error` handler. 18662 // We record this information as an expando on the error. 18663 18664 if (error != null && error._suppressLogging) { 18665 if (boundary.tag === ClassComponent) { 18666 // The error is recoverable and was silenced. 18667 // Ignore it and don't print the stack addendum. 18668 // This is handy for testing error boundaries without noise. 18669 return; 18670 } // The error is fatal. Since the silencing might have 18671 // been accidental, we'll surface it anyway. 18672 // However, the browser would have silenced the original error 18673 // so we'll print it first, and then print the stack addendum. 18674 18675 18676 console['error'](error); // Don't transform to our wrapper 18677 // For a more detailed description of this block, see: 18678 // https://github.com/facebook/react/pull/13384 18679 } 18680 18681 var componentName = source ? getComponentNameFromFiber(source) : null; 18682 var componentNameMessage = componentName ? "The above error occurred in the <" + componentName + "> component:" : 'The above error occurred in one of your React components:'; 18683 var errorBoundaryMessage; 18684 18685 if (boundary.tag === HostRoot) { 18686 errorBoundaryMessage = 'Consider adding an error boundary to your tree to customize error handling behavior.\n' + 'Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.'; 18687 } else { 18688 var errorBoundaryName = getComponentNameFromFiber(boundary) || 'Anonymous'; 18689 errorBoundaryMessage = "React will try to recreate this component tree from scratch " + ("using the error boundary you provided, " + errorBoundaryName + "."); 18690 } 18691 18692 var combinedMessage = componentNameMessage + "\n" + componentStack + "\n\n" + ("" + errorBoundaryMessage); // In development, we provide our own message with just the component stack. 18693 // We don't include the original error message and JS stack because the browser 18694 // has already printed it. Even if the application swallows the error, it is still 18695 // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. 18696 18697 console['error'](combinedMessage); // Don't transform to our wrapper 18698 } else { 18699 // In production, we print the error directly. 18700 // This will include the message, the JS stack, and anything the browser wants to show. 18701 // We pass the error object instead of custom message so that the browser displays the error natively. 18702 console['error'](error); // Don't transform to our wrapper 18703 } 18704 } catch (e) { 18705 // This method must not throw, or React internal state will get messed up. 18706 // If console.error is overridden, or logCapturedError() shows a dialog that throws, 18707 // we want to report this error outside of the normal stack as a last resort. 18708 // https://github.com/facebook/react/issues/13188 18709 setTimeout(function () { 18710 throw e; 18711 }); 18712 } 18713 } 18714 18715 var PossiblyWeakMap$1 = typeof WeakMap === 'function' ? WeakMap : Map; 18716 18717 function createRootErrorUpdate(fiber, errorInfo, lane) { 18718 var update = createUpdate(NoTimestamp, lane); // Unmount the root by rendering null. 18719 18720 update.tag = CaptureUpdate; // Caution: React DevTools currently depends on this property 18721 // being called "element". 18722 18723 update.payload = { 18724 element: null 18725 }; 18726 var error = errorInfo.value; 18727 18728 update.callback = function () { 18729 onUncaughtError(error); 18730 logCapturedError(fiber, errorInfo); 18731 }; 18732 18733 return update; 18734 } 18735 18736 function createClassErrorUpdate(fiber, errorInfo, lane) { 18737 var update = createUpdate(NoTimestamp, lane); 18738 update.tag = CaptureUpdate; 18739 var getDerivedStateFromError = fiber.type.getDerivedStateFromError; 18740 18741 if (typeof getDerivedStateFromError === 'function') { 18742 var error$1 = errorInfo.value; 18743 18744 update.payload = function () { 18745 return getDerivedStateFromError(error$1); 18746 }; 18747 18748 update.callback = function () { 18749 { 18750 markFailedErrorBoundaryForHotReloading(fiber); 18751 } 18752 18753 logCapturedError(fiber, errorInfo); 18754 }; 18755 } 18756 18757 var inst = fiber.stateNode; 18758 18759 if (inst !== null && typeof inst.componentDidCatch === 'function') { 18760 update.callback = function callback() { 18761 { 18762 markFailedErrorBoundaryForHotReloading(fiber); 18763 } 18764 18765 logCapturedError(fiber, errorInfo); 18766 18767 if (typeof getDerivedStateFromError !== 'function') { 18768 // To preserve the preexisting retry behavior of error boundaries, 18769 // we keep track of which ones already failed during this batch. 18770 // This gets reset before we yield back to the browser. 18771 // TODO: Warn in strict mode if getDerivedStateFromError is 18772 // not defined. 18773 markLegacyErrorBoundaryAsFailed(this); 18774 } 18775 18776 var error$1 = errorInfo.value; 18777 var stack = errorInfo.stack; 18778 this.componentDidCatch(error$1, { 18779 componentStack: stack !== null ? stack : '' 18780 }); 18781 18782 { 18783 if (typeof getDerivedStateFromError !== 'function') { 18784 // If componentDidCatch is the only error boundary method defined, 18785 // then it needs to call setState to recover from errors. 18786 // If no state update is scheduled then the boundary will swallow the error. 18787 if (!includesSomeLane(fiber.lanes, SyncLane)) { 18788 error('%s: Error boundaries should implement getDerivedStateFromError(). ' + 'In that method, return a state update to display an error message or fallback UI.', getComponentNameFromFiber(fiber) || 'Unknown'); 18789 } 18790 } 18791 } 18792 }; 18793 } 18794 18795 return update; 18796 } 18797 18798 function attachPingListener(root, wakeable, lanes) { 18799 // Attach a ping listener 18800 // 18801 // The data might resolve before we have a chance to commit the fallback. Or, 18802 // in the case of a refresh, we'll never commit a fallback. So we need to 18803 // attach a listener now. When it resolves ("pings"), we can decide whether to 18804 // try rendering the tree again. 18805 // 18806 // Only attach a listener if one does not already exist for the lanes 18807 // we're currently rendering (which acts like a "thread ID" here). 18808 // 18809 // We only need to do this in concurrent mode. Legacy Suspense always 18810 // commits fallbacks synchronously, so there are no pings. 18811 var pingCache = root.pingCache; 18812 var threadIDs; 18813 18814 if (pingCache === null) { 18815 pingCache = root.pingCache = new PossiblyWeakMap$1(); 18816 threadIDs = new Set(); 18817 pingCache.set(wakeable, threadIDs); 18818 } else { 18819 threadIDs = pingCache.get(wakeable); 18820 18821 if (threadIDs === undefined) { 18822 threadIDs = new Set(); 18823 pingCache.set(wakeable, threadIDs); 18824 } 18825 } 18826 18827 if (!threadIDs.has(lanes)) { 18828 // Memoize using the thread ID to prevent redundant listeners. 18829 threadIDs.add(lanes); 18830 var ping = pingSuspendedRoot.bind(null, root, wakeable, lanes); 18831 18832 { 18833 if (isDevToolsPresent) { 18834 // If we have pending work still, restore the original updaters 18835 restorePendingUpdaters(root, lanes); 18836 } 18837 } 18838 18839 wakeable.then(ping, ping); 18840 } 18841 } 18842 18843 function attachRetryListener(suspenseBoundary, root, wakeable, lanes) { 18844 // Retry listener 18845 // 18846 // If the fallback does commit, we need to attach a different type of 18847 // listener. This one schedules an update on the Suspense boundary to turn 18848 // the fallback state off. 18849 // 18850 // Stash the wakeable on the boundary fiber so we can access it in the 18851 // commit phase. 18852 // 18853 // When the wakeable resolves, we'll attempt to render the boundary 18854 // again ("retry"). 18855 var wakeables = suspenseBoundary.updateQueue; 18856 18857 if (wakeables === null) { 18858 var updateQueue = new Set(); 18859 updateQueue.add(wakeable); 18860 suspenseBoundary.updateQueue = updateQueue; 18861 } else { 18862 wakeables.add(wakeable); 18863 } 18864 } 18865 18866 function resetSuspendedComponent(sourceFiber, rootRenderLanes) { 18867 // A legacy mode Suspense quirk, only relevant to hook components. 18868 18869 18870 var tag = sourceFiber.tag; 18871 18872 if ((sourceFiber.mode & ConcurrentMode) === NoMode && (tag === FunctionComponent || tag === ForwardRef || tag === SimpleMemoComponent)) { 18873 var currentSource = sourceFiber.alternate; 18874 18875 if (currentSource) { 18876 sourceFiber.updateQueue = currentSource.updateQueue; 18877 sourceFiber.memoizedState = currentSource.memoizedState; 18878 sourceFiber.lanes = currentSource.lanes; 18879 } else { 18880 sourceFiber.updateQueue = null; 18881 sourceFiber.memoizedState = null; 18882 } 18883 } 18884 } 18885 18886 function getNearestSuspenseBoundaryToCapture(returnFiber) { 18887 var node = returnFiber; 18888 18889 do { 18890 if (node.tag === SuspenseComponent && shouldCaptureSuspense(node)) { 18891 return node; 18892 } // This boundary already captured during this render. Continue to the next 18893 // boundary. 18894 18895 18896 node = node.return; 18897 } while (node !== null); 18898 18899 return null; 18900 } 18901 18902 function markSuspenseBoundaryShouldCapture(suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes) { 18903 // This marks a Suspense boundary so that when we're unwinding the stack, 18904 // it captures the suspended "exception" and does a second (fallback) pass. 18905 if ((suspenseBoundary.mode & ConcurrentMode) === NoMode) { 18906 // Legacy Mode Suspense 18907 // 18908 // If the boundary is in legacy mode, we should *not* 18909 // suspend the commit. Pretend as if the suspended component rendered 18910 // null and keep rendering. When the Suspense boundary completes, 18911 // we'll do a second pass to render the fallback. 18912 if (suspenseBoundary === returnFiber) { 18913 // Special case where we suspended while reconciling the children of 18914 // a Suspense boundary's inner Offscreen wrapper fiber. This happens 18915 // when a React.lazy component is a direct child of a 18916 // Suspense boundary. 18917 // 18918 // Suspense boundaries are implemented as multiple fibers, but they 18919 // are a single conceptual unit. The legacy mode behavior where we 18920 // pretend the suspended fiber committed as `null` won't work, 18921 // because in this case the "suspended" fiber is the inner 18922 // Offscreen wrapper. 18923 // 18924 // Because the contents of the boundary haven't started rendering 18925 // yet (i.e. nothing in the tree has partially rendered) we can 18926 // switch to the regular, concurrent mode behavior: mark the 18927 // boundary with ShouldCapture and enter the unwind phase. 18928 suspenseBoundary.flags |= ShouldCapture; 18929 } else { 18930 suspenseBoundary.flags |= DidCapture; 18931 sourceFiber.flags |= ForceUpdateForLegacySuspense; // We're going to commit this fiber even though it didn't complete. 18932 // But we shouldn't call any lifecycle methods or callbacks. Remove 18933 // all lifecycle effect tags. 18934 18935 sourceFiber.flags &= ~(LifecycleEffectMask | Incomplete); 18936 18937 if (sourceFiber.tag === ClassComponent) { 18938 var currentSourceFiber = sourceFiber.alternate; 18939 18940 if (currentSourceFiber === null) { 18941 // This is a new mount. Change the tag so it's not mistaken for a 18942 // completed class component. For example, we should not call 18943 // componentWillUnmount if it is deleted. 18944 sourceFiber.tag = IncompleteClassComponent; 18945 } else { 18946 // When we try rendering again, we should not reuse the current fiber, 18947 // since it's known to be in an inconsistent state. Use a force update to 18948 // prevent a bail out. 18949 var update = createUpdate(NoTimestamp, SyncLane); 18950 update.tag = ForceUpdate; 18951 enqueueUpdate(sourceFiber, update, SyncLane); 18952 } 18953 } // The source fiber did not complete. Mark it with Sync priority to 18954 // indicate that it still has pending work. 18955 18956 18957 sourceFiber.lanes = mergeLanes(sourceFiber.lanes, SyncLane); 18958 } 18959 18960 return suspenseBoundary; 18961 } // Confirmed that the boundary is in a concurrent mode tree. Continue 18962 // with the normal suspend path. 18963 // 18964 // After this we'll use a set of heuristics to determine whether this 18965 // render pass will run to completion or restart or "suspend" the commit. 18966 // The actual logic for this is spread out in different places. 18967 // 18968 // This first principle is that if we're going to suspend when we complete 18969 // a root, then we should also restart if we get an update or ping that 18970 // might unsuspend it, and vice versa. The only reason to suspend is 18971 // because you think you might want to restart before committing. However, 18972 // it doesn't make sense to restart only while in the period we're suspended. 18973 // 18974 // Restarting too aggressively is also not good because it starves out any 18975 // intermediate loading state. So we use heuristics to determine when. 18976 // Suspense Heuristics 18977 // 18978 // If nothing threw a Promise or all the same fallbacks are already showing, 18979 // then don't suspend/restart. 18980 // 18981 // If this is an initial render of a new tree of Suspense boundaries and 18982 // those trigger a fallback, then don't suspend/restart. We want to ensure 18983 // that we can show the initial loading state as quickly as possible. 18984 // 18985 // If we hit a "Delayed" case, such as when we'd switch from content back into 18986 // a fallback, then we should always suspend/restart. Transitions apply 18987 // to this case. If none is defined, JND is used instead. 18988 // 18989 // If we're already showing a fallback and it gets "retried", allowing us to show 18990 // another level, but there's still an inner boundary that would show a fallback, 18991 // then we suspend/restart for 500ms since the last time we showed a fallback 18992 // anywhere in the tree. This effectively throttles progressive loading into a 18993 // consistent train of commits. This also gives us an opportunity to restart to 18994 // get to the completed state slightly earlier. 18995 // 18996 // If there's ambiguity due to batching it's resolved in preference of: 18997 // 1) "delayed", 2) "initial render", 3) "retry". 18998 // 18999 // We want to ensure that a "busy" state doesn't get force committed. We want to 19000 // ensure that new initial loading states can commit as soon as possible. 19001 19002 19003 suspenseBoundary.flags |= ShouldCapture; // TODO: I think we can remove this, since we now use `DidCapture` in 19004 // the begin phase to prevent an early bailout. 19005 19006 suspenseBoundary.lanes = rootRenderLanes; 19007 return suspenseBoundary; 19008 } 19009 19010 function throwException(root, returnFiber, sourceFiber, value, rootRenderLanes) { 19011 // The source fiber did not complete. 19012 sourceFiber.flags |= Incomplete; 19013 19014 { 19015 if (isDevToolsPresent) { 19016 // If we have pending work still, restore the original updaters 19017 restorePendingUpdaters(root, rootRenderLanes); 19018 } 19019 } 19020 19021 if (value !== null && typeof value === 'object' && typeof value.then === 'function') { 19022 // This is a wakeable. The component suspended. 19023 var wakeable = value; 19024 resetSuspendedComponent(sourceFiber); 19025 19026 { 19027 if (getIsHydrating() && sourceFiber.mode & ConcurrentMode) { 19028 markDidThrowWhileHydratingDEV(); 19029 } 19030 } 19031 19032 19033 var suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); 19034 19035 if (suspenseBoundary !== null) { 19036 suspenseBoundary.flags &= ~ForceClientRender; 19037 markSuspenseBoundaryShouldCapture(suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes); // We only attach ping listeners in concurrent mode. Legacy Suspense always 19038 // commits fallbacks synchronously, so there are no pings. 19039 19040 if (suspenseBoundary.mode & ConcurrentMode) { 19041 attachPingListener(root, wakeable, rootRenderLanes); 19042 } 19043 19044 attachRetryListener(suspenseBoundary, root, wakeable); 19045 return; 19046 } else { 19047 // No boundary was found. Unless this is a sync update, this is OK. 19048 // We can suspend and wait for more data to arrive. 19049 if (!includesSyncLane(rootRenderLanes)) { 19050 // This is not a sync update. Suspend. Since we're not activating a 19051 // Suspense boundary, this will unwind all the way to the root without 19052 // performing a second pass to render a fallback. (This is arguably how 19053 // refresh transitions should work, too, since we're not going to commit 19054 // the fallbacks anyway.) 19055 // 19056 // This case also applies to initial hydration. 19057 attachPingListener(root, wakeable, rootRenderLanes); 19058 renderDidSuspendDelayIfPossible(); 19059 return; 19060 } // This is a sync/discrete update. We treat this case like an error 19061 // because discrete renders are expected to produce a complete tree 19062 // synchronously to maintain consistency with external state. 19063 19064 19065 var uncaughtSuspenseError = new Error('A component suspended while responding to synchronous input. This ' + 'will cause the UI to be replaced with a loading indicator. To ' + 'fix, updates that suspend should be wrapped ' + 'with startTransition.'); // If we're outside a transition, fall through to the regular error path. 19066 // The error will be caught by the nearest suspense boundary. 19067 19068 value = uncaughtSuspenseError; 19069 } 19070 } else { 19071 // This is a regular error, not a Suspense wakeable. 19072 if (getIsHydrating() && sourceFiber.mode & ConcurrentMode) { 19073 markDidThrowWhileHydratingDEV(); 19074 19075 var _suspenseBoundary = getNearestSuspenseBoundaryToCapture(returnFiber); // If the error was thrown during hydration, we may be able to recover by 19076 // discarding the dehydrated content and switching to a client render. 19077 // Instead of surfacing the error, find the nearest Suspense boundary 19078 // and render it again without hydration. 19079 19080 19081 if (_suspenseBoundary !== null) { 19082 if ((_suspenseBoundary.flags & ShouldCapture) === NoFlags) { 19083 // Set a flag to indicate that we should try rendering the normal 19084 // children again, not the fallback. 19085 _suspenseBoundary.flags |= ForceClientRender; 19086 } 19087 19088 markSuspenseBoundaryShouldCapture(_suspenseBoundary, returnFiber, sourceFiber, root, rootRenderLanes); // Even though the user may not be affected by this error, we should 19089 // still log it so it can be fixed. 19090 19091 queueHydrationError(createCapturedValueAtFiber(value, sourceFiber)); 19092 return; 19093 } 19094 } 19095 } 19096 19097 value = createCapturedValueAtFiber(value, sourceFiber); 19098 renderDidError(value); // We didn't find a boundary that could handle this type of exception. Start 19099 // over and traverse parent path again, this time treating the exception 19100 // as an error. 19101 19102 var workInProgress = returnFiber; 19103 19104 do { 19105 switch (workInProgress.tag) { 19106 case HostRoot: 19107 { 19108 var _errorInfo = value; 19109 workInProgress.flags |= ShouldCapture; 19110 var lane = pickArbitraryLane(rootRenderLanes); 19111 workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); 19112 var update = createRootErrorUpdate(workInProgress, _errorInfo, lane); 19113 enqueueCapturedUpdate(workInProgress, update); 19114 return; 19115 } 19116 19117 case ClassComponent: 19118 // Capture and retry 19119 var errorInfo = value; 19120 var ctor = workInProgress.type; 19121 var instance = workInProgress.stateNode; 19122 19123 if ((workInProgress.flags & DidCapture) === NoFlags && (typeof ctor.getDerivedStateFromError === 'function' || instance !== null && typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance))) { 19124 workInProgress.flags |= ShouldCapture; 19125 19126 var _lane = pickArbitraryLane(rootRenderLanes); 19127 19128 workInProgress.lanes = mergeLanes(workInProgress.lanes, _lane); // Schedule the error boundary to re-render using updated state 19129 19130 var _update = createClassErrorUpdate(workInProgress, errorInfo, _lane); 19131 19132 enqueueCapturedUpdate(workInProgress, _update); 19133 return; 19134 } 19135 19136 break; 19137 } 19138 19139 workInProgress = workInProgress.return; 19140 } while (workInProgress !== null); 19141 } 19142 19143 function getSuspendedCache() { 19144 { 19145 return null; 19146 } // This function is called when a Suspense boundary suspends. It returns the 19147 } 19148 19149 var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; 19150 var didReceiveUpdate = false; 19151 var didWarnAboutBadClass; 19152 var didWarnAboutModulePatternComponent; 19153 var didWarnAboutContextTypeOnFunctionComponent; 19154 var didWarnAboutGetDerivedStateOnFunctionComponent; 19155 var didWarnAboutFunctionRefs; 19156 var didWarnAboutReassigningProps; 19157 var didWarnAboutRevealOrder; 19158 var didWarnAboutTailOptions; 19159 19160 { 19161 didWarnAboutBadClass = {}; 19162 didWarnAboutModulePatternComponent = {}; 19163 didWarnAboutContextTypeOnFunctionComponent = {}; 19164 didWarnAboutGetDerivedStateOnFunctionComponent = {}; 19165 didWarnAboutFunctionRefs = {}; 19166 didWarnAboutReassigningProps = false; 19167 didWarnAboutRevealOrder = {}; 19168 didWarnAboutTailOptions = {}; 19169 } 19170 19171 function reconcileChildren(current, workInProgress, nextChildren, renderLanes) { 19172 if (current === null) { 19173 // If this is a fresh new component that hasn't been rendered yet, we 19174 // won't update its child set by applying minimal side-effects. Instead, 19175 // we will add them all to the child before it gets rendered. That means 19176 // we can optimize this reconciliation pass by not tracking side-effects. 19177 workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderLanes); 19178 } else { 19179 // If the current child is the same as the work in progress, it means that 19180 // we haven't yet started any work on these children. Therefore, we use 19181 // the clone algorithm to create a copy of all the current children. 19182 // If we had any progressed work already, that is invalid at this point so 19183 // let's throw it out. 19184 workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderLanes); 19185 } 19186 } 19187 19188 function forceUnmountCurrentAndReconcile(current, workInProgress, nextChildren, renderLanes) { 19189 // This function is fork of reconcileChildren. It's used in cases where we 19190 // want to reconcile without matching against the existing set. This has the 19191 // effect of all current children being unmounted; even if the type and key 19192 // are the same, the old child is unmounted and a new child is created. 19193 // 19194 // To do this, we're going to go through the reconcile algorithm twice. In 19195 // the first pass, we schedule a deletion for all the current children by 19196 // passing null. 19197 workInProgress.child = reconcileChildFibers(workInProgress, current.child, null, renderLanes); // In the second pass, we mount the new children. The trick here is that we 19198 // pass null in place of where we usually pass the current child set. This has 19199 // the effect of remounting all children regardless of whether their 19200 // identities match. 19201 19202 workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderLanes); 19203 } 19204 19205 function updateForwardRef(current, workInProgress, Component, nextProps, renderLanes) { 19206 // TODO: current can be non-null here even if the component 19207 // hasn't yet mounted. This happens after the first render suspends. 19208 // We'll need to figure out if this is fine or can cause issues. 19209 { 19210 if (workInProgress.type !== workInProgress.elementType) { 19211 // Lazy component props can't be validated in createElement 19212 // because they're only guaranteed to be resolved here. 19213 var innerPropTypes = Component.propTypes; 19214 19215 if (innerPropTypes) { 19216 checkPropTypes(innerPropTypes, nextProps, // Resolved props 19217 'prop', getComponentNameFromType(Component)); 19218 } 19219 } 19220 } 19221 19222 var render = Component.render; 19223 var ref = workInProgress.ref; // The rest is a fork of updateFunctionComponent 19224 19225 var nextChildren; 19226 var hasId; 19227 prepareToReadContext(workInProgress, renderLanes); 19228 19229 { 19230 markComponentRenderStarted(workInProgress); 19231 } 19232 19233 { 19234 ReactCurrentOwner$1.current = workInProgress; 19235 setIsRendering(true); 19236 nextChildren = renderWithHooks(current, workInProgress, render, nextProps, ref, renderLanes); 19237 hasId = checkDidRenderIdHook(); 19238 19239 if ( workInProgress.mode & StrictLegacyMode) { 19240 setIsStrictModeForDevtools(true); 19241 19242 try { 19243 nextChildren = renderWithHooks(current, workInProgress, render, nextProps, ref, renderLanes); 19244 hasId = checkDidRenderIdHook(); 19245 } finally { 19246 setIsStrictModeForDevtools(false); 19247 } 19248 } 19249 19250 setIsRendering(false); 19251 } 19252 19253 { 19254 markComponentRenderStopped(); 19255 } 19256 19257 if (current !== null && !didReceiveUpdate) { 19258 bailoutHooks(current, workInProgress, renderLanes); 19259 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19260 } 19261 19262 if (getIsHydrating() && hasId) { 19263 pushMaterializedTreeId(workInProgress); 19264 } // React DevTools reads this flag. 19265 19266 19267 workInProgress.flags |= PerformedWork; 19268 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19269 return workInProgress.child; 19270 } 19271 19272 function updateMemoComponent(current, workInProgress, Component, nextProps, renderLanes) { 19273 if (current === null) { 19274 var type = Component.type; 19275 19276 if (isSimpleFunctionComponent(type) && Component.compare === null && // SimpleMemoComponent codepath doesn't resolve outer props either. 19277 Component.defaultProps === undefined) { 19278 var resolvedType = type; 19279 19280 { 19281 resolvedType = resolveFunctionForHotReloading(type); 19282 } // If this is a plain function component without default props, 19283 // and with only the default shallow comparison, we upgrade it 19284 // to a SimpleMemoComponent to allow fast path updates. 19285 19286 19287 workInProgress.tag = SimpleMemoComponent; 19288 workInProgress.type = resolvedType; 19289 19290 { 19291 validateFunctionComponentInDev(workInProgress, type); 19292 } 19293 19294 return updateSimpleMemoComponent(current, workInProgress, resolvedType, nextProps, renderLanes); 19295 } 19296 19297 { 19298 var innerPropTypes = type.propTypes; 19299 19300 if (innerPropTypes) { 19301 // Inner memo component props aren't currently validated in createElement. 19302 // We could move it there, but we'd still need this for lazy code path. 19303 checkPropTypes(innerPropTypes, nextProps, // Resolved props 19304 'prop', getComponentNameFromType(type)); 19305 } 19306 } 19307 19308 var child = createFiberFromTypeAndProps(Component.type, null, nextProps, workInProgress, workInProgress.mode, renderLanes); 19309 child.ref = workInProgress.ref; 19310 child.return = workInProgress; 19311 workInProgress.child = child; 19312 return child; 19313 } 19314 19315 { 19316 var _type = Component.type; 19317 var _innerPropTypes = _type.propTypes; 19318 19319 if (_innerPropTypes) { 19320 // Inner memo component props aren't currently validated in createElement. 19321 // We could move it there, but we'd still need this for lazy code path. 19322 checkPropTypes(_innerPropTypes, nextProps, // Resolved props 19323 'prop', getComponentNameFromType(_type)); 19324 } 19325 } 19326 19327 var currentChild = current.child; // This is always exactly one child 19328 19329 var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(current, renderLanes); 19330 19331 if (!hasScheduledUpdateOrContext) { 19332 // This will be the props with resolved defaultProps, 19333 // unlike current.memoizedProps which will be the unresolved ones. 19334 var prevProps = currentChild.memoizedProps; // Default to shallow comparison 19335 19336 var compare = Component.compare; 19337 compare = compare !== null ? compare : shallowEqual; 19338 19339 if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) { 19340 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19341 } 19342 } // React DevTools reads this flag. 19343 19344 19345 workInProgress.flags |= PerformedWork; 19346 var newChild = createWorkInProgress(currentChild, nextProps); 19347 newChild.ref = workInProgress.ref; 19348 newChild.return = workInProgress; 19349 workInProgress.child = newChild; 19350 return newChild; 19351 } 19352 19353 function updateSimpleMemoComponent(current, workInProgress, Component, nextProps, renderLanes) { 19354 // TODO: current can be non-null here even if the component 19355 // hasn't yet mounted. This happens when the inner render suspends. 19356 // We'll need to figure out if this is fine or can cause issues. 19357 { 19358 if (workInProgress.type !== workInProgress.elementType) { 19359 // Lazy component props can't be validated in createElement 19360 // because they're only guaranteed to be resolved here. 19361 var outerMemoType = workInProgress.elementType; 19362 19363 if (outerMemoType.$$typeof === REACT_LAZY_TYPE) { 19364 // We warn when you define propTypes on lazy() 19365 // so let's just skip over it to find memo() outer wrapper. 19366 // Inner props for memo are validated later. 19367 var lazyComponent = outerMemoType; 19368 var payload = lazyComponent._payload; 19369 var init = lazyComponent._init; 19370 19371 try { 19372 outerMemoType = init(payload); 19373 } catch (x) { 19374 outerMemoType = null; 19375 } // Inner propTypes will be validated in the function component path. 19376 19377 19378 var outerPropTypes = outerMemoType && outerMemoType.propTypes; 19379 19380 if (outerPropTypes) { 19381 checkPropTypes(outerPropTypes, nextProps, // Resolved (SimpleMemoComponent has no defaultProps) 19382 'prop', getComponentNameFromType(outerMemoType)); 19383 } 19384 } 19385 } 19386 } 19387 19388 if (current !== null) { 19389 var prevProps = current.memoizedProps; 19390 19391 if (shallowEqual(prevProps, nextProps) && current.ref === workInProgress.ref && ( // Prevent bailout if the implementation changed due to hot reload. 19392 workInProgress.type === current.type )) { 19393 didReceiveUpdate = false; // The props are shallowly equal. Reuse the previous props object, like we 19394 // would during a normal fiber bailout. 19395 // 19396 // We don't have strong guarantees that the props object is referentially 19397 // equal during updates where we can't bail out anyway — like if the props 19398 // are shallowly equal, but there's a local state or context update in the 19399 // same batch. 19400 // 19401 // However, as a principle, we should aim to make the behavior consistent 19402 // across different ways of memoizing a component. For example, React.memo 19403 // has a different internal Fiber layout if you pass a normal function 19404 // component (SimpleMemoComponent) versus if you pass a different type 19405 // like forwardRef (MemoComponent). But this is an implementation detail. 19406 // Wrapping a component in forwardRef (or React.lazy, etc) shouldn't 19407 // affect whether the props object is reused during a bailout. 19408 19409 workInProgress.pendingProps = nextProps = prevProps; 19410 19411 if (!checkScheduledUpdateOrContext(current, renderLanes)) { 19412 // The pending lanes were cleared at the beginning of beginWork. We're 19413 // about to bail out, but there might be other lanes that weren't 19414 // included in the current render. Usually, the priority level of the 19415 // remaining updates is accumulated during the evaluation of the 19416 // component (i.e. when processing the update queue). But since since 19417 // we're bailing out early *without* evaluating the component, we need 19418 // to account for it here, too. Reset to the value of the current fiber. 19419 // NOTE: This only applies to SimpleMemoComponent, not MemoComponent, 19420 // because a MemoComponent fiber does not have hooks or an update queue; 19421 // rather, it wraps around an inner component, which may or may not 19422 // contains hooks. 19423 // TODO: Move the reset at in beginWork out of the common path so that 19424 // this is no longer necessary. 19425 workInProgress.lanes = current.lanes; 19426 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19427 } else if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { 19428 // This is a special case that only exists for legacy mode. 19429 // See https://github.com/facebook/react/pull/19216. 19430 didReceiveUpdate = true; 19431 } 19432 } 19433 } 19434 19435 return updateFunctionComponent(current, workInProgress, Component, nextProps, renderLanes); 19436 } 19437 19438 function updateOffscreenComponent(current, workInProgress, renderLanes) { 19439 var nextProps = workInProgress.pendingProps; 19440 var nextChildren = nextProps.children; 19441 var prevState = current !== null ? current.memoizedState : null; 19442 19443 if (nextProps.mode === 'hidden' || enableLegacyHidden ) { 19444 // Rendering a hidden tree. 19445 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 19446 // In legacy sync mode, don't defer the subtree. Render it now. 19447 // TODO: Consider how Offscreen should work with transitions in the future 19448 var nextState = { 19449 baseLanes: NoLanes, 19450 cachePool: null, 19451 transitions: null 19452 }; 19453 workInProgress.memoizedState = nextState; 19454 19455 pushRenderLanes(workInProgress, renderLanes); 19456 } else if (!includesSomeLane(renderLanes, OffscreenLane)) { 19457 var spawnedCachePool = null; // We're hidden, and we're not rendering at Offscreen. We will bail out 19458 // and resume this tree later. 19459 19460 var nextBaseLanes; 19461 19462 if (prevState !== null) { 19463 var prevBaseLanes = prevState.baseLanes; 19464 nextBaseLanes = mergeLanes(prevBaseLanes, renderLanes); 19465 } else { 19466 nextBaseLanes = renderLanes; 19467 } // Schedule this fiber to re-render at offscreen priority. Then bailout. 19468 19469 19470 workInProgress.lanes = workInProgress.childLanes = laneToLanes(OffscreenLane); 19471 var _nextState = { 19472 baseLanes: nextBaseLanes, 19473 cachePool: spawnedCachePool, 19474 transitions: null 19475 }; 19476 workInProgress.memoizedState = _nextState; 19477 workInProgress.updateQueue = null; 19478 // to avoid a push/pop misalignment. 19479 19480 19481 pushRenderLanes(workInProgress, nextBaseLanes); 19482 19483 return null; 19484 } else { 19485 // This is the second render. The surrounding visible content has already 19486 // committed. Now we resume rendering the hidden tree. 19487 // Rendering at offscreen, so we can clear the base lanes. 19488 var _nextState2 = { 19489 baseLanes: NoLanes, 19490 cachePool: null, 19491 transitions: null 19492 }; 19493 workInProgress.memoizedState = _nextState2; // Push the lanes that were skipped when we bailed out. 19494 19495 var subtreeRenderLanes = prevState !== null ? prevState.baseLanes : renderLanes; 19496 19497 pushRenderLanes(workInProgress, subtreeRenderLanes); 19498 } 19499 } else { 19500 // Rendering a visible tree. 19501 var _subtreeRenderLanes; 19502 19503 if (prevState !== null) { 19504 // We're going from hidden -> visible. 19505 _subtreeRenderLanes = mergeLanes(prevState.baseLanes, renderLanes); 19506 19507 workInProgress.memoizedState = null; 19508 } else { 19509 // We weren't previously hidden, and we still aren't, so there's nothing 19510 // special to do. Need to push to the stack regardless, though, to avoid 19511 // a push/pop misalignment. 19512 _subtreeRenderLanes = renderLanes; 19513 } 19514 19515 pushRenderLanes(workInProgress, _subtreeRenderLanes); 19516 } 19517 19518 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19519 return workInProgress.child; 19520 } // Note: These happen to have identical begin phases, for now. We shouldn't hold 19521 19522 function updateFragment(current, workInProgress, renderLanes) { 19523 var nextChildren = workInProgress.pendingProps; 19524 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19525 return workInProgress.child; 19526 } 19527 19528 function updateMode(current, workInProgress, renderLanes) { 19529 var nextChildren = workInProgress.pendingProps.children; 19530 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19531 return workInProgress.child; 19532 } 19533 19534 function updateProfiler(current, workInProgress, renderLanes) { 19535 { 19536 workInProgress.flags |= Update; 19537 19538 { 19539 // Reset effect durations for the next eventual effect phase. 19540 // These are reset during render to allow the DevTools commit hook a chance to read them, 19541 var stateNode = workInProgress.stateNode; 19542 stateNode.effectDuration = 0; 19543 stateNode.passiveEffectDuration = 0; 19544 } 19545 } 19546 19547 var nextProps = workInProgress.pendingProps; 19548 var nextChildren = nextProps.children; 19549 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19550 return workInProgress.child; 19551 } 19552 19553 function markRef(current, workInProgress) { 19554 var ref = workInProgress.ref; 19555 19556 if (current === null && ref !== null || current !== null && current.ref !== ref) { 19557 // Schedule a Ref effect 19558 workInProgress.flags |= Ref; 19559 19560 { 19561 workInProgress.flags |= RefStatic; 19562 } 19563 } 19564 } 19565 19566 function updateFunctionComponent(current, workInProgress, Component, nextProps, renderLanes) { 19567 { 19568 if (workInProgress.type !== workInProgress.elementType) { 19569 // Lazy component props can't be validated in createElement 19570 // because they're only guaranteed to be resolved here. 19571 var innerPropTypes = Component.propTypes; 19572 19573 if (innerPropTypes) { 19574 checkPropTypes(innerPropTypes, nextProps, // Resolved props 19575 'prop', getComponentNameFromType(Component)); 19576 } 19577 } 19578 } 19579 19580 var context; 19581 19582 { 19583 var unmaskedContext = getUnmaskedContext(workInProgress, Component, true); 19584 context = getMaskedContext(workInProgress, unmaskedContext); 19585 } 19586 19587 var nextChildren; 19588 var hasId; 19589 prepareToReadContext(workInProgress, renderLanes); 19590 19591 { 19592 markComponentRenderStarted(workInProgress); 19593 } 19594 19595 { 19596 ReactCurrentOwner$1.current = workInProgress; 19597 setIsRendering(true); 19598 nextChildren = renderWithHooks(current, workInProgress, Component, nextProps, context, renderLanes); 19599 hasId = checkDidRenderIdHook(); 19600 19601 if ( workInProgress.mode & StrictLegacyMode) { 19602 setIsStrictModeForDevtools(true); 19603 19604 try { 19605 nextChildren = renderWithHooks(current, workInProgress, Component, nextProps, context, renderLanes); 19606 hasId = checkDidRenderIdHook(); 19607 } finally { 19608 setIsStrictModeForDevtools(false); 19609 } 19610 } 19611 19612 setIsRendering(false); 19613 } 19614 19615 { 19616 markComponentRenderStopped(); 19617 } 19618 19619 if (current !== null && !didReceiveUpdate) { 19620 bailoutHooks(current, workInProgress, renderLanes); 19621 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19622 } 19623 19624 if (getIsHydrating() && hasId) { 19625 pushMaterializedTreeId(workInProgress); 19626 } // React DevTools reads this flag. 19627 19628 19629 workInProgress.flags |= PerformedWork; 19630 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19631 return workInProgress.child; 19632 } 19633 19634 function updateClassComponent(current, workInProgress, Component, nextProps, renderLanes) { 19635 { 19636 // This is used by DevTools to force a boundary to error. 19637 switch (shouldError(workInProgress)) { 19638 case false: 19639 { 19640 var _instance = workInProgress.stateNode; 19641 var ctor = workInProgress.type; // TODO This way of resetting the error boundary state is a hack. 19642 // Is there a better way to do this? 19643 19644 var tempInstance = new ctor(workInProgress.memoizedProps, _instance.context); 19645 var state = tempInstance.state; 19646 19647 _instance.updater.enqueueSetState(_instance, state, null); 19648 19649 break; 19650 } 19651 19652 case true: 19653 { 19654 workInProgress.flags |= DidCapture; 19655 workInProgress.flags |= ShouldCapture; // eslint-disable-next-line react-internal/prod-error-codes 19656 19657 var error$1 = new Error('Simulated error coming from DevTools'); 19658 var lane = pickArbitraryLane(renderLanes); 19659 workInProgress.lanes = mergeLanes(workInProgress.lanes, lane); // Schedule the error boundary to re-render using updated state 19660 19661 var update = createClassErrorUpdate(workInProgress, createCapturedValueAtFiber(error$1, workInProgress), lane); 19662 enqueueCapturedUpdate(workInProgress, update); 19663 break; 19664 } 19665 } 19666 19667 if (workInProgress.type !== workInProgress.elementType) { 19668 // Lazy component props can't be validated in createElement 19669 // because they're only guaranteed to be resolved here. 19670 var innerPropTypes = Component.propTypes; 19671 19672 if (innerPropTypes) { 19673 checkPropTypes(innerPropTypes, nextProps, // Resolved props 19674 'prop', getComponentNameFromType(Component)); 19675 } 19676 } 19677 } // Push context providers early to prevent context stack mismatches. 19678 // During mounting we don't know the child context yet as the instance doesn't exist. 19679 // We will invalidate the child context in finishClassComponent() right after rendering. 19680 19681 19682 var hasContext; 19683 19684 if (isContextProvider(Component)) { 19685 hasContext = true; 19686 pushContextProvider(workInProgress); 19687 } else { 19688 hasContext = false; 19689 } 19690 19691 prepareToReadContext(workInProgress, renderLanes); 19692 var instance = workInProgress.stateNode; 19693 var shouldUpdate; 19694 19695 if (instance === null) { 19696 resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress); // In the initial pass we might need to construct the instance. 19697 19698 constructClassInstance(workInProgress, Component, nextProps); 19699 mountClassInstance(workInProgress, Component, nextProps, renderLanes); 19700 shouldUpdate = true; 19701 } else if (current === null) { 19702 // In a resume, we'll already have an instance we can reuse. 19703 shouldUpdate = resumeMountClassInstance(workInProgress, Component, nextProps, renderLanes); 19704 } else { 19705 shouldUpdate = updateClassInstance(current, workInProgress, Component, nextProps, renderLanes); 19706 } 19707 19708 var nextUnitOfWork = finishClassComponent(current, workInProgress, Component, shouldUpdate, hasContext, renderLanes); 19709 19710 { 19711 var inst = workInProgress.stateNode; 19712 19713 if (shouldUpdate && inst.props !== nextProps) { 19714 if (!didWarnAboutReassigningProps) { 19715 error('It looks like %s is reassigning its own `this.props` while rendering. ' + 'This is not supported and can lead to confusing bugs.', getComponentNameFromFiber(workInProgress) || 'a component'); 19716 } 19717 19718 didWarnAboutReassigningProps = true; 19719 } 19720 } 19721 19722 return nextUnitOfWork; 19723 } 19724 19725 function finishClassComponent(current, workInProgress, Component, shouldUpdate, hasContext, renderLanes) { 19726 // Refs should update even if shouldComponentUpdate returns false 19727 markRef(current, workInProgress); 19728 var didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags; 19729 19730 if (!shouldUpdate && !didCaptureError) { 19731 // Context providers should defer to sCU for rendering 19732 if (hasContext) { 19733 invalidateContextProvider(workInProgress, Component, false); 19734 } 19735 19736 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19737 } 19738 19739 var instance = workInProgress.stateNode; // Rerender 19740 19741 ReactCurrentOwner$1.current = workInProgress; 19742 var nextChildren; 19743 19744 if (didCaptureError && typeof Component.getDerivedStateFromError !== 'function') { 19745 // If we captured an error, but getDerivedStateFromError is not defined, 19746 // unmount all the children. componentDidCatch will schedule an update to 19747 // re-render a fallback. This is temporary until we migrate everyone to 19748 // the new API. 19749 // TODO: Warn in a future release. 19750 nextChildren = null; 19751 19752 { 19753 stopProfilerTimerIfRunning(); 19754 } 19755 } else { 19756 { 19757 markComponentRenderStarted(workInProgress); 19758 } 19759 19760 { 19761 setIsRendering(true); 19762 nextChildren = instance.render(); 19763 19764 if ( workInProgress.mode & StrictLegacyMode) { 19765 setIsStrictModeForDevtools(true); 19766 19767 try { 19768 instance.render(); 19769 } finally { 19770 setIsStrictModeForDevtools(false); 19771 } 19772 } 19773 19774 setIsRendering(false); 19775 } 19776 19777 { 19778 markComponentRenderStopped(); 19779 } 19780 } // React DevTools reads this flag. 19781 19782 19783 workInProgress.flags |= PerformedWork; 19784 19785 if (current !== null && didCaptureError) { 19786 // If we're recovering from an error, reconcile without reusing any of 19787 // the existing children. Conceptually, the normal children and the children 19788 // that are shown on error are two different sets, so we shouldn't reuse 19789 // normal children even if their identities match. 19790 forceUnmountCurrentAndReconcile(current, workInProgress, nextChildren, renderLanes); 19791 } else { 19792 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19793 } // Memoize state using the values we just used to render. 19794 // TODO: Restructure so we never read values from the instance. 19795 19796 19797 workInProgress.memoizedState = instance.state; // The context might have changed so we need to recalculate it. 19798 19799 if (hasContext) { 19800 invalidateContextProvider(workInProgress, Component, true); 19801 } 19802 19803 return workInProgress.child; 19804 } 19805 19806 function pushHostRootContext(workInProgress) { 19807 var root = workInProgress.stateNode; 19808 19809 if (root.pendingContext) { 19810 pushTopLevelContextObject(workInProgress, root.pendingContext, root.pendingContext !== root.context); 19811 } else if (root.context) { 19812 // Should always be set 19813 pushTopLevelContextObject(workInProgress, root.context, false); 19814 } 19815 19816 pushHostContainer(workInProgress, root.containerInfo); 19817 } 19818 19819 function updateHostRoot(current, workInProgress, renderLanes) { 19820 pushHostRootContext(workInProgress); 19821 19822 if (current === null) { 19823 throw new Error('Should have a current fiber. This is a bug in React.'); 19824 } 19825 19826 var nextProps = workInProgress.pendingProps; 19827 var prevState = workInProgress.memoizedState; 19828 var prevChildren = prevState.element; 19829 cloneUpdateQueue(current, workInProgress); 19830 processUpdateQueue(workInProgress, nextProps, null, renderLanes); 19831 var nextState = workInProgress.memoizedState; 19832 var root = workInProgress.stateNode; 19833 // being called "element". 19834 19835 19836 var nextChildren = nextState.element; 19837 19838 if ( prevState.isDehydrated) { 19839 // This is a hydration root whose shell has not yet hydrated. We should 19840 // attempt to hydrate. 19841 // Flip isDehydrated to false to indicate that when this render 19842 // finishes, the root will no longer be dehydrated. 19843 var overrideState = { 19844 element: nextChildren, 19845 isDehydrated: false, 19846 cache: nextState.cache, 19847 pendingSuspenseBoundaries: nextState.pendingSuspenseBoundaries, 19848 transitions: nextState.transitions 19849 }; 19850 var updateQueue = workInProgress.updateQueue; // `baseState` can always be the last state because the root doesn't 19851 // have reducer functions so it doesn't need rebasing. 19852 19853 updateQueue.baseState = overrideState; 19854 workInProgress.memoizedState = overrideState; 19855 19856 if (workInProgress.flags & ForceClientRender) { 19857 // Something errored during a previous attempt to hydrate the shell, so we 19858 // forced a client render. 19859 var recoverableError = createCapturedValueAtFiber(new Error('There was an error while hydrating. Because the error happened outside ' + 'of a Suspense boundary, the entire root will switch to ' + 'client rendering.'), workInProgress); 19860 return mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, recoverableError); 19861 } else if (nextChildren !== prevChildren) { 19862 var _recoverableError = createCapturedValueAtFiber(new Error('This root received an early update, before anything was able ' + 'hydrate. Switched the entire root to client rendering.'), workInProgress); 19863 19864 return mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, _recoverableError); 19865 } else { 19866 // The outermost shell has not hydrated yet. Start hydrating. 19867 enterHydrationState(workInProgress); 19868 19869 var child = mountChildFibers(workInProgress, null, nextChildren, renderLanes); 19870 workInProgress.child = child; 19871 var node = child; 19872 19873 while (node) { 19874 // Mark each child as hydrating. This is a fast path to know whether this 19875 // tree is part of a hydrating tree. This is used to determine if a child 19876 // node has fully mounted yet, and for scheduling event replaying. 19877 // Conceptually this is similar to Placement in that a new subtree is 19878 // inserted into the React tree here. It just happens to not need DOM 19879 // mutations because it already exists. 19880 node.flags = node.flags & ~Placement | Hydrating; 19881 node = node.sibling; 19882 } 19883 } 19884 } else { 19885 // Root is not dehydrated. Either this is a client-only root, or it 19886 // already hydrated. 19887 resetHydrationState(); 19888 19889 if (nextChildren === prevChildren) { 19890 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 19891 } 19892 19893 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19894 } 19895 19896 return workInProgress.child; 19897 } 19898 19899 function mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes, recoverableError) { 19900 // Revert to client rendering. 19901 resetHydrationState(); 19902 queueHydrationError(recoverableError); 19903 workInProgress.flags |= ForceClientRender; 19904 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19905 return workInProgress.child; 19906 } 19907 19908 function updateHostComponent(current, workInProgress, renderLanes) { 19909 pushHostContext(workInProgress); 19910 19911 if (current === null) { 19912 tryToClaimNextHydratableInstance(workInProgress); 19913 } 19914 19915 var type = workInProgress.type; 19916 var nextProps = workInProgress.pendingProps; 19917 var prevProps = current !== null ? current.memoizedProps : null; 19918 var nextChildren = nextProps.children; 19919 var isDirectTextChild = shouldSetTextContent(type, nextProps); 19920 19921 if (isDirectTextChild) { 19922 // We special case a direct text child of a host node. This is a common 19923 // case. We won't handle it as a reified child. We will instead handle 19924 // this in the host environment that also has access to this prop. That 19925 // avoids allocating another HostText fiber and traversing it. 19926 nextChildren = null; 19927 } else if (prevProps !== null && shouldSetTextContent(type, prevProps)) { 19928 // If we're switching from a direct text child to a normal child, or to 19929 // empty, we need to schedule the text content to be reset. 19930 workInProgress.flags |= ContentReset; 19931 } 19932 19933 markRef(current, workInProgress); 19934 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 19935 return workInProgress.child; 19936 } 19937 19938 function updateHostText(current, workInProgress) { 19939 if (current === null) { 19940 tryToClaimNextHydratableInstance(workInProgress); 19941 } // Nothing to do here. This is terminal. We'll do the completion step 19942 // immediately after. 19943 19944 19945 return null; 19946 } 19947 19948 function mountLazyComponent(_current, workInProgress, elementType, renderLanes) { 19949 resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); 19950 var props = workInProgress.pendingProps; 19951 var lazyComponent = elementType; 19952 var payload = lazyComponent._payload; 19953 var init = lazyComponent._init; 19954 var Component = init(payload); // Store the unwrapped component in the type. 19955 19956 workInProgress.type = Component; 19957 var resolvedTag = workInProgress.tag = resolveLazyComponentTag(Component); 19958 var resolvedProps = resolveDefaultProps(Component, props); 19959 var child; 19960 19961 switch (resolvedTag) { 19962 case FunctionComponent: 19963 { 19964 { 19965 validateFunctionComponentInDev(workInProgress, Component); 19966 workInProgress.type = Component = resolveFunctionForHotReloading(Component); 19967 } 19968 19969 child = updateFunctionComponent(null, workInProgress, Component, resolvedProps, renderLanes); 19970 return child; 19971 } 19972 19973 case ClassComponent: 19974 { 19975 { 19976 workInProgress.type = Component = resolveClassForHotReloading(Component); 19977 } 19978 19979 child = updateClassComponent(null, workInProgress, Component, resolvedProps, renderLanes); 19980 return child; 19981 } 19982 19983 case ForwardRef: 19984 { 19985 { 19986 workInProgress.type = Component = resolveForwardRefForHotReloading(Component); 19987 } 19988 19989 child = updateForwardRef(null, workInProgress, Component, resolvedProps, renderLanes); 19990 return child; 19991 } 19992 19993 case MemoComponent: 19994 { 19995 { 19996 if (workInProgress.type !== workInProgress.elementType) { 19997 var outerPropTypes = Component.propTypes; 19998 19999 if (outerPropTypes) { 20000 checkPropTypes(outerPropTypes, resolvedProps, // Resolved for outer only 20001 'prop', getComponentNameFromType(Component)); 20002 } 20003 } 20004 } 20005 20006 child = updateMemoComponent(null, workInProgress, Component, resolveDefaultProps(Component.type, resolvedProps), // The inner type can have defaults too 20007 renderLanes); 20008 return child; 20009 } 20010 } 20011 20012 var hint = ''; 20013 20014 { 20015 if (Component !== null && typeof Component === 'object' && Component.$$typeof === REACT_LAZY_TYPE) { 20016 hint = ' Did you wrap a component in React.lazy() more than once?'; 20017 } 20018 } // This message intentionally doesn't mention ForwardRef or MemoComponent 20019 // because the fact that it's a separate type of work is an 20020 // implementation detail. 20021 20022 20023 throw new Error("Element type is invalid. Received a promise that resolves to: " + Component + ". " + ("Lazy element type must resolve to a class or function." + hint)); 20024 } 20025 20026 function mountIncompleteClassComponent(_current, workInProgress, Component, nextProps, renderLanes) { 20027 resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); // Promote the fiber to a class and try rendering again. 20028 20029 workInProgress.tag = ClassComponent; // The rest of this function is a fork of `updateClassComponent` 20030 // Push context providers early to prevent context stack mismatches. 20031 // During mounting we don't know the child context yet as the instance doesn't exist. 20032 // We will invalidate the child context in finishClassComponent() right after rendering. 20033 20034 var hasContext; 20035 20036 if (isContextProvider(Component)) { 20037 hasContext = true; 20038 pushContextProvider(workInProgress); 20039 } else { 20040 hasContext = false; 20041 } 20042 20043 prepareToReadContext(workInProgress, renderLanes); 20044 constructClassInstance(workInProgress, Component, nextProps); 20045 mountClassInstance(workInProgress, Component, nextProps, renderLanes); 20046 return finishClassComponent(null, workInProgress, Component, true, hasContext, renderLanes); 20047 } 20048 20049 function mountIndeterminateComponent(_current, workInProgress, Component, renderLanes) { 20050 resetSuspendedCurrentOnMountInLegacyMode(_current, workInProgress); 20051 var props = workInProgress.pendingProps; 20052 var context; 20053 20054 { 20055 var unmaskedContext = getUnmaskedContext(workInProgress, Component, false); 20056 context = getMaskedContext(workInProgress, unmaskedContext); 20057 } 20058 20059 prepareToReadContext(workInProgress, renderLanes); 20060 var value; 20061 var hasId; 20062 20063 { 20064 markComponentRenderStarted(workInProgress); 20065 } 20066 20067 { 20068 if (Component.prototype && typeof Component.prototype.render === 'function') { 20069 var componentName = getComponentNameFromType(Component) || 'Unknown'; 20070 20071 if (!didWarnAboutBadClass[componentName]) { 20072 error("The <%s /> component appears to have a render method, but doesn't extend React.Component. " + 'This is likely to cause errors. Change %s to extend React.Component instead.', componentName, componentName); 20073 20074 didWarnAboutBadClass[componentName] = true; 20075 } 20076 } 20077 20078 if (workInProgress.mode & StrictLegacyMode) { 20079 ReactStrictModeWarnings.recordLegacyContextWarning(workInProgress, null); 20080 } 20081 20082 setIsRendering(true); 20083 ReactCurrentOwner$1.current = workInProgress; 20084 value = renderWithHooks(null, workInProgress, Component, props, context, renderLanes); 20085 hasId = checkDidRenderIdHook(); 20086 setIsRendering(false); 20087 } 20088 20089 { 20090 markComponentRenderStopped(); 20091 } // React DevTools reads this flag. 20092 20093 20094 workInProgress.flags |= PerformedWork; 20095 20096 { 20097 // Support for module components is deprecated and is removed behind a flag. 20098 // Whether or not it would crash later, we want to show a good message in DEV first. 20099 if (typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) { 20100 var _componentName = getComponentNameFromType(Component) || 'Unknown'; 20101 20102 if (!didWarnAboutModulePatternComponent[_componentName]) { 20103 error('The <%s /> component appears to be a function component that returns a class instance. ' + 'Change %s to a class that extends React.Component instead. ' + "If you can't use a class try assigning the prototype on the function as a workaround. " + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + 'cannot be called with `new` by React.', _componentName, _componentName, _componentName); 20104 20105 didWarnAboutModulePatternComponent[_componentName] = true; 20106 } 20107 } 20108 } 20109 20110 if ( // Run these checks in production only if the flag is off. 20111 // Eventually we'll delete this branch altogether. 20112 typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) { 20113 { 20114 var _componentName2 = getComponentNameFromType(Component) || 'Unknown'; 20115 20116 if (!didWarnAboutModulePatternComponent[_componentName2]) { 20117 error('The <%s /> component appears to be a function component that returns a class instance. ' + 'Change %s to a class that extends React.Component instead. ' + "If you can't use a class try assigning the prototype on the function as a workaround. " + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + 'cannot be called with `new` by React.', _componentName2, _componentName2, _componentName2); 20118 20119 didWarnAboutModulePatternComponent[_componentName2] = true; 20120 } 20121 } // Proceed under the assumption that this is a class instance 20122 20123 20124 workInProgress.tag = ClassComponent; // Throw out any hooks that were used. 20125 20126 workInProgress.memoizedState = null; 20127 workInProgress.updateQueue = null; // Push context providers early to prevent context stack mismatches. 20128 // During mounting we don't know the child context yet as the instance doesn't exist. 20129 // We will invalidate the child context in finishClassComponent() right after rendering. 20130 20131 var hasContext = false; 20132 20133 if (isContextProvider(Component)) { 20134 hasContext = true; 20135 pushContextProvider(workInProgress); 20136 } else { 20137 hasContext = false; 20138 } 20139 20140 workInProgress.memoizedState = value.state !== null && value.state !== undefined ? value.state : null; 20141 initializeUpdateQueue(workInProgress); 20142 adoptClassInstance(workInProgress, value); 20143 mountClassInstance(workInProgress, Component, props, renderLanes); 20144 return finishClassComponent(null, workInProgress, Component, true, hasContext, renderLanes); 20145 } else { 20146 // Proceed under the assumption that this is a function component 20147 workInProgress.tag = FunctionComponent; 20148 20149 { 20150 20151 if ( workInProgress.mode & StrictLegacyMode) { 20152 setIsStrictModeForDevtools(true); 20153 20154 try { 20155 value = renderWithHooks(null, workInProgress, Component, props, context, renderLanes); 20156 hasId = checkDidRenderIdHook(); 20157 } finally { 20158 setIsStrictModeForDevtools(false); 20159 } 20160 } 20161 } 20162 20163 if (getIsHydrating() && hasId) { 20164 pushMaterializedTreeId(workInProgress); 20165 } 20166 20167 reconcileChildren(null, workInProgress, value, renderLanes); 20168 20169 { 20170 validateFunctionComponentInDev(workInProgress, Component); 20171 } 20172 20173 return workInProgress.child; 20174 } 20175 } 20176 20177 function validateFunctionComponentInDev(workInProgress, Component) { 20178 { 20179 if (Component) { 20180 if (Component.childContextTypes) { 20181 error('%s(...): childContextTypes cannot be defined on a function component.', Component.displayName || Component.name || 'Component'); 20182 } 20183 } 20184 20185 if (workInProgress.ref !== null) { 20186 var info = ''; 20187 var ownerName = getCurrentFiberOwnerNameInDevOrNull(); 20188 20189 if (ownerName) { 20190 info += '\n\nCheck the render method of `' + ownerName + '`.'; 20191 } 20192 20193 var warningKey = ownerName || ''; 20194 var debugSource = workInProgress._debugSource; 20195 20196 if (debugSource) { 20197 warningKey = debugSource.fileName + ':' + debugSource.lineNumber; 20198 } 20199 20200 if (!didWarnAboutFunctionRefs[warningKey]) { 20201 didWarnAboutFunctionRefs[warningKey] = true; 20202 20203 error('Function components cannot be given refs. ' + 'Attempts to access this ref will fail. ' + 'Did you mean to use React.forwardRef()?%s', info); 20204 } 20205 } 20206 20207 if (typeof Component.getDerivedStateFromProps === 'function') { 20208 var _componentName3 = getComponentNameFromType(Component) || 'Unknown'; 20209 20210 if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { 20211 error('%s: Function components do not support getDerivedStateFromProps.', _componentName3); 20212 20213 didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; 20214 } 20215 } 20216 20217 if (typeof Component.contextType === 'object' && Component.contextType !== null) { 20218 var _componentName4 = getComponentNameFromType(Component) || 'Unknown'; 20219 20220 if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { 20221 error('%s: Function components do not support contextType.', _componentName4); 20222 20223 didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; 20224 } 20225 } 20226 } 20227 } 20228 20229 var SUSPENDED_MARKER = { 20230 dehydrated: null, 20231 treeContext: null, 20232 retryLane: NoLane 20233 }; 20234 20235 function mountSuspenseOffscreenState(renderLanes) { 20236 return { 20237 baseLanes: renderLanes, 20238 cachePool: getSuspendedCache(), 20239 transitions: null 20240 }; 20241 } 20242 20243 function updateSuspenseOffscreenState(prevOffscreenState, renderLanes) { 20244 var cachePool = null; 20245 20246 return { 20247 baseLanes: mergeLanes(prevOffscreenState.baseLanes, renderLanes), 20248 cachePool: cachePool, 20249 transitions: prevOffscreenState.transitions 20250 }; 20251 } // TODO: Probably should inline this back 20252 20253 20254 function shouldRemainOnFallback(suspenseContext, current, workInProgress, renderLanes) { 20255 // If we're already showing a fallback, there are cases where we need to 20256 // remain on that fallback regardless of whether the content has resolved. 20257 // For example, SuspenseList coordinates when nested content appears. 20258 if (current !== null) { 20259 var suspenseState = current.memoizedState; 20260 20261 if (suspenseState === null) { 20262 // Currently showing content. Don't hide it, even if ForceSuspenseFallback 20263 // is true. More precise name might be "ForceRemainSuspenseFallback". 20264 // Note: This is a factoring smell. Can't remain on a fallback if there's 20265 // no fallback to remain on. 20266 return false; 20267 } 20268 } // Not currently showing content. Consult the Suspense context. 20269 20270 20271 return hasSuspenseContext(suspenseContext, ForceSuspenseFallback); 20272 } 20273 20274 function getRemainingWorkInPrimaryTree(current, renderLanes) { 20275 // TODO: Should not remove render lanes that were pinged during this render 20276 return removeLanes(current.childLanes, renderLanes); 20277 } 20278 20279 function updateSuspenseComponent(current, workInProgress, renderLanes) { 20280 var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend. 20281 20282 { 20283 if (shouldSuspend(workInProgress)) { 20284 workInProgress.flags |= DidCapture; 20285 } 20286 } 20287 20288 var suspenseContext = suspenseStackCursor.current; 20289 var showFallback = false; 20290 var didSuspend = (workInProgress.flags & DidCapture) !== NoFlags; 20291 20292 if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) { 20293 // Something in this boundary's subtree already suspended. Switch to 20294 // rendering the fallback children. 20295 showFallback = true; 20296 workInProgress.flags &= ~DidCapture; 20297 } else { 20298 // Attempting the main content 20299 if (current === null || current.memoizedState !== null) { 20300 // This is a new mount or this boundary is already showing a fallback state. 20301 // Mark this subtree context as having at least one invisible parent that could 20302 // handle the fallback state. 20303 // Avoided boundaries are not considered since they cannot handle preferred fallback states. 20304 { 20305 suspenseContext = addSubtreeSuspenseContext(suspenseContext, InvisibleParentSuspenseContext); 20306 } 20307 } 20308 } 20309 20310 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); 20311 pushSuspenseContext(workInProgress, suspenseContext); // OK, the next part is confusing. We're about to reconcile the Suspense 20312 // boundary's children. This involves some custom reconciliation logic. Two 20313 // main reasons this is so complicated. 20314 // 20315 // First, Legacy Mode has different semantics for backwards compatibility. The 20316 // primary tree will commit in an inconsistent state, so when we do the 20317 // second pass to render the fallback, we do some exceedingly, uh, clever 20318 // hacks to make that not totally break. Like transferring effects and 20319 // deletions from hidden tree. In Concurrent Mode, it's much simpler, 20320 // because we bailout on the primary tree completely and leave it in its old 20321 // state, no effects. Same as what we do for Offscreen (except that 20322 // Offscreen doesn't have the first render pass). 20323 // 20324 // Second is hydration. During hydration, the Suspense fiber has a slightly 20325 // different layout, where the child points to a dehydrated fragment, which 20326 // contains the DOM rendered by the server. 20327 // 20328 // Third, even if you set all that aside, Suspense is like error boundaries in 20329 // that we first we try to render one tree, and if that fails, we render again 20330 // and switch to a different tree. Like a try/catch block. So we have to track 20331 // which branch we're currently rendering. Ideally we would model this using 20332 // a stack. 20333 20334 if (current === null) { 20335 // Initial mount 20336 // Special path for hydration 20337 // If we're currently hydrating, try to hydrate this boundary. 20338 tryToClaimNextHydratableInstance(workInProgress); // This could've been a dehydrated suspense component. 20339 20340 var suspenseState = workInProgress.memoizedState; 20341 20342 if (suspenseState !== null) { 20343 var dehydrated = suspenseState.dehydrated; 20344 20345 if (dehydrated !== null) { 20346 return mountDehydratedSuspenseComponent(workInProgress, dehydrated); 20347 } 20348 } 20349 20350 var nextPrimaryChildren = nextProps.children; 20351 var nextFallbackChildren = nextProps.fallback; 20352 20353 if (showFallback) { 20354 var fallbackFragment = mountSuspenseFallbackChildren(workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes); 20355 var primaryChildFragment = workInProgress.child; 20356 primaryChildFragment.memoizedState = mountSuspenseOffscreenState(renderLanes); 20357 workInProgress.memoizedState = SUSPENDED_MARKER; 20358 20359 return fallbackFragment; 20360 } else { 20361 return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); 20362 } 20363 } else { 20364 // This is an update. 20365 // Special path for hydration 20366 var prevState = current.memoizedState; 20367 20368 if (prevState !== null) { 20369 var _dehydrated = prevState.dehydrated; 20370 20371 if (_dehydrated !== null) { 20372 return updateDehydratedSuspenseComponent(current, workInProgress, didSuspend, nextProps, _dehydrated, prevState, renderLanes); 20373 } 20374 } 20375 20376 if (showFallback) { 20377 var _nextFallbackChildren = nextProps.fallback; 20378 var _nextPrimaryChildren = nextProps.children; 20379 var fallbackChildFragment = updateSuspenseFallbackChildren(current, workInProgress, _nextPrimaryChildren, _nextFallbackChildren, renderLanes); 20380 var _primaryChildFragment2 = workInProgress.child; 20381 var prevOffscreenState = current.child.memoizedState; 20382 _primaryChildFragment2.memoizedState = prevOffscreenState === null ? mountSuspenseOffscreenState(renderLanes) : updateSuspenseOffscreenState(prevOffscreenState, renderLanes); 20383 20384 _primaryChildFragment2.childLanes = getRemainingWorkInPrimaryTree(current, renderLanes); 20385 workInProgress.memoizedState = SUSPENDED_MARKER; 20386 return fallbackChildFragment; 20387 } else { 20388 var _nextPrimaryChildren2 = nextProps.children; 20389 20390 var _primaryChildFragment3 = updateSuspensePrimaryChildren(current, workInProgress, _nextPrimaryChildren2, renderLanes); 20391 20392 workInProgress.memoizedState = null; 20393 return _primaryChildFragment3; 20394 } 20395 } 20396 } 20397 20398 function mountSuspensePrimaryChildren(workInProgress, primaryChildren, renderLanes) { 20399 var mode = workInProgress.mode; 20400 var primaryChildProps = { 20401 mode: 'visible', 20402 children: primaryChildren 20403 }; 20404 var primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, mode); 20405 primaryChildFragment.return = workInProgress; 20406 workInProgress.child = primaryChildFragment; 20407 return primaryChildFragment; 20408 } 20409 20410 function mountSuspenseFallbackChildren(workInProgress, primaryChildren, fallbackChildren, renderLanes) { 20411 var mode = workInProgress.mode; 20412 var progressedPrimaryFragment = workInProgress.child; 20413 var primaryChildProps = { 20414 mode: 'hidden', 20415 children: primaryChildren 20416 }; 20417 var primaryChildFragment; 20418 var fallbackChildFragment; 20419 20420 if ((mode & ConcurrentMode) === NoMode && progressedPrimaryFragment !== null) { 20421 // In legacy mode, we commit the primary tree as if it successfully 20422 // completed, even though it's in an inconsistent state. 20423 primaryChildFragment = progressedPrimaryFragment; 20424 primaryChildFragment.childLanes = NoLanes; 20425 primaryChildFragment.pendingProps = primaryChildProps; 20426 20427 if ( workInProgress.mode & ProfileMode) { 20428 // Reset the durations from the first pass so they aren't included in the 20429 // final amounts. This seems counterintuitive, since we're intentionally 20430 // not measuring part of the render phase, but this makes it match what we 20431 // do in Concurrent Mode. 20432 primaryChildFragment.actualDuration = 0; 20433 primaryChildFragment.actualStartTime = -1; 20434 primaryChildFragment.selfBaseDuration = 0; 20435 primaryChildFragment.treeBaseDuration = 0; 20436 } 20437 20438 fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null); 20439 } else { 20440 primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, mode); 20441 fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null); 20442 } 20443 20444 primaryChildFragment.return = workInProgress; 20445 fallbackChildFragment.return = workInProgress; 20446 primaryChildFragment.sibling = fallbackChildFragment; 20447 workInProgress.child = primaryChildFragment; 20448 return fallbackChildFragment; 20449 } 20450 20451 function mountWorkInProgressOffscreenFiber(offscreenProps, mode, renderLanes) { 20452 // The props argument to `createFiberFromOffscreen` is `any` typed, so we use 20453 // this wrapper function to constrain it. 20454 return createFiberFromOffscreen(offscreenProps, mode, NoLanes, null); 20455 } 20456 20457 function updateWorkInProgressOffscreenFiber(current, offscreenProps) { 20458 // The props argument to `createWorkInProgress` is `any` typed, so we use this 20459 // wrapper function to constrain it. 20460 return createWorkInProgress(current, offscreenProps); 20461 } 20462 20463 function updateSuspensePrimaryChildren(current, workInProgress, primaryChildren, renderLanes) { 20464 var currentPrimaryChildFragment = current.child; 20465 var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; 20466 var primaryChildFragment = updateWorkInProgressOffscreenFiber(currentPrimaryChildFragment, { 20467 mode: 'visible', 20468 children: primaryChildren 20469 }); 20470 20471 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 20472 primaryChildFragment.lanes = renderLanes; 20473 } 20474 20475 primaryChildFragment.return = workInProgress; 20476 primaryChildFragment.sibling = null; 20477 20478 if (currentFallbackChildFragment !== null) { 20479 // Delete the fallback child fragment 20480 var deletions = workInProgress.deletions; 20481 20482 if (deletions === null) { 20483 workInProgress.deletions = [currentFallbackChildFragment]; 20484 workInProgress.flags |= ChildDeletion; 20485 } else { 20486 deletions.push(currentFallbackChildFragment); 20487 } 20488 } 20489 20490 workInProgress.child = primaryChildFragment; 20491 return primaryChildFragment; 20492 } 20493 20494 function updateSuspenseFallbackChildren(current, workInProgress, primaryChildren, fallbackChildren, renderLanes) { 20495 var mode = workInProgress.mode; 20496 var currentPrimaryChildFragment = current.child; 20497 var currentFallbackChildFragment = currentPrimaryChildFragment.sibling; 20498 var primaryChildProps = { 20499 mode: 'hidden', 20500 children: primaryChildren 20501 }; 20502 var primaryChildFragment; 20503 20504 if ( // In legacy mode, we commit the primary tree as if it successfully 20505 // completed, even though it's in an inconsistent state. 20506 (mode & ConcurrentMode) === NoMode && // Make sure we're on the second pass, i.e. the primary child fragment was 20507 // already cloned. In legacy mode, the only case where this isn't true is 20508 // when DevTools forces us to display a fallback; we skip the first render 20509 // pass entirely and go straight to rendering the fallback. (In Concurrent 20510 // Mode, SuspenseList can also trigger this scenario, but this is a legacy- 20511 // only codepath.) 20512 workInProgress.child !== currentPrimaryChildFragment) { 20513 var progressedPrimaryFragment = workInProgress.child; 20514 primaryChildFragment = progressedPrimaryFragment; 20515 primaryChildFragment.childLanes = NoLanes; 20516 primaryChildFragment.pendingProps = primaryChildProps; 20517 20518 if ( workInProgress.mode & ProfileMode) { 20519 // Reset the durations from the first pass so they aren't included in the 20520 // final amounts. This seems counterintuitive, since we're intentionally 20521 // not measuring part of the render phase, but this makes it match what we 20522 // do in Concurrent Mode. 20523 primaryChildFragment.actualDuration = 0; 20524 primaryChildFragment.actualStartTime = -1; 20525 primaryChildFragment.selfBaseDuration = currentPrimaryChildFragment.selfBaseDuration; 20526 primaryChildFragment.treeBaseDuration = currentPrimaryChildFragment.treeBaseDuration; 20527 } // The fallback fiber was added as a deletion during the first pass. 20528 // However, since we're going to remain on the fallback, we no longer want 20529 // to delete it. 20530 20531 20532 workInProgress.deletions = null; 20533 } else { 20534 primaryChildFragment = updateWorkInProgressOffscreenFiber(currentPrimaryChildFragment, primaryChildProps); // Since we're reusing a current tree, we need to reuse the flags, too. 20535 // (We don't do this in legacy mode, because in legacy mode we don't re-use 20536 // the current tree; see previous branch.) 20537 20538 primaryChildFragment.subtreeFlags = currentPrimaryChildFragment.subtreeFlags & StaticMask; 20539 } 20540 20541 var fallbackChildFragment; 20542 20543 if (currentFallbackChildFragment !== null) { 20544 fallbackChildFragment = createWorkInProgress(currentFallbackChildFragment, fallbackChildren); 20545 } else { 20546 fallbackChildFragment = createFiberFromFragment(fallbackChildren, mode, renderLanes, null); // Needs a placement effect because the parent (the Suspense boundary) already 20547 // mounted but this is a new fiber. 20548 20549 fallbackChildFragment.flags |= Placement; 20550 } 20551 20552 fallbackChildFragment.return = workInProgress; 20553 primaryChildFragment.return = workInProgress; 20554 primaryChildFragment.sibling = fallbackChildFragment; 20555 workInProgress.child = primaryChildFragment; 20556 return fallbackChildFragment; 20557 } 20558 20559 function retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, recoverableError) { 20560 // Falling back to client rendering. Because this has performance 20561 // implications, it's considered a recoverable error, even though the user 20562 // likely won't observe anything wrong with the UI. 20563 // 20564 // The error is passed in as an argument to enforce that every caller provide 20565 // a custom message, or explicitly opt out (currently the only path that opts 20566 // out is legacy mode; every concurrent path provides an error). 20567 if (recoverableError !== null) { 20568 queueHydrationError(recoverableError); 20569 } // This will add the old fiber to the deletion list 20570 20571 20572 reconcileChildFibers(workInProgress, current.child, null, renderLanes); // We're now not suspended nor dehydrated. 20573 20574 var nextProps = workInProgress.pendingProps; 20575 var primaryChildren = nextProps.children; 20576 var primaryChildFragment = mountSuspensePrimaryChildren(workInProgress, primaryChildren); // Needs a placement effect because the parent (the Suspense boundary) already 20577 // mounted but this is a new fiber. 20578 20579 primaryChildFragment.flags |= Placement; 20580 workInProgress.memoizedState = null; 20581 return primaryChildFragment; 20582 } 20583 20584 function mountSuspenseFallbackAfterRetryWithoutHydrating(current, workInProgress, primaryChildren, fallbackChildren, renderLanes) { 20585 var fiberMode = workInProgress.mode; 20586 var primaryChildProps = { 20587 mode: 'visible', 20588 children: primaryChildren 20589 }; 20590 var primaryChildFragment = mountWorkInProgressOffscreenFiber(primaryChildProps, fiberMode); 20591 var fallbackChildFragment = createFiberFromFragment(fallbackChildren, fiberMode, renderLanes, null); // Needs a placement effect because the parent (the Suspense 20592 // boundary) already mounted but this is a new fiber. 20593 20594 fallbackChildFragment.flags |= Placement; 20595 primaryChildFragment.return = workInProgress; 20596 fallbackChildFragment.return = workInProgress; 20597 primaryChildFragment.sibling = fallbackChildFragment; 20598 workInProgress.child = primaryChildFragment; 20599 20600 if ((workInProgress.mode & ConcurrentMode) !== NoMode) { 20601 // We will have dropped the effect list which contains the 20602 // deletion. We need to reconcile to delete the current child. 20603 reconcileChildFibers(workInProgress, current.child, null, renderLanes); 20604 } 20605 20606 return fallbackChildFragment; 20607 } 20608 20609 function mountDehydratedSuspenseComponent(workInProgress, suspenseInstance, renderLanes) { 20610 // During the first pass, we'll bail out and not drill into the children. 20611 // Instead, we'll leave the content in place and try to hydrate it later. 20612 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 20613 { 20614 error('Cannot hydrate Suspense in legacy mode. Switch from ' + 'ReactDOM.hydrate(element, container) to ' + 'ReactDOMClient.hydrateRoot(container, <App />)' + '.render(element) or remove the Suspense components from ' + 'the server rendered components.'); 20615 } 20616 20617 workInProgress.lanes = laneToLanes(SyncLane); 20618 } else if (isSuspenseInstanceFallback(suspenseInstance)) { 20619 // This is a client-only boundary. Since we won't get any content from the server 20620 // for this, we need to schedule that at a higher priority based on when it would 20621 // have timed out. In theory we could render it in this pass but it would have the 20622 // wrong priority associated with it and will prevent hydration of parent path. 20623 // Instead, we'll leave work left on it to render it in a separate commit. 20624 // TODO This time should be the time at which the server rendered response that is 20625 // a parent to this boundary was displayed. However, since we currently don't have 20626 // a protocol to transfer that time, we'll just estimate it by using the current 20627 // time. This will mean that Suspense timeouts are slightly shifted to later than 20628 // they should be. 20629 // Schedule a normal pri update to render this content. 20630 workInProgress.lanes = laneToLanes(DefaultHydrationLane); 20631 } else { 20632 // We'll continue hydrating the rest at offscreen priority since we'll already 20633 // be showing the right content coming from the server, it is no rush. 20634 workInProgress.lanes = laneToLanes(OffscreenLane); 20635 } 20636 20637 return null; 20638 } 20639 20640 function updateDehydratedSuspenseComponent(current, workInProgress, didSuspend, nextProps, suspenseInstance, suspenseState, renderLanes) { 20641 if (!didSuspend) { 20642 // This is the first render pass. Attempt to hydrate. 20643 // We should never be hydrating at this point because it is the first pass, 20644 // but after we've already committed once. 20645 warnIfHydrating(); 20646 20647 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 20648 return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, // TODO: When we delete legacy mode, we should make this error argument 20649 // required — every concurrent mode path that causes hydration to 20650 // de-opt to client rendering should have an error message. 20651 null); 20652 } 20653 20654 if (isSuspenseInstanceFallback(suspenseInstance)) { 20655 // This boundary is in a permanent fallback state. In this case, we'll never 20656 // get an update and we'll never be able to hydrate the final content. Let's just try the 20657 // client side render instead. 20658 var digest, message, stack; 20659 20660 { 20661 var _getSuspenseInstanceF = getSuspenseInstanceFallbackErrorDetails(suspenseInstance); 20662 20663 digest = _getSuspenseInstanceF.digest; 20664 message = _getSuspenseInstanceF.message; 20665 stack = _getSuspenseInstanceF.stack; 20666 } 20667 20668 var error; 20669 20670 if (message) { 20671 // eslint-disable-next-line react-internal/prod-error-codes 20672 error = new Error(message); 20673 } else { 20674 error = new Error('The server could not finish this Suspense boundary, likely ' + 'due to an error during server rendering. Switched to ' + 'client rendering.'); 20675 } 20676 20677 var capturedValue = createCapturedValue(error, digest, stack); 20678 return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, capturedValue); 20679 } 20680 // any context has changed, we need to treat is as if the input might have changed. 20681 20682 20683 var hasContextChanged = includesSomeLane(renderLanes, current.childLanes); 20684 20685 if (didReceiveUpdate || hasContextChanged) { 20686 // This boundary has changed since the first render. This means that we are now unable to 20687 // hydrate it. We might still be able to hydrate it using a higher priority lane. 20688 var root = getWorkInProgressRoot(); 20689 20690 if (root !== null) { 20691 var attemptHydrationAtLane = getBumpedLaneForHydration(root, renderLanes); 20692 20693 if (attemptHydrationAtLane !== NoLane && attemptHydrationAtLane !== suspenseState.retryLane) { 20694 // Intentionally mutating since this render will get interrupted. This 20695 // is one of the very rare times where we mutate the current tree 20696 // during the render phase. 20697 suspenseState.retryLane = attemptHydrationAtLane; // TODO: Ideally this would inherit the event time of the current render 20698 20699 var eventTime = NoTimestamp; 20700 enqueueConcurrentRenderForLane(current, attemptHydrationAtLane); 20701 scheduleUpdateOnFiber(root, current, attemptHydrationAtLane, eventTime); 20702 } 20703 } // If we have scheduled higher pri work above, this will probably just abort the render 20704 // since we now have higher priority work, but in case it doesn't, we need to prepare to 20705 // render something, if we time out. Even if that requires us to delete everything and 20706 // skip hydration. 20707 // Delay having to do this as long as the suspense timeout allows us. 20708 20709 20710 renderDidSuspendDelayIfPossible(); 20711 20712 var _capturedValue = createCapturedValue(new Error('This Suspense boundary received an update before it finished ' + 'hydrating. This caused the boundary to switch to client rendering. ' + 'The usual way to fix this is to wrap the original update ' + 'in startTransition.')); 20713 20714 return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, _capturedValue); 20715 } else if (isSuspenseInstancePending(suspenseInstance)) { 20716 // This component is still pending more data from the server, so we can't hydrate its 20717 // content. We treat it as if this component suspended itself. It might seem as if 20718 // we could just try to render it client-side instead. However, this will perform a 20719 // lot of unnecessary work and is unlikely to complete since it often will suspend 20720 // on missing data anyway. Additionally, the server might be able to render more 20721 // than we can on the client yet. In that case we'd end up with more fallback states 20722 // on the client than if we just leave it alone. If the server times out or errors 20723 // these should update this boundary to the permanent Fallback state instead. 20724 // Mark it as having captured (i.e. suspended). 20725 workInProgress.flags |= DidCapture; // Leave the child in place. I.e. the dehydrated fragment. 20726 20727 workInProgress.child = current.child; // Register a callback to retry this boundary once the server has sent the result. 20728 20729 var retry = retryDehydratedSuspenseBoundary.bind(null, current); 20730 registerSuspenseInstanceRetry(suspenseInstance, retry); 20731 return null; 20732 } else { 20733 // This is the first attempt. 20734 reenterHydrationStateFromDehydratedSuspenseInstance(workInProgress, suspenseInstance, suspenseState.treeContext); 20735 var primaryChildren = nextProps.children; 20736 var primaryChildFragment = mountSuspensePrimaryChildren(workInProgress, primaryChildren); // Mark the children as hydrating. This is a fast path to know whether this 20737 // tree is part of a hydrating tree. This is used to determine if a child 20738 // node has fully mounted yet, and for scheduling event replaying. 20739 // Conceptually this is similar to Placement in that a new subtree is 20740 // inserted into the React tree here. It just happens to not need DOM 20741 // mutations because it already exists. 20742 20743 primaryChildFragment.flags |= Hydrating; 20744 return primaryChildFragment; 20745 } 20746 } else { 20747 // This is the second render pass. We already attempted to hydrated, but 20748 // something either suspended or errored. 20749 if (workInProgress.flags & ForceClientRender) { 20750 // Something errored during hydration. Try again without hydrating. 20751 workInProgress.flags &= ~ForceClientRender; 20752 20753 var _capturedValue2 = createCapturedValue(new Error('There was an error while hydrating this Suspense boundary. ' + 'Switched to client rendering.')); 20754 20755 return retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes, _capturedValue2); 20756 } else if (workInProgress.memoizedState !== null) { 20757 // Something suspended and we should still be in dehydrated mode. 20758 // Leave the existing child in place. 20759 workInProgress.child = current.child; // The dehydrated completion pass expects this flag to be there 20760 // but the normal suspense pass doesn't. 20761 20762 workInProgress.flags |= DidCapture; 20763 return null; 20764 } else { 20765 // Suspended but we should no longer be in dehydrated mode. 20766 // Therefore we now have to render the fallback. 20767 var nextPrimaryChildren = nextProps.children; 20768 var nextFallbackChildren = nextProps.fallback; 20769 var fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(current, workInProgress, nextPrimaryChildren, nextFallbackChildren, renderLanes); 20770 var _primaryChildFragment4 = workInProgress.child; 20771 _primaryChildFragment4.memoizedState = mountSuspenseOffscreenState(renderLanes); 20772 workInProgress.memoizedState = SUSPENDED_MARKER; 20773 return fallbackChildFragment; 20774 } 20775 } 20776 } 20777 20778 function scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) { 20779 fiber.lanes = mergeLanes(fiber.lanes, renderLanes); 20780 var alternate = fiber.alternate; 20781 20782 if (alternate !== null) { 20783 alternate.lanes = mergeLanes(alternate.lanes, renderLanes); 20784 } 20785 20786 scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot); 20787 } 20788 20789 function propagateSuspenseContextChange(workInProgress, firstChild, renderLanes) { 20790 // Mark any Suspense boundaries with fallbacks as having work to do. 20791 // If they were previously forced into fallbacks, they may now be able 20792 // to unblock. 20793 var node = firstChild; 20794 20795 while (node !== null) { 20796 if (node.tag === SuspenseComponent) { 20797 var state = node.memoizedState; 20798 20799 if (state !== null) { 20800 scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); 20801 } 20802 } else if (node.tag === SuspenseListComponent) { 20803 // If the tail is hidden there might not be an Suspense boundaries 20804 // to schedule work on. In this case we have to schedule it on the 20805 // list itself. 20806 // We don't have to traverse to the children of the list since 20807 // the list will propagate the change when it rerenders. 20808 scheduleSuspenseWorkOnFiber(node, renderLanes, workInProgress); 20809 } else if (node.child !== null) { 20810 node.child.return = node; 20811 node = node.child; 20812 continue; 20813 } 20814 20815 if (node === workInProgress) { 20816 return; 20817 } 20818 20819 while (node.sibling === null) { 20820 if (node.return === null || node.return === workInProgress) { 20821 return; 20822 } 20823 20824 node = node.return; 20825 } 20826 20827 node.sibling.return = node.return; 20828 node = node.sibling; 20829 } 20830 } 20831 20832 function findLastContentRow(firstChild) { 20833 // This is going to find the last row among these children that is already 20834 // showing content on the screen, as opposed to being in fallback state or 20835 // new. If a row has multiple Suspense boundaries, any of them being in the 20836 // fallback state, counts as the whole row being in a fallback state. 20837 // Note that the "rows" will be workInProgress, but any nested children 20838 // will still be current since we haven't rendered them yet. The mounted 20839 // order may not be the same as the new order. We use the new order. 20840 var row = firstChild; 20841 var lastContentRow = null; 20842 20843 while (row !== null) { 20844 var currentRow = row.alternate; // New rows can't be content rows. 20845 20846 if (currentRow !== null && findFirstSuspended(currentRow) === null) { 20847 lastContentRow = row; 20848 } 20849 20850 row = row.sibling; 20851 } 20852 20853 return lastContentRow; 20854 } 20855 20856 function validateRevealOrder(revealOrder) { 20857 { 20858 if (revealOrder !== undefined && revealOrder !== 'forwards' && revealOrder !== 'backwards' && revealOrder !== 'together' && !didWarnAboutRevealOrder[revealOrder]) { 20859 didWarnAboutRevealOrder[revealOrder] = true; 20860 20861 if (typeof revealOrder === 'string') { 20862 switch (revealOrder.toLowerCase()) { 20863 case 'together': 20864 case 'forwards': 20865 case 'backwards': 20866 { 20867 error('"%s" is not a valid value for revealOrder on <SuspenseList />. ' + 'Use lowercase "%s" instead.', revealOrder, revealOrder.toLowerCase()); 20868 20869 break; 20870 } 20871 20872 case 'forward': 20873 case 'backward': 20874 { 20875 error('"%s" is not a valid value for revealOrder on <SuspenseList />. ' + 'React uses the -s suffix in the spelling. Use "%ss" instead.', revealOrder, revealOrder.toLowerCase()); 20876 20877 break; 20878 } 20879 20880 default: 20881 error('"%s" is not a supported revealOrder on <SuspenseList />. ' + 'Did you mean "together", "forwards" or "backwards"?', revealOrder); 20882 20883 break; 20884 } 20885 } else { 20886 error('%s is not a supported value for revealOrder on <SuspenseList />. ' + 'Did you mean "together", "forwards" or "backwards"?', revealOrder); 20887 } 20888 } 20889 } 20890 } 20891 20892 function validateTailOptions(tailMode, revealOrder) { 20893 { 20894 if (tailMode !== undefined && !didWarnAboutTailOptions[tailMode]) { 20895 if (tailMode !== 'collapsed' && tailMode !== 'hidden') { 20896 didWarnAboutTailOptions[tailMode] = true; 20897 20898 error('"%s" is not a supported value for tail on <SuspenseList />. ' + 'Did you mean "collapsed" or "hidden"?', tailMode); 20899 } else if (revealOrder !== 'forwards' && revealOrder !== 'backwards') { 20900 didWarnAboutTailOptions[tailMode] = true; 20901 20902 error('<SuspenseList tail="%s" /> is only valid if revealOrder is ' + '"forwards" or "backwards". ' + 'Did you mean to specify revealOrder="forwards"?', tailMode); 20903 } 20904 } 20905 } 20906 } 20907 20908 function validateSuspenseListNestedChild(childSlot, index) { 20909 { 20910 var isAnArray = isArray(childSlot); 20911 var isIterable = !isAnArray && typeof getIteratorFn(childSlot) === 'function'; 20912 20913 if (isAnArray || isIterable) { 20914 var type = isAnArray ? 'array' : 'iterable'; 20915 20916 error('A nested %s was passed to row #%s in <SuspenseList />. Wrap it in ' + 'an additional SuspenseList to configure its revealOrder: ' + '<SuspenseList revealOrder=...> ... ' + '<SuspenseList revealOrder=...>{%s}</SuspenseList> ... ' + '</SuspenseList>', type, index, type); 20917 20918 return false; 20919 } 20920 } 20921 20922 return true; 20923 } 20924 20925 function validateSuspenseListChildren(children, revealOrder) { 20926 { 20927 if ((revealOrder === 'forwards' || revealOrder === 'backwards') && children !== undefined && children !== null && children !== false) { 20928 if (isArray(children)) { 20929 for (var i = 0; i < children.length; i++) { 20930 if (!validateSuspenseListNestedChild(children[i], i)) { 20931 return; 20932 } 20933 } 20934 } else { 20935 var iteratorFn = getIteratorFn(children); 20936 20937 if (typeof iteratorFn === 'function') { 20938 var childrenIterator = iteratorFn.call(children); 20939 20940 if (childrenIterator) { 20941 var step = childrenIterator.next(); 20942 var _i = 0; 20943 20944 for (; !step.done; step = childrenIterator.next()) { 20945 if (!validateSuspenseListNestedChild(step.value, _i)) { 20946 return; 20947 } 20948 20949 _i++; 20950 } 20951 } 20952 } else { 20953 error('A single row was passed to a <SuspenseList revealOrder="%s" />. ' + 'This is not useful since it needs multiple rows. ' + 'Did you mean to pass multiple children or an array?', revealOrder); 20954 } 20955 } 20956 } 20957 } 20958 } 20959 20960 function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastContentRow, tailMode) { 20961 var renderState = workInProgress.memoizedState; 20962 20963 if (renderState === null) { 20964 workInProgress.memoizedState = { 20965 isBackwards: isBackwards, 20966 rendering: null, 20967 renderingStartTime: 0, 20968 last: lastContentRow, 20969 tail: tail, 20970 tailMode: tailMode 20971 }; 20972 } else { 20973 // We can reuse the existing object from previous renders. 20974 renderState.isBackwards = isBackwards; 20975 renderState.rendering = null; 20976 renderState.renderingStartTime = 0; 20977 renderState.last = lastContentRow; 20978 renderState.tail = tail; 20979 renderState.tailMode = tailMode; 20980 } 20981 } // This can end up rendering this component multiple passes. 20982 // The first pass splits the children fibers into two sets. A head and tail. 20983 // We first render the head. If anything is in fallback state, we do another 20984 // pass through beginWork to rerender all children (including the tail) with 20985 // the force suspend context. If the first render didn't have anything in 20986 // in fallback state. Then we render each row in the tail one-by-one. 20987 // That happens in the completeWork phase without going back to beginWork. 20988 20989 20990 function updateSuspenseListComponent(current, workInProgress, renderLanes) { 20991 var nextProps = workInProgress.pendingProps; 20992 var revealOrder = nextProps.revealOrder; 20993 var tailMode = nextProps.tail; 20994 var newChildren = nextProps.children; 20995 validateRevealOrder(revealOrder); 20996 validateTailOptions(tailMode, revealOrder); 20997 validateSuspenseListChildren(newChildren, revealOrder); 20998 reconcileChildren(current, workInProgress, newChildren, renderLanes); 20999 var suspenseContext = suspenseStackCursor.current; 21000 var shouldForceFallback = hasSuspenseContext(suspenseContext, ForceSuspenseFallback); 21001 21002 if (shouldForceFallback) { 21003 suspenseContext = setShallowSuspenseContext(suspenseContext, ForceSuspenseFallback); 21004 workInProgress.flags |= DidCapture; 21005 } else { 21006 var didSuspendBefore = current !== null && (current.flags & DidCapture) !== NoFlags; 21007 21008 if (didSuspendBefore) { 21009 // If we previously forced a fallback, we need to schedule work 21010 // on any nested boundaries to let them know to try to render 21011 // again. This is the same as context updating. 21012 propagateSuspenseContextChange(workInProgress, workInProgress.child, renderLanes); 21013 } 21014 21015 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); 21016 } 21017 21018 pushSuspenseContext(workInProgress, suspenseContext); 21019 21020 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 21021 // In legacy mode, SuspenseList doesn't work so we just 21022 // use make it a noop by treating it as the default revealOrder. 21023 workInProgress.memoizedState = null; 21024 } else { 21025 switch (revealOrder) { 21026 case 'forwards': 21027 { 21028 var lastContentRow = findLastContentRow(workInProgress.child); 21029 var tail; 21030 21031 if (lastContentRow === null) { 21032 // The whole list is part of the tail. 21033 // TODO: We could fast path by just rendering the tail now. 21034 tail = workInProgress.child; 21035 workInProgress.child = null; 21036 } else { 21037 // Disconnect the tail rows after the content row. 21038 // We're going to render them separately later. 21039 tail = lastContentRow.sibling; 21040 lastContentRow.sibling = null; 21041 } 21042 21043 initSuspenseListRenderState(workInProgress, false, // isBackwards 21044 tail, lastContentRow, tailMode); 21045 break; 21046 } 21047 21048 case 'backwards': 21049 { 21050 // We're going to find the first row that has existing content. 21051 // At the same time we're going to reverse the list of everything 21052 // we pass in the meantime. That's going to be our tail in reverse 21053 // order. 21054 var _tail = null; 21055 var row = workInProgress.child; 21056 workInProgress.child = null; 21057 21058 while (row !== null) { 21059 var currentRow = row.alternate; // New rows can't be content rows. 21060 21061 if (currentRow !== null && findFirstSuspended(currentRow) === null) { 21062 // This is the beginning of the main content. 21063 workInProgress.child = row; 21064 break; 21065 } 21066 21067 var nextRow = row.sibling; 21068 row.sibling = _tail; 21069 _tail = row; 21070 row = nextRow; 21071 } // TODO: If workInProgress.child is null, we can continue on the tail immediately. 21072 21073 21074 initSuspenseListRenderState(workInProgress, true, // isBackwards 21075 _tail, null, // last 21076 tailMode); 21077 break; 21078 } 21079 21080 case 'together': 21081 { 21082 initSuspenseListRenderState(workInProgress, false, // isBackwards 21083 null, // tail 21084 null, // last 21085 undefined); 21086 break; 21087 } 21088 21089 default: 21090 { 21091 // The default reveal order is the same as not having 21092 // a boundary. 21093 workInProgress.memoizedState = null; 21094 } 21095 } 21096 } 21097 21098 return workInProgress.child; 21099 } 21100 21101 function updatePortalComponent(current, workInProgress, renderLanes) { 21102 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); 21103 var nextChildren = workInProgress.pendingProps; 21104 21105 if (current === null) { 21106 // Portals are special because we don't append the children during mount 21107 // but at commit. Therefore we need to track insertions which the normal 21108 // flow doesn't do during mount. This doesn't happen at the root because 21109 // the root always starts with a "current" with a null child. 21110 // TODO: Consider unifying this with how the root works. 21111 workInProgress.child = reconcileChildFibers(workInProgress, null, nextChildren, renderLanes); 21112 } else { 21113 reconcileChildren(current, workInProgress, nextChildren, renderLanes); 21114 } 21115 21116 return workInProgress.child; 21117 } 21118 21119 var hasWarnedAboutUsingNoValuePropOnContextProvider = false; 21120 21121 function updateContextProvider(current, workInProgress, renderLanes) { 21122 var providerType = workInProgress.type; 21123 var context = providerType._context; 21124 var newProps = workInProgress.pendingProps; 21125 var oldProps = workInProgress.memoizedProps; 21126 var newValue = newProps.value; 21127 21128 { 21129 if (!('value' in newProps)) { 21130 if (!hasWarnedAboutUsingNoValuePropOnContextProvider) { 21131 hasWarnedAboutUsingNoValuePropOnContextProvider = true; 21132 21133 error('The `value` prop is required for the `<Context.Provider>`. Did you misspell it or forget to pass it?'); 21134 } 21135 } 21136 21137 var providerPropTypes = workInProgress.type.propTypes; 21138 21139 if (providerPropTypes) { 21140 checkPropTypes(providerPropTypes, newProps, 'prop', 'Context.Provider'); 21141 } 21142 } 21143 21144 pushProvider(workInProgress, context, newValue); 21145 21146 { 21147 if (oldProps !== null) { 21148 var oldValue = oldProps.value; 21149 21150 if (objectIs(oldValue, newValue)) { 21151 // No change. Bailout early if children are the same. 21152 if (oldProps.children === newProps.children && !hasContextChanged()) { 21153 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 21154 } 21155 } else { 21156 // The context value changed. Search for matching consumers and schedule 21157 // them to update. 21158 propagateContextChange(workInProgress, context, renderLanes); 21159 } 21160 } 21161 } 21162 21163 var newChildren = newProps.children; 21164 reconcileChildren(current, workInProgress, newChildren, renderLanes); 21165 return workInProgress.child; 21166 } 21167 21168 var hasWarnedAboutUsingContextAsConsumer = false; 21169 21170 function updateContextConsumer(current, workInProgress, renderLanes) { 21171 var context = workInProgress.type; // The logic below for Context differs depending on PROD or DEV mode. In 21172 // DEV mode, we create a separate object for Context.Consumer that acts 21173 // like a proxy to Context. This proxy object adds unnecessary code in PROD 21174 // so we use the old behaviour (Context.Consumer references Context) to 21175 // reduce size and overhead. The separate object references context via 21176 // a property called "_context", which also gives us the ability to check 21177 // in DEV mode if this property exists or not and warn if it does not. 21178 21179 { 21180 if (context._context === undefined) { 21181 // This may be because it's a Context (rather than a Consumer). 21182 // Or it may be because it's older React where they're the same thing. 21183 // We only want to warn if we're sure it's a new React. 21184 if (context !== context.Consumer) { 21185 if (!hasWarnedAboutUsingContextAsConsumer) { 21186 hasWarnedAboutUsingContextAsConsumer = true; 21187 21188 error('Rendering <Context> directly is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Consumer> instead?'); 21189 } 21190 } 21191 } else { 21192 context = context._context; 21193 } 21194 } 21195 21196 var newProps = workInProgress.pendingProps; 21197 var render = newProps.children; 21198 21199 { 21200 if (typeof render !== 'function') { 21201 error('A context consumer was rendered with multiple children, or a child ' + "that isn't a function. A context consumer expects a single child " + 'that is a function. If you did pass a function, make sure there ' + 'is no trailing or leading whitespace around it.'); 21202 } 21203 } 21204 21205 prepareToReadContext(workInProgress, renderLanes); 21206 var newValue = readContext(context); 21207 21208 { 21209 markComponentRenderStarted(workInProgress); 21210 } 21211 21212 var newChildren; 21213 21214 { 21215 ReactCurrentOwner$1.current = workInProgress; 21216 setIsRendering(true); 21217 newChildren = render(newValue); 21218 setIsRendering(false); 21219 } 21220 21221 { 21222 markComponentRenderStopped(); 21223 } // React DevTools reads this flag. 21224 21225 21226 workInProgress.flags |= PerformedWork; 21227 reconcileChildren(current, workInProgress, newChildren, renderLanes); 21228 return workInProgress.child; 21229 } 21230 21231 function markWorkInProgressReceivedUpdate() { 21232 didReceiveUpdate = true; 21233 } 21234 21235 function resetSuspendedCurrentOnMountInLegacyMode(current, workInProgress) { 21236 if ((workInProgress.mode & ConcurrentMode) === NoMode) { 21237 if (current !== null) { 21238 // A lazy component only mounts if it suspended inside a non- 21239 // concurrent tree, in an inconsistent state. We want to treat it like 21240 // a new mount, even though an empty version of it already committed. 21241 // Disconnect the alternate pointers. 21242 current.alternate = null; 21243 workInProgress.alternate = null; // Since this is conceptually a new fiber, schedule a Placement effect 21244 21245 workInProgress.flags |= Placement; 21246 } 21247 } 21248 } 21249 21250 function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) { 21251 if (current !== null) { 21252 // Reuse previous dependencies 21253 workInProgress.dependencies = current.dependencies; 21254 } 21255 21256 { 21257 // Don't update "base" render times for bailouts. 21258 stopProfilerTimerIfRunning(); 21259 } 21260 21261 markSkippedUpdateLanes(workInProgress.lanes); // Check if the children have any pending work. 21262 21263 if (!includesSomeLane(renderLanes, workInProgress.childLanes)) { 21264 // The children don't have any work either. We can skip them. 21265 // TODO: Once we add back resuming, we should check if the children are 21266 // a work-in-progress set. If so, we need to transfer their effects. 21267 { 21268 return null; 21269 } 21270 } // This fiber doesn't have work, but its subtree does. Clone the child 21271 // fibers and continue. 21272 21273 21274 cloneChildFibers(current, workInProgress); 21275 return workInProgress.child; 21276 } 21277 21278 function remountFiber(current, oldWorkInProgress, newWorkInProgress) { 21279 { 21280 var returnFiber = oldWorkInProgress.return; 21281 21282 if (returnFiber === null) { 21283 // eslint-disable-next-line react-internal/prod-error-codes 21284 throw new Error('Cannot swap the root fiber.'); 21285 } // Disconnect from the old current. 21286 // It will get deleted. 21287 21288 21289 current.alternate = null; 21290 oldWorkInProgress.alternate = null; // Connect to the new tree. 21291 21292 newWorkInProgress.index = oldWorkInProgress.index; 21293 newWorkInProgress.sibling = oldWorkInProgress.sibling; 21294 newWorkInProgress.return = oldWorkInProgress.return; 21295 newWorkInProgress.ref = oldWorkInProgress.ref; // Replace the child/sibling pointers above it. 21296 21297 if (oldWorkInProgress === returnFiber.child) { 21298 returnFiber.child = newWorkInProgress; 21299 } else { 21300 var prevSibling = returnFiber.child; 21301 21302 if (prevSibling === null) { 21303 // eslint-disable-next-line react-internal/prod-error-codes 21304 throw new Error('Expected parent to have a child.'); 21305 } 21306 21307 while (prevSibling.sibling !== oldWorkInProgress) { 21308 prevSibling = prevSibling.sibling; 21309 21310 if (prevSibling === null) { 21311 // eslint-disable-next-line react-internal/prod-error-codes 21312 throw new Error('Expected to find the previous sibling.'); 21313 } 21314 } 21315 21316 prevSibling.sibling = newWorkInProgress; 21317 } // Delete the old fiber and place the new one. 21318 // Since the old fiber is disconnected, we have to schedule it manually. 21319 21320 21321 var deletions = returnFiber.deletions; 21322 21323 if (deletions === null) { 21324 returnFiber.deletions = [current]; 21325 returnFiber.flags |= ChildDeletion; 21326 } else { 21327 deletions.push(current); 21328 } 21329 21330 newWorkInProgress.flags |= Placement; // Restart work from the new fiber. 21331 21332 return newWorkInProgress; 21333 } 21334 } 21335 21336 function checkScheduledUpdateOrContext(current, renderLanes) { 21337 // Before performing an early bailout, we must check if there are pending 21338 // updates or context. 21339 var updateLanes = current.lanes; 21340 21341 if (includesSomeLane(updateLanes, renderLanes)) { 21342 return true; 21343 } // No pending update, but because context is propagated lazily, we need 21344 21345 return false; 21346 } 21347 21348 function attemptEarlyBailoutIfNoScheduledUpdate(current, workInProgress, renderLanes) { 21349 // This fiber does not have any pending work. Bailout without entering 21350 // the begin phase. There's still some bookkeeping we that needs to be done 21351 // in this optimized path, mostly pushing stuff onto the stack. 21352 switch (workInProgress.tag) { 21353 case HostRoot: 21354 pushHostRootContext(workInProgress); 21355 var root = workInProgress.stateNode; 21356 21357 resetHydrationState(); 21358 break; 21359 21360 case HostComponent: 21361 pushHostContext(workInProgress); 21362 break; 21363 21364 case ClassComponent: 21365 { 21366 var Component = workInProgress.type; 21367 21368 if (isContextProvider(Component)) { 21369 pushContextProvider(workInProgress); 21370 } 21371 21372 break; 21373 } 21374 21375 case HostPortal: 21376 pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); 21377 break; 21378 21379 case ContextProvider: 21380 { 21381 var newValue = workInProgress.memoizedProps.value; 21382 var context = workInProgress.type._context; 21383 pushProvider(workInProgress, context, newValue); 21384 break; 21385 } 21386 21387 case Profiler: 21388 { 21389 // Profiler should only call onRender when one of its descendants actually rendered. 21390 var hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes); 21391 21392 if (hasChildWork) { 21393 workInProgress.flags |= Update; 21394 } 21395 21396 { 21397 // Reset effect durations for the next eventual effect phase. 21398 // These are reset during render to allow the DevTools commit hook a chance to read them, 21399 var stateNode = workInProgress.stateNode; 21400 stateNode.effectDuration = 0; 21401 stateNode.passiveEffectDuration = 0; 21402 } 21403 } 21404 21405 break; 21406 21407 case SuspenseComponent: 21408 { 21409 var state = workInProgress.memoizedState; 21410 21411 if (state !== null) { 21412 if (state.dehydrated !== null) { 21413 pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current)); // We know that this component will suspend again because if it has 21414 // been unsuspended it has committed as a resolved Suspense component. 21415 // If it needs to be retried, it should have work scheduled on it. 21416 21417 workInProgress.flags |= DidCapture; // We should never render the children of a dehydrated boundary until we 21418 // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork. 21419 21420 return null; 21421 } // If this boundary is currently timed out, we need to decide 21422 // whether to retry the primary children, or to skip over it and 21423 // go straight to the fallback. Check the priority of the primary 21424 // child fragment. 21425 21426 21427 var primaryChildFragment = workInProgress.child; 21428 var primaryChildLanes = primaryChildFragment.childLanes; 21429 21430 if (includesSomeLane(renderLanes, primaryChildLanes)) { 21431 // The primary children have pending work. Use the normal path 21432 // to attempt to render the primary children again. 21433 return updateSuspenseComponent(current, workInProgress, renderLanes); 21434 } else { 21435 // The primary child fragment does not have pending work marked 21436 // on it 21437 pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current)); // The primary children do not have pending work with sufficient 21438 // priority. Bailout. 21439 21440 var child = bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 21441 21442 if (child !== null) { 21443 // The fallback children have pending work. Skip over the 21444 // primary children and work on the fallback. 21445 return child.sibling; 21446 } else { 21447 // Note: We can return `null` here because we already checked 21448 // whether there were nested context consumers, via the call to 21449 // `bailoutOnAlreadyFinishedWork` above. 21450 return null; 21451 } 21452 } 21453 } else { 21454 pushSuspenseContext(workInProgress, setDefaultShallowSuspenseContext(suspenseStackCursor.current)); 21455 } 21456 21457 break; 21458 } 21459 21460 case SuspenseListComponent: 21461 { 21462 var didSuspendBefore = (current.flags & DidCapture) !== NoFlags; 21463 21464 var _hasChildWork = includesSomeLane(renderLanes, workInProgress.childLanes); 21465 21466 if (didSuspendBefore) { 21467 if (_hasChildWork) { 21468 // If something was in fallback state last time, and we have all the 21469 // same children then we're still in progressive loading state. 21470 // Something might get unblocked by state updates or retries in the 21471 // tree which will affect the tail. So we need to use the normal 21472 // path to compute the correct tail. 21473 return updateSuspenseListComponent(current, workInProgress, renderLanes); 21474 } // If none of the children had any work, that means that none of 21475 // them got retried so they'll still be blocked in the same way 21476 // as before. We can fast bail out. 21477 21478 21479 workInProgress.flags |= DidCapture; 21480 } // If nothing suspended before and we're rendering the same children, 21481 // then the tail doesn't matter. Anything new that suspends will work 21482 // in the "together" mode, so we can continue from the state we had. 21483 21484 21485 var renderState = workInProgress.memoizedState; 21486 21487 if (renderState !== null) { 21488 // Reset to the "together" mode in case we've started a different 21489 // update in the past but didn't complete it. 21490 renderState.rendering = null; 21491 renderState.tail = null; 21492 renderState.lastEffect = null; 21493 } 21494 21495 pushSuspenseContext(workInProgress, suspenseStackCursor.current); 21496 21497 if (_hasChildWork) { 21498 break; 21499 } else { 21500 // If none of the children had any work, that means that none of 21501 // them got retried so they'll still be blocked in the same way 21502 // as before. We can fast bail out. 21503 return null; 21504 } 21505 } 21506 21507 case OffscreenComponent: 21508 case LegacyHiddenComponent: 21509 { 21510 // Need to check if the tree still needs to be deferred. This is 21511 // almost identical to the logic used in the normal update path, 21512 // so we'll just enter that. The only difference is we'll bail out 21513 // at the next level instead of this one, because the child props 21514 // have not changed. Which is fine. 21515 // TODO: Probably should refactor `beginWork` to split the bailout 21516 // path from the normal path. I'm tempted to do a labeled break here 21517 // but I won't :) 21518 workInProgress.lanes = NoLanes; 21519 return updateOffscreenComponent(current, workInProgress, renderLanes); 21520 } 21521 } 21522 21523 return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes); 21524 } 21525 21526 function beginWork(current, workInProgress, renderLanes) { 21527 { 21528 if (workInProgress._debugNeedsRemount && current !== null) { 21529 // This will restart the begin phase with a new fiber. 21530 return remountFiber(current, workInProgress, createFiberFromTypeAndProps(workInProgress.type, workInProgress.key, workInProgress.pendingProps, workInProgress._debugOwner || null, workInProgress.mode, workInProgress.lanes)); 21531 } 21532 } 21533 21534 if (current !== null) { 21535 var oldProps = current.memoizedProps; 21536 var newProps = workInProgress.pendingProps; 21537 21538 if (oldProps !== newProps || hasContextChanged() || ( // Force a re-render if the implementation changed due to hot reload: 21539 workInProgress.type !== current.type )) { 21540 // If props or context changed, mark the fiber as having performed work. 21541 // This may be unset if the props are determined to be equal later (memo). 21542 didReceiveUpdate = true; 21543 } else { 21544 // Neither props nor legacy context changes. Check if there's a pending 21545 // update or context change. 21546 var hasScheduledUpdateOrContext = checkScheduledUpdateOrContext(current, renderLanes); 21547 21548 if (!hasScheduledUpdateOrContext && // If this is the second pass of an error or suspense boundary, there 21549 // may not be work scheduled on `current`, so we check for this flag. 21550 (workInProgress.flags & DidCapture) === NoFlags) { 21551 // No pending updates or context. Bail out now. 21552 didReceiveUpdate = false; 21553 return attemptEarlyBailoutIfNoScheduledUpdate(current, workInProgress, renderLanes); 21554 } 21555 21556 if ((current.flags & ForceUpdateForLegacySuspense) !== NoFlags) { 21557 // This is a special case that only exists for legacy mode. 21558 // See https://github.com/facebook/react/pull/19216. 21559 didReceiveUpdate = true; 21560 } else { 21561 // An update was scheduled on this fiber, but there are no new props 21562 // nor legacy context. Set this to false. If an update queue or context 21563 // consumer produces a changed value, it will set this to true. Otherwise, 21564 // the component will assume the children have not changed and bail out. 21565 didReceiveUpdate = false; 21566 } 21567 } 21568 } else { 21569 didReceiveUpdate = false; 21570 21571 if (getIsHydrating() && isForkedChild(workInProgress)) { 21572 // Check if this child belongs to a list of muliple children in 21573 // its parent. 21574 // 21575 // In a true multi-threaded implementation, we would render children on 21576 // parallel threads. This would represent the beginning of a new render 21577 // thread for this subtree. 21578 // 21579 // We only use this for id generation during hydration, which is why the 21580 // logic is located in this special branch. 21581 var slotIndex = workInProgress.index; 21582 var numberOfForks = getForksAtLevel(); 21583 pushTreeId(workInProgress, numberOfForks, slotIndex); 21584 } 21585 } // Before entering the begin phase, clear pending update priority. 21586 // TODO: This assumes that we're about to evaluate the component and process 21587 // the update queue. However, there's an exception: SimpleMemoComponent 21588 // sometimes bails out later in the begin phase. This indicates that we should 21589 // move this assignment out of the common path and into each branch. 21590 21591 21592 workInProgress.lanes = NoLanes; 21593 21594 switch (workInProgress.tag) { 21595 case IndeterminateComponent: 21596 { 21597 return mountIndeterminateComponent(current, workInProgress, workInProgress.type, renderLanes); 21598 } 21599 21600 case LazyComponent: 21601 { 21602 var elementType = workInProgress.elementType; 21603 return mountLazyComponent(current, workInProgress, elementType, renderLanes); 21604 } 21605 21606 case FunctionComponent: 21607 { 21608 var Component = workInProgress.type; 21609 var unresolvedProps = workInProgress.pendingProps; 21610 var resolvedProps = workInProgress.elementType === Component ? unresolvedProps : resolveDefaultProps(Component, unresolvedProps); 21611 return updateFunctionComponent(current, workInProgress, Component, resolvedProps, renderLanes); 21612 } 21613 21614 case ClassComponent: 21615 { 21616 var _Component = workInProgress.type; 21617 var _unresolvedProps = workInProgress.pendingProps; 21618 21619 var _resolvedProps = workInProgress.elementType === _Component ? _unresolvedProps : resolveDefaultProps(_Component, _unresolvedProps); 21620 21621 return updateClassComponent(current, workInProgress, _Component, _resolvedProps, renderLanes); 21622 } 21623 21624 case HostRoot: 21625 return updateHostRoot(current, workInProgress, renderLanes); 21626 21627 case HostComponent: 21628 return updateHostComponent(current, workInProgress, renderLanes); 21629 21630 case HostText: 21631 return updateHostText(current, workInProgress); 21632 21633 case SuspenseComponent: 21634 return updateSuspenseComponent(current, workInProgress, renderLanes); 21635 21636 case HostPortal: 21637 return updatePortalComponent(current, workInProgress, renderLanes); 21638 21639 case ForwardRef: 21640 { 21641 var type = workInProgress.type; 21642 var _unresolvedProps2 = workInProgress.pendingProps; 21643 21644 var _resolvedProps2 = workInProgress.elementType === type ? _unresolvedProps2 : resolveDefaultProps(type, _unresolvedProps2); 21645 21646 return updateForwardRef(current, workInProgress, type, _resolvedProps2, renderLanes); 21647 } 21648 21649 case Fragment: 21650 return updateFragment(current, workInProgress, renderLanes); 21651 21652 case Mode: 21653 return updateMode(current, workInProgress, renderLanes); 21654 21655 case Profiler: 21656 return updateProfiler(current, workInProgress, renderLanes); 21657 21658 case ContextProvider: 21659 return updateContextProvider(current, workInProgress, renderLanes); 21660 21661 case ContextConsumer: 21662 return updateContextConsumer(current, workInProgress, renderLanes); 21663 21664 case MemoComponent: 21665 { 21666 var _type2 = workInProgress.type; 21667 var _unresolvedProps3 = workInProgress.pendingProps; // Resolve outer props first, then resolve inner props. 21668 21669 var _resolvedProps3 = resolveDefaultProps(_type2, _unresolvedProps3); 21670 21671 { 21672 if (workInProgress.type !== workInProgress.elementType) { 21673 var outerPropTypes = _type2.propTypes; 21674 21675 if (outerPropTypes) { 21676 checkPropTypes(outerPropTypes, _resolvedProps3, // Resolved for outer only 21677 'prop', getComponentNameFromType(_type2)); 21678 } 21679 } 21680 } 21681 21682 _resolvedProps3 = resolveDefaultProps(_type2.type, _resolvedProps3); 21683 return updateMemoComponent(current, workInProgress, _type2, _resolvedProps3, renderLanes); 21684 } 21685 21686 case SimpleMemoComponent: 21687 { 21688 return updateSimpleMemoComponent(current, workInProgress, workInProgress.type, workInProgress.pendingProps, renderLanes); 21689 } 21690 21691 case IncompleteClassComponent: 21692 { 21693 var _Component2 = workInProgress.type; 21694 var _unresolvedProps4 = workInProgress.pendingProps; 21695 21696 var _resolvedProps4 = workInProgress.elementType === _Component2 ? _unresolvedProps4 : resolveDefaultProps(_Component2, _unresolvedProps4); 21697 21698 return mountIncompleteClassComponent(current, workInProgress, _Component2, _resolvedProps4, renderLanes); 21699 } 21700 21701 case SuspenseListComponent: 21702 { 21703 return updateSuspenseListComponent(current, workInProgress, renderLanes); 21704 } 21705 21706 case ScopeComponent: 21707 { 21708 21709 break; 21710 } 21711 21712 case OffscreenComponent: 21713 { 21714 return updateOffscreenComponent(current, workInProgress, renderLanes); 21715 } 21716 } 21717 21718 throw new Error("Unknown unit of work tag (" + workInProgress.tag + "). This error is likely caused by a bug in " + 'React. Please file an issue.'); 21719 } 21720 21721 function markUpdate(workInProgress) { 21722 // Tag the fiber with an update effect. This turns a Placement into 21723 // a PlacementAndUpdate. 21724 workInProgress.flags |= Update; 21725 } 21726 21727 function markRef$1(workInProgress) { 21728 workInProgress.flags |= Ref; 21729 21730 { 21731 workInProgress.flags |= RefStatic; 21732 } 21733 } 21734 21735 var appendAllChildren; 21736 var updateHostContainer; 21737 var updateHostComponent$1; 21738 var updateHostText$1; 21739 21740 { 21741 // Mutation mode 21742 appendAllChildren = function (parent, workInProgress, needsVisibilityToggle, isHidden) { 21743 // We only have the top Fiber that was created but we need recurse down its 21744 // children to find all the terminal nodes. 21745 var node = workInProgress.child; 21746 21747 while (node !== null) { 21748 if (node.tag === HostComponent || node.tag === HostText) { 21749 appendInitialChild(parent, node.stateNode); 21750 } else if (node.tag === HostPortal) ; else if (node.child !== null) { 21751 node.child.return = node; 21752 node = node.child; 21753 continue; 21754 } 21755 21756 if (node === workInProgress) { 21757 return; 21758 } 21759 21760 while (node.sibling === null) { 21761 if (node.return === null || node.return === workInProgress) { 21762 return; 21763 } 21764 21765 node = node.return; 21766 } 21767 21768 node.sibling.return = node.return; 21769 node = node.sibling; 21770 } 21771 }; 21772 21773 updateHostContainer = function (current, workInProgress) {// Noop 21774 }; 21775 21776 updateHostComponent$1 = function (current, workInProgress, type, newProps, rootContainerInstance) { 21777 // If we have an alternate, that means this is an update and we need to 21778 // schedule a side-effect to do the updates. 21779 var oldProps = current.memoizedProps; 21780 21781 if (oldProps === newProps) { 21782 // In mutation mode, this is sufficient for a bailout because 21783 // we won't touch this node even if children changed. 21784 return; 21785 } // If we get updated because one of our children updated, we don't 21786 // have newProps so we'll have to reuse them. 21787 // TODO: Split the update API as separate for the props vs. children. 21788 // Even better would be if children weren't special cased at all tho. 21789 21790 21791 var instance = workInProgress.stateNode; 21792 var currentHostContext = getHostContext(); // TODO: Experiencing an error where oldProps is null. Suggests a host 21793 // component is hitting the resume path. Figure out why. Possibly 21794 // related to `hidden`. 21795 21796 var updatePayload = prepareUpdate(instance, type, oldProps, newProps, rootContainerInstance, currentHostContext); // TODO: Type this specific to this type of component. 21797 21798 workInProgress.updateQueue = updatePayload; // If the update payload indicates that there is a change or if there 21799 // is a new ref we mark this as an update. All the work is done in commitWork. 21800 21801 if (updatePayload) { 21802 markUpdate(workInProgress); 21803 } 21804 }; 21805 21806 updateHostText$1 = function (current, workInProgress, oldText, newText) { 21807 // If the text differs, mark it as an update. All the work in done in commitWork. 21808 if (oldText !== newText) { 21809 markUpdate(workInProgress); 21810 } 21811 }; 21812 } 21813 21814 function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { 21815 if (getIsHydrating()) { 21816 // If we're hydrating, we should consume as many items as we can 21817 // so we don't leave any behind. 21818 return; 21819 } 21820 21821 switch (renderState.tailMode) { 21822 case 'hidden': 21823 { 21824 // Any insertions at the end of the tail list after this point 21825 // should be invisible. If there are already mounted boundaries 21826 // anything before them are not considered for collapsing. 21827 // Therefore we need to go through the whole tail to find if 21828 // there are any. 21829 var tailNode = renderState.tail; 21830 var lastTailNode = null; 21831 21832 while (tailNode !== null) { 21833 if (tailNode.alternate !== null) { 21834 lastTailNode = tailNode; 21835 } 21836 21837 tailNode = tailNode.sibling; 21838 } // Next we're simply going to delete all insertions after the 21839 // last rendered item. 21840 21841 21842 if (lastTailNode === null) { 21843 // All remaining items in the tail are insertions. 21844 renderState.tail = null; 21845 } else { 21846 // Detach the insertion after the last node that was already 21847 // inserted. 21848 lastTailNode.sibling = null; 21849 } 21850 21851 break; 21852 } 21853 21854 case 'collapsed': 21855 { 21856 // Any insertions at the end of the tail list after this point 21857 // should be invisible. If there are already mounted boundaries 21858 // anything before them are not considered for collapsing. 21859 // Therefore we need to go through the whole tail to find if 21860 // there are any. 21861 var _tailNode = renderState.tail; 21862 var _lastTailNode = null; 21863 21864 while (_tailNode !== null) { 21865 if (_tailNode.alternate !== null) { 21866 _lastTailNode = _tailNode; 21867 } 21868 21869 _tailNode = _tailNode.sibling; 21870 } // Next we're simply going to delete all insertions after the 21871 // last rendered item. 21872 21873 21874 if (_lastTailNode === null) { 21875 // All remaining items in the tail are insertions. 21876 if (!hasRenderedATailFallback && renderState.tail !== null) { 21877 // We suspended during the head. We want to show at least one 21878 // row at the tail. So we'll keep on and cut off the rest. 21879 renderState.tail.sibling = null; 21880 } else { 21881 renderState.tail = null; 21882 } 21883 } else { 21884 // Detach the insertion after the last node that was already 21885 // inserted. 21886 _lastTailNode.sibling = null; 21887 } 21888 21889 break; 21890 } 21891 } 21892 } 21893 21894 function bubbleProperties(completedWork) { 21895 var didBailout = completedWork.alternate !== null && completedWork.alternate.child === completedWork.child; 21896 var newChildLanes = NoLanes; 21897 var subtreeFlags = NoFlags; 21898 21899 if (!didBailout) { 21900 // Bubble up the earliest expiration time. 21901 if ( (completedWork.mode & ProfileMode) !== NoMode) { 21902 // In profiling mode, resetChildExpirationTime is also used to reset 21903 // profiler durations. 21904 var actualDuration = completedWork.actualDuration; 21905 var treeBaseDuration = completedWork.selfBaseDuration; 21906 var child = completedWork.child; 21907 21908 while (child !== null) { 21909 newChildLanes = mergeLanes(newChildLanes, mergeLanes(child.lanes, child.childLanes)); 21910 subtreeFlags |= child.subtreeFlags; 21911 subtreeFlags |= child.flags; // When a fiber is cloned, its actualDuration is reset to 0. This value will 21912 // only be updated if work is done on the fiber (i.e. it doesn't bailout). 21913 // When work is done, it should bubble to the parent's actualDuration. If 21914 // the fiber has not been cloned though, (meaning no work was done), then 21915 // this value will reflect the amount of time spent working on a previous 21916 // render. In that case it should not bubble. We determine whether it was 21917 // cloned by comparing the child pointer. 21918 21919 actualDuration += child.actualDuration; 21920 treeBaseDuration += child.treeBaseDuration; 21921 child = child.sibling; 21922 } 21923 21924 completedWork.actualDuration = actualDuration; 21925 completedWork.treeBaseDuration = treeBaseDuration; 21926 } else { 21927 var _child = completedWork.child; 21928 21929 while (_child !== null) { 21930 newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child.lanes, _child.childLanes)); 21931 subtreeFlags |= _child.subtreeFlags; 21932 subtreeFlags |= _child.flags; // Update the return pointer so the tree is consistent. This is a code 21933 // smell because it assumes the commit phase is never concurrent with 21934 // the render phase. Will address during refactor to alternate model. 21935 21936 _child.return = completedWork; 21937 _child = _child.sibling; 21938 } 21939 } 21940 21941 completedWork.subtreeFlags |= subtreeFlags; 21942 } else { 21943 // Bubble up the earliest expiration time. 21944 if ( (completedWork.mode & ProfileMode) !== NoMode) { 21945 // In profiling mode, resetChildExpirationTime is also used to reset 21946 // profiler durations. 21947 var _treeBaseDuration = completedWork.selfBaseDuration; 21948 var _child2 = completedWork.child; 21949 21950 while (_child2 !== null) { 21951 newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child2.lanes, _child2.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to, 21952 // so we should bubble those up even during a bailout. All the other 21953 // flags have a lifetime only of a single render + commit, so we should 21954 // ignore them. 21955 21956 subtreeFlags |= _child2.subtreeFlags & StaticMask; 21957 subtreeFlags |= _child2.flags & StaticMask; 21958 _treeBaseDuration += _child2.treeBaseDuration; 21959 _child2 = _child2.sibling; 21960 } 21961 21962 completedWork.treeBaseDuration = _treeBaseDuration; 21963 } else { 21964 var _child3 = completedWork.child; 21965 21966 while (_child3 !== null) { 21967 newChildLanes = mergeLanes(newChildLanes, mergeLanes(_child3.lanes, _child3.childLanes)); // "Static" flags share the lifetime of the fiber/hook they belong to, 21968 // so we should bubble those up even during a bailout. All the other 21969 // flags have a lifetime only of a single render + commit, so we should 21970 // ignore them. 21971 21972 subtreeFlags |= _child3.subtreeFlags & StaticMask; 21973 subtreeFlags |= _child3.flags & StaticMask; // Update the return pointer so the tree is consistent. This is a code 21974 // smell because it assumes the commit phase is never concurrent with 21975 // the render phase. Will address during refactor to alternate model. 21976 21977 _child3.return = completedWork; 21978 _child3 = _child3.sibling; 21979 } 21980 } 21981 21982 completedWork.subtreeFlags |= subtreeFlags; 21983 } 21984 21985 completedWork.childLanes = newChildLanes; 21986 return didBailout; 21987 } 21988 21989 function completeDehydratedSuspenseBoundary(current, workInProgress, nextState) { 21990 if (hasUnhydratedTailNodes() && (workInProgress.mode & ConcurrentMode) !== NoMode && (workInProgress.flags & DidCapture) === NoFlags) { 21991 warnIfUnhydratedTailNodes(workInProgress); 21992 resetHydrationState(); 21993 workInProgress.flags |= ForceClientRender | Incomplete | ShouldCapture; 21994 return false; 21995 } 21996 21997 var wasHydrated = popHydrationState(workInProgress); 21998 21999 if (nextState !== null && nextState.dehydrated !== null) { 22000 // We might be inside a hydration state the first time we're picking up this 22001 // Suspense boundary, and also after we've reentered it for further hydration. 22002 if (current === null) { 22003 if (!wasHydrated) { 22004 throw new Error('A dehydrated suspense component was completed without a hydrated node. ' + 'This is probably a bug in React.'); 22005 } 22006 22007 prepareToHydrateHostSuspenseInstance(workInProgress); 22008 bubbleProperties(workInProgress); 22009 22010 { 22011 if ((workInProgress.mode & ProfileMode) !== NoMode) { 22012 var isTimedOutSuspense = nextState !== null; 22013 22014 if (isTimedOutSuspense) { 22015 // Don't count time spent in a timed out Suspense subtree as part of the base duration. 22016 var primaryChildFragment = workInProgress.child; 22017 22018 if (primaryChildFragment !== null) { 22019 // $FlowFixMe Flow doesn't support type casting in combination with the -= operator 22020 workInProgress.treeBaseDuration -= primaryChildFragment.treeBaseDuration; 22021 } 22022 } 22023 } 22024 } 22025 22026 return false; 22027 } else { 22028 // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration 22029 // state since we're now exiting out of it. popHydrationState doesn't do that for us. 22030 resetHydrationState(); 22031 22032 if ((workInProgress.flags & DidCapture) === NoFlags) { 22033 // This boundary did not suspend so it's now hydrated and unsuspended. 22034 workInProgress.memoizedState = null; 22035 } // If nothing suspended, we need to schedule an effect to mark this boundary 22036 // as having hydrated so events know that they're free to be invoked. 22037 // It's also a signal to replay events and the suspense callback. 22038 // If something suspended, schedule an effect to attach retry listeners. 22039 // So we might as well always mark this. 22040 22041 22042 workInProgress.flags |= Update; 22043 bubbleProperties(workInProgress); 22044 22045 { 22046 if ((workInProgress.mode & ProfileMode) !== NoMode) { 22047 var _isTimedOutSuspense = nextState !== null; 22048 22049 if (_isTimedOutSuspense) { 22050 // Don't count time spent in a timed out Suspense subtree as part of the base duration. 22051 var _primaryChildFragment = workInProgress.child; 22052 22053 if (_primaryChildFragment !== null) { 22054 // $FlowFixMe Flow doesn't support type casting in combination with the -= operator 22055 workInProgress.treeBaseDuration -= _primaryChildFragment.treeBaseDuration; 22056 } 22057 } 22058 } 22059 } 22060 22061 return false; 22062 } 22063 } else { 22064 // Successfully completed this tree. If this was a forced client render, 22065 // there may have been recoverable errors during first hydration 22066 // attempt. If so, add them to a queue so we can log them in the 22067 // commit phase. 22068 upgradeHydrationErrorsToRecoverable(); // Fall through to normal Suspense path 22069 22070 return true; 22071 } 22072 } 22073 22074 function completeWork(current, workInProgress, renderLanes) { 22075 var newProps = workInProgress.pendingProps; // Note: This intentionally doesn't check if we're hydrating because comparing 22076 // to the current tree provider fiber is just as fast and less error-prone. 22077 // Ideally we would have a special version of the work loop only 22078 // for hydration. 22079 22080 popTreeContext(workInProgress); 22081 22082 switch (workInProgress.tag) { 22083 case IndeterminateComponent: 22084 case LazyComponent: 22085 case SimpleMemoComponent: 22086 case FunctionComponent: 22087 case ForwardRef: 22088 case Fragment: 22089 case Mode: 22090 case Profiler: 22091 case ContextConsumer: 22092 case MemoComponent: 22093 bubbleProperties(workInProgress); 22094 return null; 22095 22096 case ClassComponent: 22097 { 22098 var Component = workInProgress.type; 22099 22100 if (isContextProvider(Component)) { 22101 popContext(workInProgress); 22102 } 22103 22104 bubbleProperties(workInProgress); 22105 return null; 22106 } 22107 22108 case HostRoot: 22109 { 22110 var fiberRoot = workInProgress.stateNode; 22111 popHostContainer(workInProgress); 22112 popTopLevelContextObject(workInProgress); 22113 resetWorkInProgressVersions(); 22114 22115 if (fiberRoot.pendingContext) { 22116 fiberRoot.context = fiberRoot.pendingContext; 22117 fiberRoot.pendingContext = null; 22118 } 22119 22120 if (current === null || current.child === null) { 22121 // If we hydrated, pop so that we can delete any remaining children 22122 // that weren't hydrated. 22123 var wasHydrated = popHydrationState(workInProgress); 22124 22125 if (wasHydrated) { 22126 // If we hydrated, then we'll need to schedule an update for 22127 // the commit side-effects on the root. 22128 markUpdate(workInProgress); 22129 } else { 22130 if (current !== null) { 22131 var prevState = current.memoizedState; 22132 22133 if ( // Check if this is a client root 22134 !prevState.isDehydrated || // Check if we reverted to client rendering (e.g. due to an error) 22135 (workInProgress.flags & ForceClientRender) !== NoFlags) { 22136 // Schedule an effect to clear this container at the start of the 22137 // next commit. This handles the case of React rendering into a 22138 // container with previous children. It's also safe to do for 22139 // updates too, because current.child would only be null if the 22140 // previous render was null (so the container would already 22141 // be empty). 22142 workInProgress.flags |= Snapshot; // If this was a forced client render, there may have been 22143 // recoverable errors during first hydration attempt. If so, add 22144 // them to a queue so we can log them in the commit phase. 22145 22146 upgradeHydrationErrorsToRecoverable(); 22147 } 22148 } 22149 } 22150 } 22151 22152 updateHostContainer(current, workInProgress); 22153 bubbleProperties(workInProgress); 22154 22155 return null; 22156 } 22157 22158 case HostComponent: 22159 { 22160 popHostContext(workInProgress); 22161 var rootContainerInstance = getRootHostContainer(); 22162 var type = workInProgress.type; 22163 22164 if (current !== null && workInProgress.stateNode != null) { 22165 updateHostComponent$1(current, workInProgress, type, newProps, rootContainerInstance); 22166 22167 if (current.ref !== workInProgress.ref) { 22168 markRef$1(workInProgress); 22169 } 22170 } else { 22171 if (!newProps) { 22172 if (workInProgress.stateNode === null) { 22173 throw new Error('We must have new props for new mounts. This error is likely ' + 'caused by a bug in React. Please file an issue.'); 22174 } // This can happen when we abort work. 22175 22176 22177 bubbleProperties(workInProgress); 22178 return null; 22179 } 22180 22181 var currentHostContext = getHostContext(); // TODO: Move createInstance to beginWork and keep it on a context 22182 // "stack" as the parent. Then append children as we go in beginWork 22183 // or completeWork depending on whether we want to add them top->down or 22184 // bottom->up. Top->down is faster in IE11. 22185 22186 var _wasHydrated = popHydrationState(workInProgress); 22187 22188 if (_wasHydrated) { 22189 // TODO: Move this and createInstance step into the beginPhase 22190 // to consolidate. 22191 if (prepareToHydrateHostInstance(workInProgress, rootContainerInstance, currentHostContext)) { 22192 // If changes to the hydrated node need to be applied at the 22193 // commit-phase we mark this as such. 22194 markUpdate(workInProgress); 22195 } 22196 } else { 22197 var instance = createInstance(type, newProps, rootContainerInstance, currentHostContext, workInProgress); 22198 appendAllChildren(instance, workInProgress, false, false); 22199 workInProgress.stateNode = instance; // Certain renderers require commit-time effects for initial mount. 22200 // (eg DOM renderer supports auto-focus for certain elements). 22201 // Make sure such renderers get scheduled for later work. 22202 22203 if (finalizeInitialChildren(instance, type, newProps, rootContainerInstance)) { 22204 markUpdate(workInProgress); 22205 } 22206 } 22207 22208 if (workInProgress.ref !== null) { 22209 // If there is a ref on a host node we need to schedule a callback 22210 markRef$1(workInProgress); 22211 } 22212 } 22213 22214 bubbleProperties(workInProgress); 22215 return null; 22216 } 22217 22218 case HostText: 22219 { 22220 var newText = newProps; 22221 22222 if (current && workInProgress.stateNode != null) { 22223 var oldText = current.memoizedProps; // If we have an alternate, that means this is an update and we need 22224 // to schedule a side-effect to do the updates. 22225 22226 updateHostText$1(current, workInProgress, oldText, newText); 22227 } else { 22228 if (typeof newText !== 'string') { 22229 if (workInProgress.stateNode === null) { 22230 throw new Error('We must have new props for new mounts. This error is likely ' + 'caused by a bug in React. Please file an issue.'); 22231 } // This can happen when we abort work. 22232 22233 } 22234 22235 var _rootContainerInstance = getRootHostContainer(); 22236 22237 var _currentHostContext = getHostContext(); 22238 22239 var _wasHydrated2 = popHydrationState(workInProgress); 22240 22241 if (_wasHydrated2) { 22242 if (prepareToHydrateHostTextInstance(workInProgress)) { 22243 markUpdate(workInProgress); 22244 } 22245 } else { 22246 workInProgress.stateNode = createTextInstance(newText, _rootContainerInstance, _currentHostContext, workInProgress); 22247 } 22248 } 22249 22250 bubbleProperties(workInProgress); 22251 return null; 22252 } 22253 22254 case SuspenseComponent: 22255 { 22256 popSuspenseContext(workInProgress); 22257 var nextState = workInProgress.memoizedState; // Special path for dehydrated boundaries. We may eventually move this 22258 // to its own fiber type so that we can add other kinds of hydration 22259 // boundaries that aren't associated with a Suspense tree. In anticipation 22260 // of such a refactor, all the hydration logic is contained in 22261 // this branch. 22262 22263 if (current === null || current.memoizedState !== null && current.memoizedState.dehydrated !== null) { 22264 var fallthroughToNormalSuspensePath = completeDehydratedSuspenseBoundary(current, workInProgress, nextState); 22265 22266 if (!fallthroughToNormalSuspensePath) { 22267 if (workInProgress.flags & ShouldCapture) { 22268 // Special case. There were remaining unhydrated nodes. We treat 22269 // this as a mismatch. Revert to client rendering. 22270 return workInProgress; 22271 } else { 22272 // Did not finish hydrating, either because this is the initial 22273 // render or because something suspended. 22274 return null; 22275 } 22276 } // Continue with the normal Suspense path. 22277 22278 } 22279 22280 if ((workInProgress.flags & DidCapture) !== NoFlags) { 22281 // Something suspended. Re-render with the fallback children. 22282 workInProgress.lanes = renderLanes; // Do not reset the effect list. 22283 22284 if ( (workInProgress.mode & ProfileMode) !== NoMode) { 22285 transferActualDuration(workInProgress); 22286 } // Don't bubble properties in this case. 22287 22288 22289 return workInProgress; 22290 } 22291 22292 var nextDidTimeout = nextState !== null; 22293 var prevDidTimeout = current !== null && current.memoizedState !== null; 22294 // a passive effect, which is when we process the transitions 22295 22296 22297 if (nextDidTimeout !== prevDidTimeout) { 22298 // an effect to toggle the subtree's visibility. When we switch from 22299 // fallback -> primary, the inner Offscreen fiber schedules this effect 22300 // as part of its normal complete phase. But when we switch from 22301 // primary -> fallback, the inner Offscreen fiber does not have a complete 22302 // phase. So we need to schedule its effect here. 22303 // 22304 // We also use this flag to connect/disconnect the effects, but the same 22305 // logic applies: when re-connecting, the Offscreen fiber's complete 22306 // phase will handle scheduling the effect. It's only when the fallback 22307 // is active that we have to do anything special. 22308 22309 22310 if (nextDidTimeout) { 22311 var _offscreenFiber2 = workInProgress.child; 22312 _offscreenFiber2.flags |= Visibility; // TODO: This will still suspend a synchronous tree if anything 22313 // in the concurrent tree already suspended during this render. 22314 // This is a known bug. 22315 22316 if ((workInProgress.mode & ConcurrentMode) !== NoMode) { 22317 // TODO: Move this back to throwException because this is too late 22318 // if this is a large tree which is common for initial loads. We 22319 // don't know if we should restart a render or not until we get 22320 // this marker, and this is too late. 22321 // If this render already had a ping or lower pri updates, 22322 // and this is the first time we know we're going to suspend we 22323 // should be able to immediately restart from within throwException. 22324 var hasInvisibleChildContext = current === null && (workInProgress.memoizedProps.unstable_avoidThisFallback !== true || !enableSuspenseAvoidThisFallback); 22325 22326 if (hasInvisibleChildContext || hasSuspenseContext(suspenseStackCursor.current, InvisibleParentSuspenseContext)) { 22327 // If this was in an invisible tree or a new render, then showing 22328 // this boundary is ok. 22329 renderDidSuspend(); 22330 } else { 22331 // Otherwise, we're going to have to hide content so we should 22332 // suspend for longer if possible. 22333 renderDidSuspendDelayIfPossible(); 22334 } 22335 } 22336 } 22337 } 22338 22339 var wakeables = workInProgress.updateQueue; 22340 22341 if (wakeables !== null) { 22342 // Schedule an effect to attach a retry listener to the promise. 22343 // TODO: Move to passive phase 22344 workInProgress.flags |= Update; 22345 } 22346 22347 bubbleProperties(workInProgress); 22348 22349 { 22350 if ((workInProgress.mode & ProfileMode) !== NoMode) { 22351 if (nextDidTimeout) { 22352 // Don't count time spent in a timed out Suspense subtree as part of the base duration. 22353 var primaryChildFragment = workInProgress.child; 22354 22355 if (primaryChildFragment !== null) { 22356 // $FlowFixMe Flow doesn't support type casting in combination with the -= operator 22357 workInProgress.treeBaseDuration -= primaryChildFragment.treeBaseDuration; 22358 } 22359 } 22360 } 22361 } 22362 22363 return null; 22364 } 22365 22366 case HostPortal: 22367 popHostContainer(workInProgress); 22368 updateHostContainer(current, workInProgress); 22369 22370 if (current === null) { 22371 preparePortalMount(workInProgress.stateNode.containerInfo); 22372 } 22373 22374 bubbleProperties(workInProgress); 22375 return null; 22376 22377 case ContextProvider: 22378 // Pop provider fiber 22379 var context = workInProgress.type._context; 22380 popProvider(context, workInProgress); 22381 bubbleProperties(workInProgress); 22382 return null; 22383 22384 case IncompleteClassComponent: 22385 { 22386 // Same as class component case. I put it down here so that the tags are 22387 // sequential to ensure this switch is compiled to a jump table. 22388 var _Component = workInProgress.type; 22389 22390 if (isContextProvider(_Component)) { 22391 popContext(workInProgress); 22392 } 22393 22394 bubbleProperties(workInProgress); 22395 return null; 22396 } 22397 22398 case SuspenseListComponent: 22399 { 22400 popSuspenseContext(workInProgress); 22401 var renderState = workInProgress.memoizedState; 22402 22403 if (renderState === null) { 22404 // We're running in the default, "independent" mode. 22405 // We don't do anything in this mode. 22406 bubbleProperties(workInProgress); 22407 return null; 22408 } 22409 22410 var didSuspendAlready = (workInProgress.flags & DidCapture) !== NoFlags; 22411 var renderedTail = renderState.rendering; 22412 22413 if (renderedTail === null) { 22414 // We just rendered the head. 22415 if (!didSuspendAlready) { 22416 // This is the first pass. We need to figure out if anything is still 22417 // suspended in the rendered set. 22418 // If new content unsuspended, but there's still some content that 22419 // didn't. Then we need to do a second pass that forces everything 22420 // to keep showing their fallbacks. 22421 // We might be suspended if something in this render pass suspended, or 22422 // something in the previous committed pass suspended. Otherwise, 22423 // there's no chance so we can skip the expensive call to 22424 // findFirstSuspended. 22425 var cannotBeSuspended = renderHasNotSuspendedYet() && (current === null || (current.flags & DidCapture) === NoFlags); 22426 22427 if (!cannotBeSuspended) { 22428 var row = workInProgress.child; 22429 22430 while (row !== null) { 22431 var suspended = findFirstSuspended(row); 22432 22433 if (suspended !== null) { 22434 didSuspendAlready = true; 22435 workInProgress.flags |= DidCapture; 22436 cutOffTailIfNeeded(renderState, false); // If this is a newly suspended tree, it might not get committed as 22437 // part of the second pass. In that case nothing will subscribe to 22438 // its thenables. Instead, we'll transfer its thenables to the 22439 // SuspenseList so that it can retry if they resolve. 22440 // There might be multiple of these in the list but since we're 22441 // going to wait for all of them anyway, it doesn't really matter 22442 // which ones gets to ping. In theory we could get clever and keep 22443 // track of how many dependencies remain but it gets tricky because 22444 // in the meantime, we can add/remove/change items and dependencies. 22445 // We might bail out of the loop before finding any but that 22446 // doesn't matter since that means that the other boundaries that 22447 // we did find already has their listeners attached. 22448 22449 var newThenables = suspended.updateQueue; 22450 22451 if (newThenables !== null) { 22452 workInProgress.updateQueue = newThenables; 22453 workInProgress.flags |= Update; 22454 } // Rerender the whole list, but this time, we'll force fallbacks 22455 // to stay in place. 22456 // Reset the effect flags before doing the second pass since that's now invalid. 22457 // Reset the child fibers to their original state. 22458 22459 22460 workInProgress.subtreeFlags = NoFlags; 22461 resetChildFibers(workInProgress, renderLanes); // Set up the Suspense Context to force suspense and immediately 22462 // rerender the children. 22463 22464 pushSuspenseContext(workInProgress, setShallowSuspenseContext(suspenseStackCursor.current, ForceSuspenseFallback)); // Don't bubble properties in this case. 22465 22466 return workInProgress.child; 22467 } 22468 22469 row = row.sibling; 22470 } 22471 } 22472 22473 if (renderState.tail !== null && now() > getRenderTargetTime()) { 22474 // We have already passed our CPU deadline but we still have rows 22475 // left in the tail. We'll just give up further attempts to render 22476 // the main content and only render fallbacks. 22477 workInProgress.flags |= DidCapture; 22478 didSuspendAlready = true; 22479 cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this 22480 // to get it started back up to attempt the next item. While in terms 22481 // of priority this work has the same priority as this current render, 22482 // it's not part of the same transition once the transition has 22483 // committed. If it's sync, we still want to yield so that it can be 22484 // painted. Conceptually, this is really the same as pinging. 22485 // We can use any RetryLane even if it's the one currently rendering 22486 // since we're leaving it behind on this node. 22487 22488 workInProgress.lanes = SomeRetryLane; 22489 } 22490 } else { 22491 cutOffTailIfNeeded(renderState, false); 22492 } // Next we're going to render the tail. 22493 22494 } else { 22495 // Append the rendered row to the child list. 22496 if (!didSuspendAlready) { 22497 var _suspended = findFirstSuspended(renderedTail); 22498 22499 if (_suspended !== null) { 22500 workInProgress.flags |= DidCapture; 22501 didSuspendAlready = true; // Ensure we transfer the update queue to the parent so that it doesn't 22502 // get lost if this row ends up dropped during a second pass. 22503 22504 var _newThenables = _suspended.updateQueue; 22505 22506 if (_newThenables !== null) { 22507 workInProgress.updateQueue = _newThenables; 22508 workInProgress.flags |= Update; 22509 } 22510 22511 cutOffTailIfNeeded(renderState, true); // This might have been modified. 22512 22513 if (renderState.tail === null && renderState.tailMode === 'hidden' && !renderedTail.alternate && !getIsHydrating() // We don't cut it if we're hydrating. 22514 ) { 22515 // We're done. 22516 bubbleProperties(workInProgress); 22517 return null; 22518 } 22519 } else if ( // The time it took to render last row is greater than the remaining 22520 // time we have to render. So rendering one more row would likely 22521 // exceed it. 22522 now() * 2 - renderState.renderingStartTime > getRenderTargetTime() && renderLanes !== OffscreenLane) { 22523 // We have now passed our CPU deadline and we'll just give up further 22524 // attempts to render the main content and only render fallbacks. 22525 // The assumption is that this is usually faster. 22526 workInProgress.flags |= DidCapture; 22527 didSuspendAlready = true; 22528 cutOffTailIfNeeded(renderState, false); // Since nothing actually suspended, there will nothing to ping this 22529 // to get it started back up to attempt the next item. While in terms 22530 // of priority this work has the same priority as this current render, 22531 // it's not part of the same transition once the transition has 22532 // committed. If it's sync, we still want to yield so that it can be 22533 // painted. Conceptually, this is really the same as pinging. 22534 // We can use any RetryLane even if it's the one currently rendering 22535 // since we're leaving it behind on this node. 22536 22537 workInProgress.lanes = SomeRetryLane; 22538 } 22539 } 22540 22541 if (renderState.isBackwards) { 22542 // The effect list of the backwards tail will have been added 22543 // to the end. This breaks the guarantee that life-cycles fire in 22544 // sibling order but that isn't a strong guarantee promised by React. 22545 // Especially since these might also just pop in during future commits. 22546 // Append to the beginning of the list. 22547 renderedTail.sibling = workInProgress.child; 22548 workInProgress.child = renderedTail; 22549 } else { 22550 var previousSibling = renderState.last; 22551 22552 if (previousSibling !== null) { 22553 previousSibling.sibling = renderedTail; 22554 } else { 22555 workInProgress.child = renderedTail; 22556 } 22557 22558 renderState.last = renderedTail; 22559 } 22560 } 22561 22562 if (renderState.tail !== null) { 22563 // We still have tail rows to render. 22564 // Pop a row. 22565 var next = renderState.tail; 22566 renderState.rendering = next; 22567 renderState.tail = next.sibling; 22568 renderState.renderingStartTime = now(); 22569 next.sibling = null; // Restore the context. 22570 // TODO: We can probably just avoid popping it instead and only 22571 // setting it the first time we go from not suspended to suspended. 22572 22573 var suspenseContext = suspenseStackCursor.current; 22574 22575 if (didSuspendAlready) { 22576 suspenseContext = setShallowSuspenseContext(suspenseContext, ForceSuspenseFallback); 22577 } else { 22578 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext); 22579 } 22580 22581 pushSuspenseContext(workInProgress, suspenseContext); // Do a pass over the next row. 22582 // Don't bubble properties in this case. 22583 22584 return next; 22585 } 22586 22587 bubbleProperties(workInProgress); 22588 return null; 22589 } 22590 22591 case ScopeComponent: 22592 { 22593 22594 break; 22595 } 22596 22597 case OffscreenComponent: 22598 case LegacyHiddenComponent: 22599 { 22600 popRenderLanes(workInProgress); 22601 var _nextState = workInProgress.memoizedState; 22602 var nextIsHidden = _nextState !== null; 22603 22604 if (current !== null) { 22605 var _prevState = current.memoizedState; 22606 var prevIsHidden = _prevState !== null; 22607 22608 if (prevIsHidden !== nextIsHidden && ( // LegacyHidden doesn't do any hiding — it only pre-renders. 22609 !enableLegacyHidden )) { 22610 workInProgress.flags |= Visibility; 22611 } 22612 } 22613 22614 if (!nextIsHidden || (workInProgress.mode & ConcurrentMode) === NoMode) { 22615 bubbleProperties(workInProgress); 22616 } else { 22617 // Don't bubble properties for hidden children unless we're rendering 22618 // at offscreen priority. 22619 if (includesSomeLane(subtreeRenderLanes, OffscreenLane)) { 22620 bubbleProperties(workInProgress); 22621 22622 { 22623 // Check if there was an insertion or update in the hidden subtree. 22624 // If so, we need to hide those nodes in the commit phase, so 22625 // schedule a visibility effect. 22626 if ( workInProgress.subtreeFlags & (Placement | Update)) { 22627 workInProgress.flags |= Visibility; 22628 } 22629 } 22630 } 22631 } 22632 return null; 22633 } 22634 22635 case CacheComponent: 22636 { 22637 22638 return null; 22639 } 22640 22641 case TracingMarkerComponent: 22642 { 22643 22644 return null; 22645 } 22646 } 22647 22648 throw new Error("Unknown unit of work tag (" + workInProgress.tag + "). This error is likely caused by a bug in " + 'React. Please file an issue.'); 22649 } 22650 22651 function unwindWork(current, workInProgress, renderLanes) { 22652 // Note: This intentionally doesn't check if we're hydrating because comparing 22653 // to the current tree provider fiber is just as fast and less error-prone. 22654 // Ideally we would have a special version of the work loop only 22655 // for hydration. 22656 popTreeContext(workInProgress); 22657 22658 switch (workInProgress.tag) { 22659 case ClassComponent: 22660 { 22661 var Component = workInProgress.type; 22662 22663 if (isContextProvider(Component)) { 22664 popContext(workInProgress); 22665 } 22666 22667 var flags = workInProgress.flags; 22668 22669 if (flags & ShouldCapture) { 22670 workInProgress.flags = flags & ~ShouldCapture | DidCapture; 22671 22672 if ( (workInProgress.mode & ProfileMode) !== NoMode) { 22673 transferActualDuration(workInProgress); 22674 } 22675 22676 return workInProgress; 22677 } 22678 22679 return null; 22680 } 22681 22682 case HostRoot: 22683 { 22684 var root = workInProgress.stateNode; 22685 popHostContainer(workInProgress); 22686 popTopLevelContextObject(workInProgress); 22687 resetWorkInProgressVersions(); 22688 var _flags = workInProgress.flags; 22689 22690 if ((_flags & ShouldCapture) !== NoFlags && (_flags & DidCapture) === NoFlags) { 22691 // There was an error during render that wasn't captured by a suspense 22692 // boundary. Do a second pass on the root to unmount the children. 22693 workInProgress.flags = _flags & ~ShouldCapture | DidCapture; 22694 return workInProgress; 22695 } // We unwound to the root without completing it. Exit. 22696 22697 22698 return null; 22699 } 22700 22701 case HostComponent: 22702 { 22703 // TODO: popHydrationState 22704 popHostContext(workInProgress); 22705 return null; 22706 } 22707 22708 case SuspenseComponent: 22709 { 22710 popSuspenseContext(workInProgress); 22711 var suspenseState = workInProgress.memoizedState; 22712 22713 if (suspenseState !== null && suspenseState.dehydrated !== null) { 22714 if (workInProgress.alternate === null) { 22715 throw new Error('Threw in newly mounted dehydrated component. This is likely a bug in ' + 'React. Please file an issue.'); 22716 } 22717 22718 resetHydrationState(); 22719 } 22720 22721 var _flags2 = workInProgress.flags; 22722 22723 if (_flags2 & ShouldCapture) { 22724 workInProgress.flags = _flags2 & ~ShouldCapture | DidCapture; // Captured a suspense effect. Re-render the boundary. 22725 22726 if ( (workInProgress.mode & ProfileMode) !== NoMode) { 22727 transferActualDuration(workInProgress); 22728 } 22729 22730 return workInProgress; 22731 } 22732 22733 return null; 22734 } 22735 22736 case SuspenseListComponent: 22737 { 22738 popSuspenseContext(workInProgress); // SuspenseList doesn't actually catch anything. It should've been 22739 // caught by a nested boundary. If not, it should bubble through. 22740 22741 return null; 22742 } 22743 22744 case HostPortal: 22745 popHostContainer(workInProgress); 22746 return null; 22747 22748 case ContextProvider: 22749 var context = workInProgress.type._context; 22750 popProvider(context, workInProgress); 22751 return null; 22752 22753 case OffscreenComponent: 22754 case LegacyHiddenComponent: 22755 popRenderLanes(workInProgress); 22756 return null; 22757 22758 case CacheComponent: 22759 22760 return null; 22761 22762 default: 22763 return null; 22764 } 22765 } 22766 22767 function unwindInterruptedWork(current, interruptedWork, renderLanes) { 22768 // Note: This intentionally doesn't check if we're hydrating because comparing 22769 // to the current tree provider fiber is just as fast and less error-prone. 22770 // Ideally we would have a special version of the work loop only 22771 // for hydration. 22772 popTreeContext(interruptedWork); 22773 22774 switch (interruptedWork.tag) { 22775 case ClassComponent: 22776 { 22777 var childContextTypes = interruptedWork.type.childContextTypes; 22778 22779 if (childContextTypes !== null && childContextTypes !== undefined) { 22780 popContext(interruptedWork); 22781 } 22782 22783 break; 22784 } 22785 22786 case HostRoot: 22787 { 22788 var root = interruptedWork.stateNode; 22789 popHostContainer(interruptedWork); 22790 popTopLevelContextObject(interruptedWork); 22791 resetWorkInProgressVersions(); 22792 break; 22793 } 22794 22795 case HostComponent: 22796 { 22797 popHostContext(interruptedWork); 22798 break; 22799 } 22800 22801 case HostPortal: 22802 popHostContainer(interruptedWork); 22803 break; 22804 22805 case SuspenseComponent: 22806 popSuspenseContext(interruptedWork); 22807 break; 22808 22809 case SuspenseListComponent: 22810 popSuspenseContext(interruptedWork); 22811 break; 22812 22813 case ContextProvider: 22814 var context = interruptedWork.type._context; 22815 popProvider(context, interruptedWork); 22816 break; 22817 22818 case OffscreenComponent: 22819 case LegacyHiddenComponent: 22820 popRenderLanes(interruptedWork); 22821 break; 22822 } 22823 } 22824 22825 var didWarnAboutUndefinedSnapshotBeforeUpdate = null; 22826 22827 { 22828 didWarnAboutUndefinedSnapshotBeforeUpdate = new Set(); 22829 } // Used during the commit phase to track the state of the Offscreen component stack. 22830 // Allows us to avoid traversing the return path to find the nearest Offscreen ancestor. 22831 // Only used when enableSuspenseLayoutEffectSemantics is enabled. 22832 22833 22834 var offscreenSubtreeIsHidden = false; 22835 var offscreenSubtreeWasHidden = false; 22836 var PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set; 22837 var nextEffect = null; // Used for Profiling builds to track updaters. 22838 22839 var inProgressLanes = null; 22840 var inProgressRoot = null; 22841 function reportUncaughtErrorInDEV(error) { 22842 // Wrapping each small part of the commit phase into a guarded 22843 // callback is a bit too slow (https://github.com/facebook/react/pull/21666). 22844 // But we rely on it to surface errors to DEV tools like overlays 22845 // (https://github.com/facebook/react/issues/21712). 22846 // As a compromise, rethrow only caught errors in a guard. 22847 { 22848 invokeGuardedCallback(null, function () { 22849 throw error; 22850 }); 22851 clearCaughtError(); 22852 } 22853 } 22854 22855 var callComponentWillUnmountWithTimer = function (current, instance) { 22856 instance.props = current.memoizedProps; 22857 instance.state = current.memoizedState; 22858 22859 if ( current.mode & ProfileMode) { 22860 try { 22861 startLayoutEffectTimer(); 22862 instance.componentWillUnmount(); 22863 } finally { 22864 recordLayoutEffectDuration(current); 22865 } 22866 } else { 22867 instance.componentWillUnmount(); 22868 } 22869 }; // Capture errors so they don't interrupt mounting. 22870 22871 22872 function safelyCallCommitHookLayoutEffectListMount(current, nearestMountedAncestor) { 22873 try { 22874 commitHookEffectListMount(Layout, current); 22875 } catch (error) { 22876 captureCommitPhaseError(current, nearestMountedAncestor, error); 22877 } 22878 } // Capture errors so they don't interrupt unmounting. 22879 22880 22881 function safelyCallComponentWillUnmount(current, nearestMountedAncestor, instance) { 22882 try { 22883 callComponentWillUnmountWithTimer(current, instance); 22884 } catch (error) { 22885 captureCommitPhaseError(current, nearestMountedAncestor, error); 22886 } 22887 } // Capture errors so they don't interrupt mounting. 22888 22889 22890 function safelyCallComponentDidMount(current, nearestMountedAncestor, instance) { 22891 try { 22892 instance.componentDidMount(); 22893 } catch (error) { 22894 captureCommitPhaseError(current, nearestMountedAncestor, error); 22895 } 22896 } // Capture errors so they don't interrupt mounting. 22897 22898 22899 function safelyAttachRef(current, nearestMountedAncestor) { 22900 try { 22901 commitAttachRef(current); 22902 } catch (error) { 22903 captureCommitPhaseError(current, nearestMountedAncestor, error); 22904 } 22905 } 22906 22907 function safelyDetachRef(current, nearestMountedAncestor) { 22908 var ref = current.ref; 22909 22910 if (ref !== null) { 22911 if (typeof ref === 'function') { 22912 var retVal; 22913 22914 try { 22915 if (enableProfilerTimer && enableProfilerCommitHooks && current.mode & ProfileMode) { 22916 try { 22917 startLayoutEffectTimer(); 22918 retVal = ref(null); 22919 } finally { 22920 recordLayoutEffectDuration(current); 22921 } 22922 } else { 22923 retVal = ref(null); 22924 } 22925 } catch (error) { 22926 captureCommitPhaseError(current, nearestMountedAncestor, error); 22927 } 22928 22929 { 22930 if (typeof retVal === 'function') { 22931 error('Unexpected return value from a callback ref in %s. ' + 'A callback ref should not return a function.', getComponentNameFromFiber(current)); 22932 } 22933 } 22934 } else { 22935 ref.current = null; 22936 } 22937 } 22938 } 22939 22940 function safelyCallDestroy(current, nearestMountedAncestor, destroy) { 22941 try { 22942 destroy(); 22943 } catch (error) { 22944 captureCommitPhaseError(current, nearestMountedAncestor, error); 22945 } 22946 } 22947 22948 var focusedInstanceHandle = null; 22949 var shouldFireAfterActiveInstanceBlur = false; 22950 function commitBeforeMutationEffects(root, firstChild) { 22951 focusedInstanceHandle = prepareForCommit(root.containerInfo); 22952 nextEffect = firstChild; 22953 commitBeforeMutationEffects_begin(); // We no longer need to track the active instance fiber 22954 22955 var shouldFire = shouldFireAfterActiveInstanceBlur; 22956 shouldFireAfterActiveInstanceBlur = false; 22957 focusedInstanceHandle = null; 22958 return shouldFire; 22959 } 22960 22961 function commitBeforeMutationEffects_begin() { 22962 while (nextEffect !== null) { 22963 var fiber = nextEffect; // This phase is only used for beforeActiveInstanceBlur. 22964 22965 var child = fiber.child; 22966 22967 if ((fiber.subtreeFlags & BeforeMutationMask) !== NoFlags && child !== null) { 22968 child.return = fiber; 22969 nextEffect = child; 22970 } else { 22971 commitBeforeMutationEffects_complete(); 22972 } 22973 } 22974 } 22975 22976 function commitBeforeMutationEffects_complete() { 22977 while (nextEffect !== null) { 22978 var fiber = nextEffect; 22979 setCurrentFiber(fiber); 22980 22981 try { 22982 commitBeforeMutationEffectsOnFiber(fiber); 22983 } catch (error) { 22984 captureCommitPhaseError(fiber, fiber.return, error); 22985 } 22986 22987 resetCurrentFiber(); 22988 var sibling = fiber.sibling; 22989 22990 if (sibling !== null) { 22991 sibling.return = fiber.return; 22992 nextEffect = sibling; 22993 return; 22994 } 22995 22996 nextEffect = fiber.return; 22997 } 22998 } 22999 23000 function commitBeforeMutationEffectsOnFiber(finishedWork) { 23001 var current = finishedWork.alternate; 23002 var flags = finishedWork.flags; 23003 23004 if ((flags & Snapshot) !== NoFlags) { 23005 setCurrentFiber(finishedWork); 23006 23007 switch (finishedWork.tag) { 23008 case FunctionComponent: 23009 case ForwardRef: 23010 case SimpleMemoComponent: 23011 { 23012 break; 23013 } 23014 23015 case ClassComponent: 23016 { 23017 if (current !== null) { 23018 var prevProps = current.memoizedProps; 23019 var prevState = current.memoizedState; 23020 var instance = finishedWork.stateNode; // We could update instance props and state here, 23021 // but instead we rely on them being set during last render. 23022 // TODO: revisit this when we implement resuming. 23023 23024 { 23025 if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) { 23026 if (instance.props !== finishedWork.memoizedProps) { 23027 error('Expected %s props to match memoized props before ' + 'getSnapshotBeforeUpdate. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.props`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance'); 23028 } 23029 23030 if (instance.state !== finishedWork.memoizedState) { 23031 error('Expected %s state to match memoized state before ' + 'getSnapshotBeforeUpdate. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.state`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance'); 23032 } 23033 } 23034 } 23035 23036 var snapshot = instance.getSnapshotBeforeUpdate(finishedWork.elementType === finishedWork.type ? prevProps : resolveDefaultProps(finishedWork.type, prevProps), prevState); 23037 23038 { 23039 var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate; 23040 23041 if (snapshot === undefined && !didWarnSet.has(finishedWork.type)) { 23042 didWarnSet.add(finishedWork.type); 23043 23044 error('%s.getSnapshotBeforeUpdate(): A snapshot value (or null) ' + 'must be returned. You have returned undefined.', getComponentNameFromFiber(finishedWork)); 23045 } 23046 } 23047 23048 instance.__reactInternalSnapshotBeforeUpdate = snapshot; 23049 } 23050 23051 break; 23052 } 23053 23054 case HostRoot: 23055 { 23056 { 23057 var root = finishedWork.stateNode; 23058 clearContainer(root.containerInfo); 23059 } 23060 23061 break; 23062 } 23063 23064 case HostComponent: 23065 case HostText: 23066 case HostPortal: 23067 case IncompleteClassComponent: 23068 // Nothing to do for these component types 23069 break; 23070 23071 default: 23072 { 23073 throw new Error('This unit of work tag should not have side-effects. This error is ' + 'likely caused by a bug in React. Please file an issue.'); 23074 } 23075 } 23076 23077 resetCurrentFiber(); 23078 } 23079 } 23080 23081 function commitHookEffectListUnmount(flags, finishedWork, nearestMountedAncestor) { 23082 var updateQueue = finishedWork.updateQueue; 23083 var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; 23084 23085 if (lastEffect !== null) { 23086 var firstEffect = lastEffect.next; 23087 var effect = firstEffect; 23088 23089 do { 23090 if ((effect.tag & flags) === flags) { 23091 // Unmount 23092 var destroy = effect.destroy; 23093 effect.destroy = undefined; 23094 23095 if (destroy !== undefined) { 23096 { 23097 if ((flags & Passive$1) !== NoFlags$1) { 23098 markComponentPassiveEffectUnmountStarted(finishedWork); 23099 } else if ((flags & Layout) !== NoFlags$1) { 23100 markComponentLayoutEffectUnmountStarted(finishedWork); 23101 } 23102 } 23103 23104 { 23105 if ((flags & Insertion) !== NoFlags$1) { 23106 setIsRunningInsertionEffect(true); 23107 } 23108 } 23109 23110 safelyCallDestroy(finishedWork, nearestMountedAncestor, destroy); 23111 23112 { 23113 if ((flags & Insertion) !== NoFlags$1) { 23114 setIsRunningInsertionEffect(false); 23115 } 23116 } 23117 23118 { 23119 if ((flags & Passive$1) !== NoFlags$1) { 23120 markComponentPassiveEffectUnmountStopped(); 23121 } else if ((flags & Layout) !== NoFlags$1) { 23122 markComponentLayoutEffectUnmountStopped(); 23123 } 23124 } 23125 } 23126 } 23127 23128 effect = effect.next; 23129 } while (effect !== firstEffect); 23130 } 23131 } 23132 23133 function commitHookEffectListMount(flags, finishedWork) { 23134 var updateQueue = finishedWork.updateQueue; 23135 var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; 23136 23137 if (lastEffect !== null) { 23138 var firstEffect = lastEffect.next; 23139 var effect = firstEffect; 23140 23141 do { 23142 if ((effect.tag & flags) === flags) { 23143 { 23144 if ((flags & Passive$1) !== NoFlags$1) { 23145 markComponentPassiveEffectMountStarted(finishedWork); 23146 } else if ((flags & Layout) !== NoFlags$1) { 23147 markComponentLayoutEffectMountStarted(finishedWork); 23148 } 23149 } // Mount 23150 23151 23152 var create = effect.create; 23153 23154 { 23155 if ((flags & Insertion) !== NoFlags$1) { 23156 setIsRunningInsertionEffect(true); 23157 } 23158 } 23159 23160 effect.destroy = create(); 23161 23162 { 23163 if ((flags & Insertion) !== NoFlags$1) { 23164 setIsRunningInsertionEffect(false); 23165 } 23166 } 23167 23168 { 23169 if ((flags & Passive$1) !== NoFlags$1) { 23170 markComponentPassiveEffectMountStopped(); 23171 } else if ((flags & Layout) !== NoFlags$1) { 23172 markComponentLayoutEffectMountStopped(); 23173 } 23174 } 23175 23176 { 23177 var destroy = effect.destroy; 23178 23179 if (destroy !== undefined && typeof destroy !== 'function') { 23180 var hookName = void 0; 23181 23182 if ((effect.tag & Layout) !== NoFlags) { 23183 hookName = 'useLayoutEffect'; 23184 } else if ((effect.tag & Insertion) !== NoFlags) { 23185 hookName = 'useInsertionEffect'; 23186 } else { 23187 hookName = 'useEffect'; 23188 } 23189 23190 var addendum = void 0; 23191 23192 if (destroy === null) { 23193 addendum = ' You returned null. If your effect does not require clean ' + 'up, return undefined (or nothing).'; 23194 } else if (typeof destroy.then === 'function') { 23195 addendum = '\n\nIt looks like you wrote ' + hookName + '(async () => ...) or returned a Promise. ' + 'Instead, write the async function inside your effect ' + 'and call it immediately:\n\n' + hookName + '(() => {\n' + ' async function fetchData() {\n' + ' // You can await here\n' + ' const response = await MyAPI.getData(someId);\n' + ' // ...\n' + ' }\n' + ' fetchData();\n' + "}, [someId]); // Or [] if effect doesn't need props or state\n\n" + 'Learn more about data fetching with Hooks: https://reactjs.org/link/hooks-data-fetching'; 23196 } else { 23197 addendum = ' You returned: ' + destroy; 23198 } 23199 23200 error('%s must not return anything besides a function, ' + 'which is used for clean-up.%s', hookName, addendum); 23201 } 23202 } 23203 } 23204 23205 effect = effect.next; 23206 } while (effect !== firstEffect); 23207 } 23208 } 23209 23210 function commitPassiveEffectDurations(finishedRoot, finishedWork) { 23211 { 23212 // Only Profilers with work in their subtree will have an Update effect scheduled. 23213 if ((finishedWork.flags & Update) !== NoFlags) { 23214 switch (finishedWork.tag) { 23215 case Profiler: 23216 { 23217 var passiveEffectDuration = finishedWork.stateNode.passiveEffectDuration; 23218 var _finishedWork$memoize = finishedWork.memoizedProps, 23219 id = _finishedWork$memoize.id, 23220 onPostCommit = _finishedWork$memoize.onPostCommit; // This value will still reflect the previous commit phase. 23221 // It does not get reset until the start of the next commit phase. 23222 23223 var commitTime = getCommitTime(); 23224 var phase = finishedWork.alternate === null ? 'mount' : 'update'; 23225 23226 { 23227 if (isCurrentUpdateNested()) { 23228 phase = 'nested-update'; 23229 } 23230 } 23231 23232 if (typeof onPostCommit === 'function') { 23233 onPostCommit(id, phase, passiveEffectDuration, commitTime); 23234 } // Bubble times to the next nearest ancestor Profiler. 23235 // After we process that Profiler, we'll bubble further up. 23236 23237 23238 var parentFiber = finishedWork.return; 23239 23240 outer: while (parentFiber !== null) { 23241 switch (parentFiber.tag) { 23242 case HostRoot: 23243 var root = parentFiber.stateNode; 23244 root.passiveEffectDuration += passiveEffectDuration; 23245 break outer; 23246 23247 case Profiler: 23248 var parentStateNode = parentFiber.stateNode; 23249 parentStateNode.passiveEffectDuration += passiveEffectDuration; 23250 break outer; 23251 } 23252 23253 parentFiber = parentFiber.return; 23254 } 23255 23256 break; 23257 } 23258 } 23259 } 23260 } 23261 } 23262 23263 function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork, committedLanes) { 23264 if ((finishedWork.flags & LayoutMask) !== NoFlags) { 23265 switch (finishedWork.tag) { 23266 case FunctionComponent: 23267 case ForwardRef: 23268 case SimpleMemoComponent: 23269 { 23270 if ( !offscreenSubtreeWasHidden) { 23271 // At this point layout effects have already been destroyed (during mutation phase). 23272 // This is done to prevent sibling component effects from interfering with each other, 23273 // e.g. a destroy function in one component should never override a ref set 23274 // by a create function in another component during the same commit. 23275 if ( finishedWork.mode & ProfileMode) { 23276 try { 23277 startLayoutEffectTimer(); 23278 commitHookEffectListMount(Layout | HasEffect, finishedWork); 23279 } finally { 23280 recordLayoutEffectDuration(finishedWork); 23281 } 23282 } else { 23283 commitHookEffectListMount(Layout | HasEffect, finishedWork); 23284 } 23285 } 23286 23287 break; 23288 } 23289 23290 case ClassComponent: 23291 { 23292 var instance = finishedWork.stateNode; 23293 23294 if (finishedWork.flags & Update) { 23295 if (!offscreenSubtreeWasHidden) { 23296 if (current === null) { 23297 // We could update instance props and state here, 23298 // but instead we rely on them being set during last render. 23299 // TODO: revisit this when we implement resuming. 23300 { 23301 if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) { 23302 if (instance.props !== finishedWork.memoizedProps) { 23303 error('Expected %s props to match memoized props before ' + 'componentDidMount. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.props`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance'); 23304 } 23305 23306 if (instance.state !== finishedWork.memoizedState) { 23307 error('Expected %s state to match memoized state before ' + 'componentDidMount. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.state`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance'); 23308 } 23309 } 23310 } 23311 23312 if ( finishedWork.mode & ProfileMode) { 23313 try { 23314 startLayoutEffectTimer(); 23315 instance.componentDidMount(); 23316 } finally { 23317 recordLayoutEffectDuration(finishedWork); 23318 } 23319 } else { 23320 instance.componentDidMount(); 23321 } 23322 } else { 23323 var prevProps = finishedWork.elementType === finishedWork.type ? current.memoizedProps : resolveDefaultProps(finishedWork.type, current.memoizedProps); 23324 var prevState = current.memoizedState; // We could update instance props and state here, 23325 // but instead we rely on them being set during last render. 23326 // TODO: revisit this when we implement resuming. 23327 23328 { 23329 if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) { 23330 if (instance.props !== finishedWork.memoizedProps) { 23331 error('Expected %s props to match memoized props before ' + 'componentDidUpdate. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.props`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance'); 23332 } 23333 23334 if (instance.state !== finishedWork.memoizedState) { 23335 error('Expected %s state to match memoized state before ' + 'componentDidUpdate. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.state`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance'); 23336 } 23337 } 23338 } 23339 23340 if ( finishedWork.mode & ProfileMode) { 23341 try { 23342 startLayoutEffectTimer(); 23343 instance.componentDidUpdate(prevProps, prevState, instance.__reactInternalSnapshotBeforeUpdate); 23344 } finally { 23345 recordLayoutEffectDuration(finishedWork); 23346 } 23347 } else { 23348 instance.componentDidUpdate(prevProps, prevState, instance.__reactInternalSnapshotBeforeUpdate); 23349 } 23350 } 23351 } 23352 } // TODO: I think this is now always non-null by the time it reaches the 23353 // commit phase. Consider removing the type check. 23354 23355 23356 var updateQueue = finishedWork.updateQueue; 23357 23358 if (updateQueue !== null) { 23359 { 23360 if (finishedWork.type === finishedWork.elementType && !didWarnAboutReassigningProps) { 23361 if (instance.props !== finishedWork.memoizedProps) { 23362 error('Expected %s props to match memoized props before ' + 'processing the update queue. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.props`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance'); 23363 } 23364 23365 if (instance.state !== finishedWork.memoizedState) { 23366 error('Expected %s state to match memoized state before ' + 'processing the update queue. ' + 'This might either be because of a bug in React, or because ' + 'a component reassigns its own `this.state`. ' + 'Please file an issue.', getComponentNameFromFiber(finishedWork) || 'instance'); 23367 } 23368 } 23369 } // We could update instance props and state here, 23370 // but instead we rely on them being set during last render. 23371 // TODO: revisit this when we implement resuming. 23372 23373 23374 commitUpdateQueue(finishedWork, updateQueue, instance); 23375 } 23376 23377 break; 23378 } 23379 23380 case HostRoot: 23381 { 23382 // TODO: I think this is now always non-null by the time it reaches the 23383 // commit phase. Consider removing the type check. 23384 var _updateQueue = finishedWork.updateQueue; 23385 23386 if (_updateQueue !== null) { 23387 var _instance = null; 23388 23389 if (finishedWork.child !== null) { 23390 switch (finishedWork.child.tag) { 23391 case HostComponent: 23392 _instance = getPublicInstance(finishedWork.child.stateNode); 23393 break; 23394 23395 case ClassComponent: 23396 _instance = finishedWork.child.stateNode; 23397 break; 23398 } 23399 } 23400 23401 commitUpdateQueue(finishedWork, _updateQueue, _instance); 23402 } 23403 23404 break; 23405 } 23406 23407 case HostComponent: 23408 { 23409 var _instance2 = finishedWork.stateNode; // Renderers may schedule work to be done after host components are mounted 23410 // (eg DOM renderer may schedule auto-focus for inputs and form controls). 23411 // These effects should only be committed when components are first mounted, 23412 // aka when there is no current/alternate. 23413 23414 if (current === null && finishedWork.flags & Update) { 23415 var type = finishedWork.type; 23416 var props = finishedWork.memoizedProps; 23417 commitMount(_instance2, type, props); 23418 } 23419 23420 break; 23421 } 23422 23423 case HostText: 23424 { 23425 // We have no life-cycles associated with text. 23426 break; 23427 } 23428 23429 case HostPortal: 23430 { 23431 // We have no life-cycles associated with portals. 23432 break; 23433 } 23434 23435 case Profiler: 23436 { 23437 { 23438 var _finishedWork$memoize2 = finishedWork.memoizedProps, 23439 onCommit = _finishedWork$memoize2.onCommit, 23440 onRender = _finishedWork$memoize2.onRender; 23441 var effectDuration = finishedWork.stateNode.effectDuration; 23442 var commitTime = getCommitTime(); 23443 var phase = current === null ? 'mount' : 'update'; 23444 23445 { 23446 if (isCurrentUpdateNested()) { 23447 phase = 'nested-update'; 23448 } 23449 } 23450 23451 if (typeof onRender === 'function') { 23452 onRender(finishedWork.memoizedProps.id, phase, finishedWork.actualDuration, finishedWork.treeBaseDuration, finishedWork.actualStartTime, commitTime); 23453 } 23454 23455 { 23456 if (typeof onCommit === 'function') { 23457 onCommit(finishedWork.memoizedProps.id, phase, effectDuration, commitTime); 23458 } // Schedule a passive effect for this Profiler to call onPostCommit hooks. 23459 // This effect should be scheduled even if there is no onPostCommit callback for this Profiler, 23460 // because the effect is also where times bubble to parent Profilers. 23461 23462 23463 enqueuePendingPassiveProfilerEffect(finishedWork); // Propagate layout effect durations to the next nearest Profiler ancestor. 23464 // Do not reset these values until the next render so DevTools has a chance to read them first. 23465 23466 var parentFiber = finishedWork.return; 23467 23468 outer: while (parentFiber !== null) { 23469 switch (parentFiber.tag) { 23470 case HostRoot: 23471 var root = parentFiber.stateNode; 23472 root.effectDuration += effectDuration; 23473 break outer; 23474 23475 case Profiler: 23476 var parentStateNode = parentFiber.stateNode; 23477 parentStateNode.effectDuration += effectDuration; 23478 break outer; 23479 } 23480 23481 parentFiber = parentFiber.return; 23482 } 23483 } 23484 } 23485 23486 break; 23487 } 23488 23489 case SuspenseComponent: 23490 { 23491 commitSuspenseHydrationCallbacks(finishedRoot, finishedWork); 23492 break; 23493 } 23494 23495 case SuspenseListComponent: 23496 case IncompleteClassComponent: 23497 case ScopeComponent: 23498 case OffscreenComponent: 23499 case LegacyHiddenComponent: 23500 case TracingMarkerComponent: 23501 { 23502 break; 23503 } 23504 23505 default: 23506 throw new Error('This unit of work tag should not have side-effects. This error is ' + 'likely caused by a bug in React. Please file an issue.'); 23507 } 23508 } 23509 23510 if ( !offscreenSubtreeWasHidden) { 23511 { 23512 if (finishedWork.flags & Ref) { 23513 commitAttachRef(finishedWork); 23514 } 23515 } 23516 } 23517 } 23518 23519 function reappearLayoutEffectsOnFiber(node) { 23520 // Turn on layout effects in a tree that previously disappeared. 23521 // TODO (Offscreen) Check: flags & LayoutStatic 23522 switch (node.tag) { 23523 case FunctionComponent: 23524 case ForwardRef: 23525 case SimpleMemoComponent: 23526 { 23527 if ( node.mode & ProfileMode) { 23528 try { 23529 startLayoutEffectTimer(); 23530 safelyCallCommitHookLayoutEffectListMount(node, node.return); 23531 } finally { 23532 recordLayoutEffectDuration(node); 23533 } 23534 } else { 23535 safelyCallCommitHookLayoutEffectListMount(node, node.return); 23536 } 23537 23538 break; 23539 } 23540 23541 case ClassComponent: 23542 { 23543 var instance = node.stateNode; 23544 23545 if (typeof instance.componentDidMount === 'function') { 23546 safelyCallComponentDidMount(node, node.return, instance); 23547 } 23548 23549 safelyAttachRef(node, node.return); 23550 break; 23551 } 23552 23553 case HostComponent: 23554 { 23555 safelyAttachRef(node, node.return); 23556 break; 23557 } 23558 } 23559 } 23560 23561 function hideOrUnhideAllChildren(finishedWork, isHidden) { 23562 // Only hide or unhide the top-most host nodes. 23563 var hostSubtreeRoot = null; 23564 23565 { 23566 // We only have the top Fiber that was inserted but we need to recurse down its 23567 // children to find all the terminal nodes. 23568 var node = finishedWork; 23569 23570 while (true) { 23571 if (node.tag === HostComponent) { 23572 if (hostSubtreeRoot === null) { 23573 hostSubtreeRoot = node; 23574 23575 try { 23576 var instance = node.stateNode; 23577 23578 if (isHidden) { 23579 hideInstance(instance); 23580 } else { 23581 unhideInstance(node.stateNode, node.memoizedProps); 23582 } 23583 } catch (error) { 23584 captureCommitPhaseError(finishedWork, finishedWork.return, error); 23585 } 23586 } 23587 } else if (node.tag === HostText) { 23588 if (hostSubtreeRoot === null) { 23589 try { 23590 var _instance3 = node.stateNode; 23591 23592 if (isHidden) { 23593 hideTextInstance(_instance3); 23594 } else { 23595 unhideTextInstance(_instance3, node.memoizedProps); 23596 } 23597 } catch (error) { 23598 captureCommitPhaseError(finishedWork, finishedWork.return, error); 23599 } 23600 } 23601 } else if ((node.tag === OffscreenComponent || node.tag === LegacyHiddenComponent) && node.memoizedState !== null && node !== finishedWork) ; else if (node.child !== null) { 23602 node.child.return = node; 23603 node = node.child; 23604 continue; 23605 } 23606 23607 if (node === finishedWork) { 23608 return; 23609 } 23610 23611 while (node.sibling === null) { 23612 if (node.return === null || node.return === finishedWork) { 23613 return; 23614 } 23615 23616 if (hostSubtreeRoot === node) { 23617 hostSubtreeRoot = null; 23618 } 23619 23620 node = node.return; 23621 } 23622 23623 if (hostSubtreeRoot === node) { 23624 hostSubtreeRoot = null; 23625 } 23626 23627 node.sibling.return = node.return; 23628 node = node.sibling; 23629 } 23630 } 23631 } 23632 23633 function commitAttachRef(finishedWork) { 23634 var ref = finishedWork.ref; 23635 23636 if (ref !== null) { 23637 var instance = finishedWork.stateNode; 23638 var instanceToUse; 23639 23640 switch (finishedWork.tag) { 23641 case HostComponent: 23642 instanceToUse = getPublicInstance(instance); 23643 break; 23644 23645 default: 23646 instanceToUse = instance; 23647 } // Moved outside to ensure DCE works with this flag 23648 23649 if (typeof ref === 'function') { 23650 var retVal; 23651 23652 if ( finishedWork.mode & ProfileMode) { 23653 try { 23654 startLayoutEffectTimer(); 23655 retVal = ref(instanceToUse); 23656 } finally { 23657 recordLayoutEffectDuration(finishedWork); 23658 } 23659 } else { 23660 retVal = ref(instanceToUse); 23661 } 23662 23663 { 23664 if (typeof retVal === 'function') { 23665 error('Unexpected return value from a callback ref in %s. ' + 'A callback ref should not return a function.', getComponentNameFromFiber(finishedWork)); 23666 } 23667 } 23668 } else { 23669 { 23670 if (!ref.hasOwnProperty('current')) { 23671 error('Unexpected ref object provided for %s. ' + 'Use either a ref-setter function or React.createRef().', getComponentNameFromFiber(finishedWork)); 23672 } 23673 } 23674 23675 ref.current = instanceToUse; 23676 } 23677 } 23678 } 23679 23680 function detachFiberMutation(fiber) { 23681 // Cut off the return pointer to disconnect it from the tree. 23682 // This enables us to detect and warn against state updates on an unmounted component. 23683 // It also prevents events from bubbling from within disconnected components. 23684 // 23685 // Ideally, we should also clear the child pointer of the parent alternate to let this 23686 // get GC:ed but we don't know which for sure which parent is the current 23687 // one so we'll settle for GC:ing the subtree of this child. 23688 // This child itself will be GC:ed when the parent updates the next time. 23689 // 23690 // Note that we can't clear child or sibling pointers yet. 23691 // They're needed for passive effects and for findDOMNode. 23692 // We defer those fields, and all other cleanup, to the passive phase (see detachFiberAfterEffects). 23693 // 23694 // Don't reset the alternate yet, either. We need that so we can detach the 23695 // alternate's fields in the passive phase. Clearing the return pointer is 23696 // sufficient for findDOMNode semantics. 23697 var alternate = fiber.alternate; 23698 23699 if (alternate !== null) { 23700 alternate.return = null; 23701 } 23702 23703 fiber.return = null; 23704 } 23705 23706 function detachFiberAfterEffects(fiber) { 23707 var alternate = fiber.alternate; 23708 23709 if (alternate !== null) { 23710 fiber.alternate = null; 23711 detachFiberAfterEffects(alternate); 23712 } // Note: Defensively using negation instead of < in case 23713 // `deletedTreeCleanUpLevel` is undefined. 23714 23715 23716 { 23717 // Clear cyclical Fiber fields. This level alone is designed to roughly 23718 // approximate the planned Fiber refactor. In that world, `setState` will be 23719 // bound to a special "instance" object instead of a Fiber. The Instance 23720 // object will not have any of these fields. It will only be connected to 23721 // the fiber tree via a single link at the root. So if this level alone is 23722 // sufficient to fix memory issues, that bodes well for our plans. 23723 fiber.child = null; 23724 fiber.deletions = null; 23725 fiber.sibling = null; // The `stateNode` is cyclical because on host nodes it points to the host 23726 // tree, which has its own pointers to children, parents, and siblings. 23727 // The other host nodes also point back to fibers, so we should detach that 23728 // one, too. 23729 23730 if (fiber.tag === HostComponent) { 23731 var hostInstance = fiber.stateNode; 23732 23733 if (hostInstance !== null) { 23734 detachDeletedInstance(hostInstance); 23735 } 23736 } 23737 23738 fiber.stateNode = null; // I'm intentionally not clearing the `return` field in this level. We 23739 // already disconnect the `return` pointer at the root of the deleted 23740 // subtree (in `detachFiberMutation`). Besides, `return` by itself is not 23741 // cyclical — it's only cyclical when combined with `child`, `sibling`, and 23742 // `alternate`. But we'll clear it in the next level anyway, just in case. 23743 23744 { 23745 fiber._debugOwner = null; 23746 } 23747 23748 { 23749 // Theoretically, nothing in here should be necessary, because we already 23750 // disconnected the fiber from the tree. So even if something leaks this 23751 // particular fiber, it won't leak anything else 23752 // 23753 // The purpose of this branch is to be super aggressive so we can measure 23754 // if there's any difference in memory impact. If there is, that could 23755 // indicate a React leak we don't know about. 23756 fiber.return = null; 23757 fiber.dependencies = null; 23758 fiber.memoizedProps = null; 23759 fiber.memoizedState = null; 23760 fiber.pendingProps = null; 23761 fiber.stateNode = null; // TODO: Move to `commitPassiveUnmountInsideDeletedTreeOnFiber` instead. 23762 23763 fiber.updateQueue = null; 23764 } 23765 } 23766 } 23767 23768 function getHostParentFiber(fiber) { 23769 var parent = fiber.return; 23770 23771 while (parent !== null) { 23772 if (isHostParent(parent)) { 23773 return parent; 23774 } 23775 23776 parent = parent.return; 23777 } 23778 23779 throw new Error('Expected to find a host parent. This error is likely caused by a bug ' + 'in React. Please file an issue.'); 23780 } 23781 23782 function isHostParent(fiber) { 23783 return fiber.tag === HostComponent || fiber.tag === HostRoot || fiber.tag === HostPortal; 23784 } 23785 23786 function getHostSibling(fiber) { 23787 // We're going to search forward into the tree until we find a sibling host 23788 // node. Unfortunately, if multiple insertions are done in a row we have to 23789 // search past them. This leads to exponential search for the next sibling. 23790 // TODO: Find a more efficient way to do this. 23791 var node = fiber; 23792 23793 siblings: while (true) { 23794 // If we didn't find anything, let's try the next sibling. 23795 while (node.sibling === null) { 23796 if (node.return === null || isHostParent(node.return)) { 23797 // If we pop out of the root or hit the parent the fiber we are the 23798 // last sibling. 23799 return null; 23800 } 23801 23802 node = node.return; 23803 } 23804 23805 node.sibling.return = node.return; 23806 node = node.sibling; 23807 23808 while (node.tag !== HostComponent && node.tag !== HostText && node.tag !== DehydratedFragment) { 23809 // If it is not host node and, we might have a host node inside it. 23810 // Try to search down until we find one. 23811 if (node.flags & Placement) { 23812 // If we don't have a child, try the siblings instead. 23813 continue siblings; 23814 } // If we don't have a child, try the siblings instead. 23815 // We also skip portals because they are not part of this host tree. 23816 23817 23818 if (node.child === null || node.tag === HostPortal) { 23819 continue siblings; 23820 } else { 23821 node.child.return = node; 23822 node = node.child; 23823 } 23824 } // Check if this host node is stable or about to be placed. 23825 23826 23827 if (!(node.flags & Placement)) { 23828 // Found it! 23829 return node.stateNode; 23830 } 23831 } 23832 } 23833 23834 function commitPlacement(finishedWork) { 23835 23836 23837 var parentFiber = getHostParentFiber(finishedWork); // Note: these two variables *must* always be updated together. 23838 23839 switch (parentFiber.tag) { 23840 case HostComponent: 23841 { 23842 var parent = parentFiber.stateNode; 23843 23844 if (parentFiber.flags & ContentReset) { 23845 // Reset the text content of the parent before doing any insertions 23846 resetTextContent(parent); // Clear ContentReset from the effect tag 23847 23848 parentFiber.flags &= ~ContentReset; 23849 } 23850 23851 var before = getHostSibling(finishedWork); // We only have the top Fiber that was inserted but we need to recurse down its 23852 // children to find all the terminal nodes. 23853 23854 insertOrAppendPlacementNode(finishedWork, before, parent); 23855 break; 23856 } 23857 23858 case HostRoot: 23859 case HostPortal: 23860 { 23861 var _parent = parentFiber.stateNode.containerInfo; 23862 23863 var _before = getHostSibling(finishedWork); 23864 23865 insertOrAppendPlacementNodeIntoContainer(finishedWork, _before, _parent); 23866 break; 23867 } 23868 // eslint-disable-next-line-no-fallthrough 23869 23870 default: 23871 throw new Error('Invalid host parent fiber. This error is likely caused by a bug ' + 'in React. Please file an issue.'); 23872 } 23873 } 23874 23875 function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { 23876 var tag = node.tag; 23877 var isHost = tag === HostComponent || tag === HostText; 23878 23879 if (isHost) { 23880 var stateNode = node.stateNode; 23881 23882 if (before) { 23883 insertInContainerBefore(parent, stateNode, before); 23884 } else { 23885 appendChildToContainer(parent, stateNode); 23886 } 23887 } else if (tag === HostPortal) ; else { 23888 var child = node.child; 23889 23890 if (child !== null) { 23891 insertOrAppendPlacementNodeIntoContainer(child, before, parent); 23892 var sibling = child.sibling; 23893 23894 while (sibling !== null) { 23895 insertOrAppendPlacementNodeIntoContainer(sibling, before, parent); 23896 sibling = sibling.sibling; 23897 } 23898 } 23899 } 23900 } 23901 23902 function insertOrAppendPlacementNode(node, before, parent) { 23903 var tag = node.tag; 23904 var isHost = tag === HostComponent || tag === HostText; 23905 23906 if (isHost) { 23907 var stateNode = node.stateNode; 23908 23909 if (before) { 23910 insertBefore(parent, stateNode, before); 23911 } else { 23912 appendChild(parent, stateNode); 23913 } 23914 } else if (tag === HostPortal) ; else { 23915 var child = node.child; 23916 23917 if (child !== null) { 23918 insertOrAppendPlacementNode(child, before, parent); 23919 var sibling = child.sibling; 23920 23921 while (sibling !== null) { 23922 insertOrAppendPlacementNode(sibling, before, parent); 23923 sibling = sibling.sibling; 23924 } 23925 } 23926 } 23927 } // These are tracked on the stack as we recursively traverse a 23928 // deleted subtree. 23929 // TODO: Update these during the whole mutation phase, not just during 23930 // a deletion. 23931 23932 23933 var hostParent = null; 23934 var hostParentIsContainer = false; 23935 23936 function commitDeletionEffects(root, returnFiber, deletedFiber) { 23937 { 23938 // We only have the top Fiber that was deleted but we need to recurse down its 23939 // children to find all the terminal nodes. 23940 // Recursively delete all host nodes from the parent, detach refs, clean 23941 // up mounted layout effects, and call componentWillUnmount. 23942 // We only need to remove the topmost host child in each branch. But then we 23943 // still need to keep traversing to unmount effects, refs, and cWU. TODO: We 23944 // could split this into two separate traversals functions, where the second 23945 // one doesn't include any removeChild logic. This is maybe the same 23946 // function as "disappearLayoutEffects" (or whatever that turns into after 23947 // the layout phase is refactored to use recursion). 23948 // Before starting, find the nearest host parent on the stack so we know 23949 // which instance/container to remove the children from. 23950 // TODO: Instead of searching up the fiber return path on every deletion, we 23951 // can track the nearest host component on the JS stack as we traverse the 23952 // tree during the commit phase. This would make insertions faster, too. 23953 var parent = returnFiber; 23954 23955 findParent: while (parent !== null) { 23956 switch (parent.tag) { 23957 case HostComponent: 23958 { 23959 hostParent = parent.stateNode; 23960 hostParentIsContainer = false; 23961 break findParent; 23962 } 23963 23964 case HostRoot: 23965 { 23966 hostParent = parent.stateNode.containerInfo; 23967 hostParentIsContainer = true; 23968 break findParent; 23969 } 23970 23971 case HostPortal: 23972 { 23973 hostParent = parent.stateNode.containerInfo; 23974 hostParentIsContainer = true; 23975 break findParent; 23976 } 23977 } 23978 23979 parent = parent.return; 23980 } 23981 23982 if (hostParent === null) { 23983 throw new Error('Expected to find a host parent. This error is likely caused by ' + 'a bug in React. Please file an issue.'); 23984 } 23985 23986 commitDeletionEffectsOnFiber(root, returnFiber, deletedFiber); 23987 hostParent = null; 23988 hostParentIsContainer = false; 23989 } 23990 23991 detachFiberMutation(deletedFiber); 23992 } 23993 23994 function recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, parent) { 23995 // TODO: Use a static flag to skip trees that don't have unmount effects 23996 var child = parent.child; 23997 23998 while (child !== null) { 23999 commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, child); 24000 child = child.sibling; 24001 } 24002 } 24003 24004 function commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, deletedFiber) { 24005 onCommitUnmount(deletedFiber); // The cases in this outer switch modify the stack before they traverse 24006 // into their subtree. There are simpler cases in the inner switch 24007 // that don't modify the stack. 24008 24009 switch (deletedFiber.tag) { 24010 case HostComponent: 24011 { 24012 if (!offscreenSubtreeWasHidden) { 24013 safelyDetachRef(deletedFiber, nearestMountedAncestor); 24014 } // Intentional fallthrough to next branch 24015 24016 } 24017 // eslint-disable-next-line-no-fallthrough 24018 24019 case HostText: 24020 { 24021 // We only need to remove the nearest host child. Set the host parent 24022 // to `null` on the stack to indicate that nested children don't 24023 // need to be removed. 24024 { 24025 var prevHostParent = hostParent; 24026 var prevHostParentIsContainer = hostParentIsContainer; 24027 hostParent = null; 24028 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24029 hostParent = prevHostParent; 24030 hostParentIsContainer = prevHostParentIsContainer; 24031 24032 if (hostParent !== null) { 24033 // Now that all the child effects have unmounted, we can remove the 24034 // node from the tree. 24035 if (hostParentIsContainer) { 24036 removeChildFromContainer(hostParent, deletedFiber.stateNode); 24037 } else { 24038 removeChild(hostParent, deletedFiber.stateNode); 24039 } 24040 } 24041 } 24042 24043 return; 24044 } 24045 24046 case DehydratedFragment: 24047 { 24048 // Delete the dehydrated suspense boundary and all of its content. 24049 24050 24051 { 24052 if (hostParent !== null) { 24053 if (hostParentIsContainer) { 24054 clearSuspenseBoundaryFromContainer(hostParent, deletedFiber.stateNode); 24055 } else { 24056 clearSuspenseBoundary(hostParent, deletedFiber.stateNode); 24057 } 24058 } 24059 } 24060 24061 return; 24062 } 24063 24064 case HostPortal: 24065 { 24066 { 24067 // When we go into a portal, it becomes the parent to remove from. 24068 var _prevHostParent = hostParent; 24069 var _prevHostParentIsContainer = hostParentIsContainer; 24070 hostParent = deletedFiber.stateNode.containerInfo; 24071 hostParentIsContainer = true; 24072 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24073 hostParent = _prevHostParent; 24074 hostParentIsContainer = _prevHostParentIsContainer; 24075 } 24076 24077 return; 24078 } 24079 24080 case FunctionComponent: 24081 case ForwardRef: 24082 case MemoComponent: 24083 case SimpleMemoComponent: 24084 { 24085 if (!offscreenSubtreeWasHidden) { 24086 var updateQueue = deletedFiber.updateQueue; 24087 24088 if (updateQueue !== null) { 24089 var lastEffect = updateQueue.lastEffect; 24090 24091 if (lastEffect !== null) { 24092 var firstEffect = lastEffect.next; 24093 var effect = firstEffect; 24094 24095 do { 24096 var _effect = effect, 24097 destroy = _effect.destroy, 24098 tag = _effect.tag; 24099 24100 if (destroy !== undefined) { 24101 if ((tag & Insertion) !== NoFlags$1) { 24102 safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy); 24103 } else if ((tag & Layout) !== NoFlags$1) { 24104 { 24105 markComponentLayoutEffectUnmountStarted(deletedFiber); 24106 } 24107 24108 if ( deletedFiber.mode & ProfileMode) { 24109 startLayoutEffectTimer(); 24110 safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy); 24111 recordLayoutEffectDuration(deletedFiber); 24112 } else { 24113 safelyCallDestroy(deletedFiber, nearestMountedAncestor, destroy); 24114 } 24115 24116 { 24117 markComponentLayoutEffectUnmountStopped(); 24118 } 24119 } 24120 } 24121 24122 effect = effect.next; 24123 } while (effect !== firstEffect); 24124 } 24125 } 24126 } 24127 24128 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24129 return; 24130 } 24131 24132 case ClassComponent: 24133 { 24134 if (!offscreenSubtreeWasHidden) { 24135 safelyDetachRef(deletedFiber, nearestMountedAncestor); 24136 var instance = deletedFiber.stateNode; 24137 24138 if (typeof instance.componentWillUnmount === 'function') { 24139 safelyCallComponentWillUnmount(deletedFiber, nearestMountedAncestor, instance); 24140 } 24141 } 24142 24143 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24144 return; 24145 } 24146 24147 case ScopeComponent: 24148 { 24149 24150 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24151 return; 24152 } 24153 24154 case OffscreenComponent: 24155 { 24156 if ( // TODO: Remove this dead flag 24157 deletedFiber.mode & ConcurrentMode) { 24158 // If this offscreen component is hidden, we already unmounted it. Before 24159 // deleting the children, track that it's already unmounted so that we 24160 // don't attempt to unmount the effects again. 24161 // TODO: If the tree is hidden, in most cases we should be able to skip 24162 // over the nested children entirely. An exception is we haven't yet found 24163 // the topmost host node to delete, which we already track on the stack. 24164 // But the other case is portals, which need to be detached no matter how 24165 // deeply they are nested. We should use a subtree flag to track whether a 24166 // subtree includes a nested portal. 24167 var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; 24168 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || deletedFiber.memoizedState !== null; 24169 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24170 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; 24171 } else { 24172 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24173 } 24174 24175 break; 24176 } 24177 24178 default: 24179 { 24180 recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); 24181 return; 24182 } 24183 } 24184 } 24185 24186 function commitSuspenseCallback(finishedWork) { 24187 // TODO: Move this to passive phase 24188 var newState = finishedWork.memoizedState; 24189 } 24190 24191 function commitSuspenseHydrationCallbacks(finishedRoot, finishedWork) { 24192 24193 var newState = finishedWork.memoizedState; 24194 24195 if (newState === null) { 24196 var current = finishedWork.alternate; 24197 24198 if (current !== null) { 24199 var prevState = current.memoizedState; 24200 24201 if (prevState !== null) { 24202 var suspenseInstance = prevState.dehydrated; 24203 24204 if (suspenseInstance !== null) { 24205 commitHydratedSuspenseInstance(suspenseInstance); 24206 } 24207 } 24208 } 24209 } 24210 } 24211 24212 function attachSuspenseRetryListeners(finishedWork) { 24213 // If this boundary just timed out, then it will have a set of wakeables. 24214 // For each wakeable, attach a listener so that when it resolves, React 24215 // attempts to re-render the boundary in the primary (pre-timeout) state. 24216 var wakeables = finishedWork.updateQueue; 24217 24218 if (wakeables !== null) { 24219 finishedWork.updateQueue = null; 24220 var retryCache = finishedWork.stateNode; 24221 24222 if (retryCache === null) { 24223 retryCache = finishedWork.stateNode = new PossiblyWeakSet(); 24224 } 24225 24226 wakeables.forEach(function (wakeable) { 24227 // Memoize using the boundary fiber to prevent redundant listeners. 24228 var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); 24229 24230 if (!retryCache.has(wakeable)) { 24231 retryCache.add(wakeable); 24232 24233 { 24234 if (isDevToolsPresent) { 24235 if (inProgressLanes !== null && inProgressRoot !== null) { 24236 // If we have pending work still, associate the original updaters with it. 24237 restorePendingUpdaters(inProgressRoot, inProgressLanes); 24238 } else { 24239 throw Error('Expected finished root and lanes to be set. This is a bug in React.'); 24240 } 24241 } 24242 } 24243 24244 wakeable.then(retry, retry); 24245 } 24246 }); 24247 } 24248 } // This function detects when a Suspense boundary goes from visible to hidden. 24249 function commitMutationEffects(root, finishedWork, committedLanes) { 24250 inProgressLanes = committedLanes; 24251 inProgressRoot = root; 24252 setCurrentFiber(finishedWork); 24253 commitMutationEffectsOnFiber(finishedWork, root); 24254 setCurrentFiber(finishedWork); 24255 inProgressLanes = null; 24256 inProgressRoot = null; 24257 } 24258 24259 function recursivelyTraverseMutationEffects(root, parentFiber, lanes) { 24260 // Deletions effects can be scheduled on any fiber type. They need to happen 24261 // before the children effects hae fired. 24262 var deletions = parentFiber.deletions; 24263 24264 if (deletions !== null) { 24265 for (var i = 0; i < deletions.length; i++) { 24266 var childToDelete = deletions[i]; 24267 24268 try { 24269 commitDeletionEffects(root, parentFiber, childToDelete); 24270 } catch (error) { 24271 captureCommitPhaseError(childToDelete, parentFiber, error); 24272 } 24273 } 24274 } 24275 24276 var prevDebugFiber = getCurrentFiber(); 24277 24278 if (parentFiber.subtreeFlags & MutationMask) { 24279 var child = parentFiber.child; 24280 24281 while (child !== null) { 24282 setCurrentFiber(child); 24283 commitMutationEffectsOnFiber(child, root); 24284 child = child.sibling; 24285 } 24286 } 24287 24288 setCurrentFiber(prevDebugFiber); 24289 } 24290 24291 function commitMutationEffectsOnFiber(finishedWork, root, lanes) { 24292 var current = finishedWork.alternate; 24293 var flags = finishedWork.flags; // The effect flag should be checked *after* we refine the type of fiber, 24294 // because the fiber tag is more specific. An exception is any flag related 24295 // to reconcilation, because those can be set on all fiber types. 24296 24297 switch (finishedWork.tag) { 24298 case FunctionComponent: 24299 case ForwardRef: 24300 case MemoComponent: 24301 case SimpleMemoComponent: 24302 { 24303 recursivelyTraverseMutationEffects(root, finishedWork); 24304 commitReconciliationEffects(finishedWork); 24305 24306 if (flags & Update) { 24307 try { 24308 commitHookEffectListUnmount(Insertion | HasEffect, finishedWork, finishedWork.return); 24309 commitHookEffectListMount(Insertion | HasEffect, finishedWork); 24310 } catch (error) { 24311 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24312 } // Layout effects are destroyed during the mutation phase so that all 24313 // destroy functions for all fibers are called before any create functions. 24314 // This prevents sibling component effects from interfering with each other, 24315 // e.g. a destroy function in one component should never override a ref set 24316 // by a create function in another component during the same commit. 24317 24318 24319 if ( finishedWork.mode & ProfileMode) { 24320 try { 24321 startLayoutEffectTimer(); 24322 commitHookEffectListUnmount(Layout | HasEffect, finishedWork, finishedWork.return); 24323 } catch (error) { 24324 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24325 } 24326 24327 recordLayoutEffectDuration(finishedWork); 24328 } else { 24329 try { 24330 commitHookEffectListUnmount(Layout | HasEffect, finishedWork, finishedWork.return); 24331 } catch (error) { 24332 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24333 } 24334 } 24335 } 24336 24337 return; 24338 } 24339 24340 case ClassComponent: 24341 { 24342 recursivelyTraverseMutationEffects(root, finishedWork); 24343 commitReconciliationEffects(finishedWork); 24344 24345 if (flags & Ref) { 24346 if (current !== null) { 24347 safelyDetachRef(current, current.return); 24348 } 24349 } 24350 24351 return; 24352 } 24353 24354 case HostComponent: 24355 { 24356 recursivelyTraverseMutationEffects(root, finishedWork); 24357 commitReconciliationEffects(finishedWork); 24358 24359 if (flags & Ref) { 24360 if (current !== null) { 24361 safelyDetachRef(current, current.return); 24362 } 24363 } 24364 24365 { 24366 // TODO: ContentReset gets cleared by the children during the commit 24367 // phase. This is a refactor hazard because it means we must read 24368 // flags the flags after `commitReconciliationEffects` has already run; 24369 // the order matters. We should refactor so that ContentReset does not 24370 // rely on mutating the flag during commit. Like by setting a flag 24371 // during the render phase instead. 24372 if (finishedWork.flags & ContentReset) { 24373 var instance = finishedWork.stateNode; 24374 24375 try { 24376 resetTextContent(instance); 24377 } catch (error) { 24378 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24379 } 24380 } 24381 24382 if (flags & Update) { 24383 var _instance4 = finishedWork.stateNode; 24384 24385 if (_instance4 != null) { 24386 // Commit the work prepared earlier. 24387 var newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps 24388 // as the newProps. The updatePayload will contain the real change in 24389 // this case. 24390 24391 var oldProps = current !== null ? current.memoizedProps : newProps; 24392 var type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. 24393 24394 var updatePayload = finishedWork.updateQueue; 24395 finishedWork.updateQueue = null; 24396 24397 if (updatePayload !== null) { 24398 try { 24399 commitUpdate(_instance4, updatePayload, type, oldProps, newProps, finishedWork); 24400 } catch (error) { 24401 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24402 } 24403 } 24404 } 24405 } 24406 } 24407 24408 return; 24409 } 24410 24411 case HostText: 24412 { 24413 recursivelyTraverseMutationEffects(root, finishedWork); 24414 commitReconciliationEffects(finishedWork); 24415 24416 if (flags & Update) { 24417 { 24418 if (finishedWork.stateNode === null) { 24419 throw new Error('This should have a text node initialized. This error is likely ' + 'caused by a bug in React. Please file an issue.'); 24420 } 24421 24422 var textInstance = finishedWork.stateNode; 24423 var newText = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps 24424 // as the newProps. The updatePayload will contain the real change in 24425 // this case. 24426 24427 var oldText = current !== null ? current.memoizedProps : newText; 24428 24429 try { 24430 commitTextUpdate(textInstance, oldText, newText); 24431 } catch (error) { 24432 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24433 } 24434 } 24435 } 24436 24437 return; 24438 } 24439 24440 case HostRoot: 24441 { 24442 recursivelyTraverseMutationEffects(root, finishedWork); 24443 commitReconciliationEffects(finishedWork); 24444 24445 if (flags & Update) { 24446 { 24447 if (current !== null) { 24448 var prevRootState = current.memoizedState; 24449 24450 if (prevRootState.isDehydrated) { 24451 try { 24452 commitHydratedContainer(root.containerInfo); 24453 } catch (error) { 24454 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24455 } 24456 } 24457 } 24458 } 24459 } 24460 24461 return; 24462 } 24463 24464 case HostPortal: 24465 { 24466 recursivelyTraverseMutationEffects(root, finishedWork); 24467 commitReconciliationEffects(finishedWork); 24468 24469 return; 24470 } 24471 24472 case SuspenseComponent: 24473 { 24474 recursivelyTraverseMutationEffects(root, finishedWork); 24475 commitReconciliationEffects(finishedWork); 24476 var offscreenFiber = finishedWork.child; 24477 24478 if (offscreenFiber.flags & Visibility) { 24479 var offscreenInstance = offscreenFiber.stateNode; 24480 var newState = offscreenFiber.memoizedState; 24481 var isHidden = newState !== null; // Track the current state on the Offscreen instance so we can 24482 // read it during an event 24483 24484 offscreenInstance.isHidden = isHidden; 24485 24486 if (isHidden) { 24487 var wasHidden = offscreenFiber.alternate !== null && offscreenFiber.alternate.memoizedState !== null; 24488 24489 if (!wasHidden) { 24490 // TODO: Move to passive phase 24491 markCommitTimeOfFallback(); 24492 } 24493 } 24494 } 24495 24496 if (flags & Update) { 24497 try { 24498 commitSuspenseCallback(finishedWork); 24499 } catch (error) { 24500 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24501 } 24502 24503 attachSuspenseRetryListeners(finishedWork); 24504 } 24505 24506 return; 24507 } 24508 24509 case OffscreenComponent: 24510 { 24511 var _wasHidden = current !== null && current.memoizedState !== null; 24512 24513 if ( // TODO: Remove this dead flag 24514 finishedWork.mode & ConcurrentMode) { 24515 // Before committing the children, track on the stack whether this 24516 // offscreen subtree was already hidden, so that we don't unmount the 24517 // effects again. 24518 var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; 24519 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || _wasHidden; 24520 recursivelyTraverseMutationEffects(root, finishedWork); 24521 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; 24522 } else { 24523 recursivelyTraverseMutationEffects(root, finishedWork); 24524 } 24525 24526 commitReconciliationEffects(finishedWork); 24527 24528 if (flags & Visibility) { 24529 var _offscreenInstance = finishedWork.stateNode; 24530 var _newState = finishedWork.memoizedState; 24531 24532 var _isHidden = _newState !== null; 24533 24534 var offscreenBoundary = finishedWork; // Track the current state on the Offscreen instance so we can 24535 // read it during an event 24536 24537 _offscreenInstance.isHidden = _isHidden; 24538 24539 { 24540 if (_isHidden) { 24541 if (!_wasHidden) { 24542 if ((offscreenBoundary.mode & ConcurrentMode) !== NoMode) { 24543 nextEffect = offscreenBoundary; 24544 var offscreenChild = offscreenBoundary.child; 24545 24546 while (offscreenChild !== null) { 24547 nextEffect = offscreenChild; 24548 disappearLayoutEffects_begin(offscreenChild); 24549 offscreenChild = offscreenChild.sibling; 24550 } 24551 } 24552 } 24553 } 24554 } 24555 24556 { 24557 // TODO: This needs to run whenever there's an insertion or update 24558 // inside a hidden Offscreen tree. 24559 hideOrUnhideAllChildren(offscreenBoundary, _isHidden); 24560 } 24561 } 24562 24563 return; 24564 } 24565 24566 case SuspenseListComponent: 24567 { 24568 recursivelyTraverseMutationEffects(root, finishedWork); 24569 commitReconciliationEffects(finishedWork); 24570 24571 if (flags & Update) { 24572 attachSuspenseRetryListeners(finishedWork); 24573 } 24574 24575 return; 24576 } 24577 24578 case ScopeComponent: 24579 { 24580 24581 return; 24582 } 24583 24584 default: 24585 { 24586 recursivelyTraverseMutationEffects(root, finishedWork); 24587 commitReconciliationEffects(finishedWork); 24588 return; 24589 } 24590 } 24591 } 24592 24593 function commitReconciliationEffects(finishedWork) { 24594 // Placement effects (insertions, reorders) can be scheduled on any fiber 24595 // type. They needs to happen after the children effects have fired, but 24596 // before the effects on this fiber have fired. 24597 var flags = finishedWork.flags; 24598 24599 if (flags & Placement) { 24600 try { 24601 commitPlacement(finishedWork); 24602 } catch (error) { 24603 captureCommitPhaseError(finishedWork, finishedWork.return, error); 24604 } // Clear the "placement" from effect tag so that we know that this is 24605 // inserted, before any life-cycles like componentDidMount gets called. 24606 // TODO: findDOMNode doesn't rely on this any more but isMounted does 24607 // and isMounted is deprecated anyway so we should be able to kill this. 24608 24609 24610 finishedWork.flags &= ~Placement; 24611 } 24612 24613 if (flags & Hydrating) { 24614 finishedWork.flags &= ~Hydrating; 24615 } 24616 } 24617 24618 function commitLayoutEffects(finishedWork, root, committedLanes) { 24619 inProgressLanes = committedLanes; 24620 inProgressRoot = root; 24621 nextEffect = finishedWork; 24622 commitLayoutEffects_begin(finishedWork, root, committedLanes); 24623 inProgressLanes = null; 24624 inProgressRoot = null; 24625 } 24626 24627 function commitLayoutEffects_begin(subtreeRoot, root, committedLanes) { 24628 // Suspense layout effects semantics don't change for legacy roots. 24629 var isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode; 24630 24631 while (nextEffect !== null) { 24632 var fiber = nextEffect; 24633 var firstChild = fiber.child; 24634 24635 if ( fiber.tag === OffscreenComponent && isModernRoot) { 24636 // Keep track of the current Offscreen stack's state. 24637 var isHidden = fiber.memoizedState !== null; 24638 var newOffscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden; 24639 24640 if (newOffscreenSubtreeIsHidden) { 24641 // The Offscreen tree is hidden. Skip over its layout effects. 24642 commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); 24643 continue; 24644 } else { 24645 // TODO (Offscreen) Also check: subtreeFlags & LayoutMask 24646 var current = fiber.alternate; 24647 var wasHidden = current !== null && current.memoizedState !== null; 24648 var newOffscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden; 24649 var prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden; 24650 var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; // Traverse the Offscreen subtree with the current Offscreen as the root. 24651 24652 offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden; 24653 offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden; 24654 24655 if (offscreenSubtreeWasHidden && !prevOffscreenSubtreeWasHidden) { 24656 // This is the root of a reappearing boundary. Turn its layout effects 24657 // back on. 24658 nextEffect = fiber; 24659 reappearLayoutEffects_begin(fiber); 24660 } 24661 24662 var child = firstChild; 24663 24664 while (child !== null) { 24665 nextEffect = child; 24666 commitLayoutEffects_begin(child, // New root; bubble back up to here and stop. 24667 root, committedLanes); 24668 child = child.sibling; 24669 } // Restore Offscreen state and resume in our-progress traversal. 24670 24671 24672 nextEffect = fiber; 24673 offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; 24674 offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; 24675 commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); 24676 continue; 24677 } 24678 } 24679 24680 if ((fiber.subtreeFlags & LayoutMask) !== NoFlags && firstChild !== null) { 24681 firstChild.return = fiber; 24682 nextEffect = firstChild; 24683 } else { 24684 commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes); 24685 } 24686 } 24687 } 24688 24689 function commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes) { 24690 while (nextEffect !== null) { 24691 var fiber = nextEffect; 24692 24693 if ((fiber.flags & LayoutMask) !== NoFlags) { 24694 var current = fiber.alternate; 24695 setCurrentFiber(fiber); 24696 24697 try { 24698 commitLayoutEffectOnFiber(root, current, fiber, committedLanes); 24699 } catch (error) { 24700 captureCommitPhaseError(fiber, fiber.return, error); 24701 } 24702 24703 resetCurrentFiber(); 24704 } 24705 24706 if (fiber === subtreeRoot) { 24707 nextEffect = null; 24708 return; 24709 } 24710 24711 var sibling = fiber.sibling; 24712 24713 if (sibling !== null) { 24714 sibling.return = fiber.return; 24715 nextEffect = sibling; 24716 return; 24717 } 24718 24719 nextEffect = fiber.return; 24720 } 24721 } 24722 24723 function disappearLayoutEffects_begin(subtreeRoot) { 24724 while (nextEffect !== null) { 24725 var fiber = nextEffect; 24726 var firstChild = fiber.child; // TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic) 24727 24728 switch (fiber.tag) { 24729 case FunctionComponent: 24730 case ForwardRef: 24731 case MemoComponent: 24732 case SimpleMemoComponent: 24733 { 24734 if ( fiber.mode & ProfileMode) { 24735 try { 24736 startLayoutEffectTimer(); 24737 commitHookEffectListUnmount(Layout, fiber, fiber.return); 24738 } finally { 24739 recordLayoutEffectDuration(fiber); 24740 } 24741 } else { 24742 commitHookEffectListUnmount(Layout, fiber, fiber.return); 24743 } 24744 24745 break; 24746 } 24747 24748 case ClassComponent: 24749 { 24750 // TODO (Offscreen) Check: flags & RefStatic 24751 safelyDetachRef(fiber, fiber.return); 24752 var instance = fiber.stateNode; 24753 24754 if (typeof instance.componentWillUnmount === 'function') { 24755 safelyCallComponentWillUnmount(fiber, fiber.return, instance); 24756 } 24757 24758 break; 24759 } 24760 24761 case HostComponent: 24762 { 24763 safelyDetachRef(fiber, fiber.return); 24764 break; 24765 } 24766 24767 case OffscreenComponent: 24768 { 24769 // Check if this is a 24770 var isHidden = fiber.memoizedState !== null; 24771 24772 if (isHidden) { 24773 // Nested Offscreen tree is already hidden. Don't disappear 24774 // its effects. 24775 disappearLayoutEffects_complete(subtreeRoot); 24776 continue; 24777 } 24778 24779 break; 24780 } 24781 } // TODO (Offscreen) Check: subtreeFlags & LayoutStatic 24782 24783 24784 if (firstChild !== null) { 24785 firstChild.return = fiber; 24786 nextEffect = firstChild; 24787 } else { 24788 disappearLayoutEffects_complete(subtreeRoot); 24789 } 24790 } 24791 } 24792 24793 function disappearLayoutEffects_complete(subtreeRoot) { 24794 while (nextEffect !== null) { 24795 var fiber = nextEffect; 24796 24797 if (fiber === subtreeRoot) { 24798 nextEffect = null; 24799 return; 24800 } 24801 24802 var sibling = fiber.sibling; 24803 24804 if (sibling !== null) { 24805 sibling.return = fiber.return; 24806 nextEffect = sibling; 24807 return; 24808 } 24809 24810 nextEffect = fiber.return; 24811 } 24812 } 24813 24814 function reappearLayoutEffects_begin(subtreeRoot) { 24815 while (nextEffect !== null) { 24816 var fiber = nextEffect; 24817 var firstChild = fiber.child; 24818 24819 if (fiber.tag === OffscreenComponent) { 24820 var isHidden = fiber.memoizedState !== null; 24821 24822 if (isHidden) { 24823 // Nested Offscreen tree is still hidden. Don't re-appear its effects. 24824 reappearLayoutEffects_complete(subtreeRoot); 24825 continue; 24826 } 24827 } // TODO (Offscreen) Check: subtreeFlags & LayoutStatic 24828 24829 24830 if (firstChild !== null) { 24831 // This node may have been reused from a previous render, so we can't 24832 // assume its return pointer is correct. 24833 firstChild.return = fiber; 24834 nextEffect = firstChild; 24835 } else { 24836 reappearLayoutEffects_complete(subtreeRoot); 24837 } 24838 } 24839 } 24840 24841 function reappearLayoutEffects_complete(subtreeRoot) { 24842 while (nextEffect !== null) { 24843 var fiber = nextEffect; // TODO (Offscreen) Check: flags & LayoutStatic 24844 24845 setCurrentFiber(fiber); 24846 24847 try { 24848 reappearLayoutEffectsOnFiber(fiber); 24849 } catch (error) { 24850 captureCommitPhaseError(fiber, fiber.return, error); 24851 } 24852 24853 resetCurrentFiber(); 24854 24855 if (fiber === subtreeRoot) { 24856 nextEffect = null; 24857 return; 24858 } 24859 24860 var sibling = fiber.sibling; 24861 24862 if (sibling !== null) { 24863 // This node may have been reused from a previous render, so we can't 24864 // assume its return pointer is correct. 24865 sibling.return = fiber.return; 24866 nextEffect = sibling; 24867 return; 24868 } 24869 24870 nextEffect = fiber.return; 24871 } 24872 } 24873 24874 function commitPassiveMountEffects(root, finishedWork, committedLanes, committedTransitions) { 24875 nextEffect = finishedWork; 24876 commitPassiveMountEffects_begin(finishedWork, root, committedLanes, committedTransitions); 24877 } 24878 24879 function commitPassiveMountEffects_begin(subtreeRoot, root, committedLanes, committedTransitions) { 24880 while (nextEffect !== null) { 24881 var fiber = nextEffect; 24882 var firstChild = fiber.child; 24883 24884 if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && firstChild !== null) { 24885 firstChild.return = fiber; 24886 nextEffect = firstChild; 24887 } else { 24888 commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes, committedTransitions); 24889 } 24890 } 24891 } 24892 24893 function commitPassiveMountEffects_complete(subtreeRoot, root, committedLanes, committedTransitions) { 24894 while (nextEffect !== null) { 24895 var fiber = nextEffect; 24896 24897 if ((fiber.flags & Passive) !== NoFlags) { 24898 setCurrentFiber(fiber); 24899 24900 try { 24901 commitPassiveMountOnFiber(root, fiber, committedLanes, committedTransitions); 24902 } catch (error) { 24903 captureCommitPhaseError(fiber, fiber.return, error); 24904 } 24905 24906 resetCurrentFiber(); 24907 } 24908 24909 if (fiber === subtreeRoot) { 24910 nextEffect = null; 24911 return; 24912 } 24913 24914 var sibling = fiber.sibling; 24915 24916 if (sibling !== null) { 24917 sibling.return = fiber.return; 24918 nextEffect = sibling; 24919 return; 24920 } 24921 24922 nextEffect = fiber.return; 24923 } 24924 } 24925 24926 function commitPassiveMountOnFiber(finishedRoot, finishedWork, committedLanes, committedTransitions) { 24927 switch (finishedWork.tag) { 24928 case FunctionComponent: 24929 case ForwardRef: 24930 case SimpleMemoComponent: 24931 { 24932 if ( finishedWork.mode & ProfileMode) { 24933 startPassiveEffectTimer(); 24934 24935 try { 24936 commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); 24937 } finally { 24938 recordPassiveEffectDuration(finishedWork); 24939 } 24940 } else { 24941 commitHookEffectListMount(Passive$1 | HasEffect, finishedWork); 24942 } 24943 24944 break; 24945 } 24946 } 24947 } 24948 24949 function commitPassiveUnmountEffects(firstChild) { 24950 nextEffect = firstChild; 24951 commitPassiveUnmountEffects_begin(); 24952 } 24953 24954 function commitPassiveUnmountEffects_begin() { 24955 while (nextEffect !== null) { 24956 var fiber = nextEffect; 24957 var child = fiber.child; 24958 24959 if ((nextEffect.flags & ChildDeletion) !== NoFlags) { 24960 var deletions = fiber.deletions; 24961 24962 if (deletions !== null) { 24963 for (var i = 0; i < deletions.length; i++) { 24964 var fiberToDelete = deletions[i]; 24965 nextEffect = fiberToDelete; 24966 commitPassiveUnmountEffectsInsideOfDeletedTree_begin(fiberToDelete, fiber); 24967 } 24968 24969 { 24970 // A fiber was deleted from this parent fiber, but it's still part of 24971 // the previous (alternate) parent fiber's list of children. Because 24972 // children are a linked list, an earlier sibling that's still alive 24973 // will be connected to the deleted fiber via its `alternate`: 24974 // 24975 // live fiber 24976 // --alternate--> previous live fiber 24977 // --sibling--> deleted fiber 24978 // 24979 // We can't disconnect `alternate` on nodes that haven't been deleted 24980 // yet, but we can disconnect the `sibling` and `child` pointers. 24981 var previousFiber = fiber.alternate; 24982 24983 if (previousFiber !== null) { 24984 var detachedChild = previousFiber.child; 24985 24986 if (detachedChild !== null) { 24987 previousFiber.child = null; 24988 24989 do { 24990 var detachedSibling = detachedChild.sibling; 24991 detachedChild.sibling = null; 24992 detachedChild = detachedSibling; 24993 } while (detachedChild !== null); 24994 } 24995 } 24996 } 24997 24998 nextEffect = fiber; 24999 } 25000 } 25001 25002 if ((fiber.subtreeFlags & PassiveMask) !== NoFlags && child !== null) { 25003 child.return = fiber; 25004 nextEffect = child; 25005 } else { 25006 commitPassiveUnmountEffects_complete(); 25007 } 25008 } 25009 } 25010 25011 function commitPassiveUnmountEffects_complete() { 25012 while (nextEffect !== null) { 25013 var fiber = nextEffect; 25014 25015 if ((fiber.flags & Passive) !== NoFlags) { 25016 setCurrentFiber(fiber); 25017 commitPassiveUnmountOnFiber(fiber); 25018 resetCurrentFiber(); 25019 } 25020 25021 var sibling = fiber.sibling; 25022 25023 if (sibling !== null) { 25024 sibling.return = fiber.return; 25025 nextEffect = sibling; 25026 return; 25027 } 25028 25029 nextEffect = fiber.return; 25030 } 25031 } 25032 25033 function commitPassiveUnmountOnFiber(finishedWork) { 25034 switch (finishedWork.tag) { 25035 case FunctionComponent: 25036 case ForwardRef: 25037 case SimpleMemoComponent: 25038 { 25039 if ( finishedWork.mode & ProfileMode) { 25040 startPassiveEffectTimer(); 25041 commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork, finishedWork.return); 25042 recordPassiveEffectDuration(finishedWork); 25043 } else { 25044 commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork, finishedWork.return); 25045 } 25046 25047 break; 25048 } 25049 } 25050 } 25051 25052 function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(deletedSubtreeRoot, nearestMountedAncestor) { 25053 while (nextEffect !== null) { 25054 var fiber = nextEffect; // Deletion effects fire in parent -> child order 25055 // TODO: Check if fiber has a PassiveStatic flag 25056 25057 setCurrentFiber(fiber); 25058 commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor); 25059 resetCurrentFiber(); 25060 var child = fiber.child; // TODO: Only traverse subtree if it has a PassiveStatic flag. (But, if we 25061 // do this, still need to handle `deletedTreeCleanUpLevel` correctly.) 25062 25063 if (child !== null) { 25064 child.return = fiber; 25065 nextEffect = child; 25066 } else { 25067 commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot); 25068 } 25069 } 25070 } 25071 25072 function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot) { 25073 while (nextEffect !== null) { 25074 var fiber = nextEffect; 25075 var sibling = fiber.sibling; 25076 var returnFiber = fiber.return; 25077 25078 { 25079 // Recursively traverse the entire deleted tree and clean up fiber fields. 25080 // This is more aggressive than ideal, and the long term goal is to only 25081 // have to detach the deleted tree at the root. 25082 detachFiberAfterEffects(fiber); 25083 25084 if (fiber === deletedSubtreeRoot) { 25085 nextEffect = null; 25086 return; 25087 } 25088 } 25089 25090 if (sibling !== null) { 25091 sibling.return = returnFiber; 25092 nextEffect = sibling; 25093 return; 25094 } 25095 25096 nextEffect = returnFiber; 25097 } 25098 } 25099 25100 function commitPassiveUnmountInsideDeletedTreeOnFiber(current, nearestMountedAncestor) { 25101 switch (current.tag) { 25102 case FunctionComponent: 25103 case ForwardRef: 25104 case SimpleMemoComponent: 25105 { 25106 if ( current.mode & ProfileMode) { 25107 startPassiveEffectTimer(); 25108 commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); 25109 recordPassiveEffectDuration(current); 25110 } else { 25111 commitHookEffectListUnmount(Passive$1, current, nearestMountedAncestor); 25112 } 25113 25114 break; 25115 } 25116 } 25117 } // TODO: Reuse reappearLayoutEffects traversal here? 25118 25119 25120 function invokeLayoutEffectMountInDEV(fiber) { 25121 { 25122 // We don't need to re-check StrictEffectsMode here. 25123 // This function is only called if that check has already passed. 25124 switch (fiber.tag) { 25125 case FunctionComponent: 25126 case ForwardRef: 25127 case SimpleMemoComponent: 25128 { 25129 try { 25130 commitHookEffectListMount(Layout | HasEffect, fiber); 25131 } catch (error) { 25132 captureCommitPhaseError(fiber, fiber.return, error); 25133 } 25134 25135 break; 25136 } 25137 25138 case ClassComponent: 25139 { 25140 var instance = fiber.stateNode; 25141 25142 try { 25143 instance.componentDidMount(); 25144 } catch (error) { 25145 captureCommitPhaseError(fiber, fiber.return, error); 25146 } 25147 25148 break; 25149 } 25150 } 25151 } 25152 } 25153 25154 function invokePassiveEffectMountInDEV(fiber) { 25155 { 25156 // We don't need to re-check StrictEffectsMode here. 25157 // This function is only called if that check has already passed. 25158 switch (fiber.tag) { 25159 case FunctionComponent: 25160 case ForwardRef: 25161 case SimpleMemoComponent: 25162 { 25163 try { 25164 commitHookEffectListMount(Passive$1 | HasEffect, fiber); 25165 } catch (error) { 25166 captureCommitPhaseError(fiber, fiber.return, error); 25167 } 25168 25169 break; 25170 } 25171 } 25172 } 25173 } 25174 25175 function invokeLayoutEffectUnmountInDEV(fiber) { 25176 { 25177 // We don't need to re-check StrictEffectsMode here. 25178 // This function is only called if that check has already passed. 25179 switch (fiber.tag) { 25180 case FunctionComponent: 25181 case ForwardRef: 25182 case SimpleMemoComponent: 25183 { 25184 try { 25185 commitHookEffectListUnmount(Layout | HasEffect, fiber, fiber.return); 25186 } catch (error) { 25187 captureCommitPhaseError(fiber, fiber.return, error); 25188 } 25189 25190 break; 25191 } 25192 25193 case ClassComponent: 25194 { 25195 var instance = fiber.stateNode; 25196 25197 if (typeof instance.componentWillUnmount === 'function') { 25198 safelyCallComponentWillUnmount(fiber, fiber.return, instance); 25199 } 25200 25201 break; 25202 } 25203 } 25204 } 25205 } 25206 25207 function invokePassiveEffectUnmountInDEV(fiber) { 25208 { 25209 // We don't need to re-check StrictEffectsMode here. 25210 // This function is only called if that check has already passed. 25211 switch (fiber.tag) { 25212 case FunctionComponent: 25213 case ForwardRef: 25214 case SimpleMemoComponent: 25215 { 25216 try { 25217 commitHookEffectListUnmount(Passive$1 | HasEffect, fiber, fiber.return); 25218 } catch (error) { 25219 captureCommitPhaseError(fiber, fiber.return, error); 25220 } 25221 } 25222 } 25223 } 25224 } 25225 25226 var COMPONENT_TYPE = 0; 25227 var HAS_PSEUDO_CLASS_TYPE = 1; 25228 var ROLE_TYPE = 2; 25229 var TEST_NAME_TYPE = 3; 25230 var TEXT_TYPE = 4; 25231 25232 if (typeof Symbol === 'function' && Symbol.for) { 25233 var symbolFor = Symbol.for; 25234 COMPONENT_TYPE = symbolFor('selector.component'); 25235 HAS_PSEUDO_CLASS_TYPE = symbolFor('selector.has_pseudo_class'); 25236 ROLE_TYPE = symbolFor('selector.role'); 25237 TEST_NAME_TYPE = symbolFor('selector.test_id'); 25238 TEXT_TYPE = symbolFor('selector.text'); 25239 } 25240 var commitHooks = []; 25241 function onCommitRoot$1() { 25242 { 25243 commitHooks.forEach(function (commitHook) { 25244 return commitHook(); 25245 }); 25246 } 25247 } 25248 25249 var ReactCurrentActQueue = ReactSharedInternals.ReactCurrentActQueue; 25250 function isLegacyActEnvironment(fiber) { 25251 { 25252 // Legacy mode. We preserve the behavior of React 17's act. It assumes an 25253 // act environment whenever `jest` is defined, but you can still turn off 25254 // spurious warnings by setting IS_REACT_ACT_ENVIRONMENT explicitly 25255 // to false. 25256 var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global 25257 typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined' ? IS_REACT_ACT_ENVIRONMENT : undefined; // $FlowExpectedError - Flow doesn't know about jest 25258 25259 var jestIsDefined = typeof jest !== 'undefined'; 25260 return jestIsDefined && isReactActEnvironmentGlobal !== false; 25261 } 25262 } 25263 function isConcurrentActEnvironment() { 25264 { 25265 var isReactActEnvironmentGlobal = // $FlowExpectedError – Flow doesn't know about IS_REACT_ACT_ENVIRONMENT global 25266 typeof IS_REACT_ACT_ENVIRONMENT !== 'undefined' ? IS_REACT_ACT_ENVIRONMENT : undefined; 25267 25268 if (!isReactActEnvironmentGlobal && ReactCurrentActQueue.current !== null) { 25269 // TODO: Include link to relevant documentation page. 25270 error('The current testing environment is not configured to support ' + 'act(...)'); 25271 } 25272 25273 return isReactActEnvironmentGlobal; 25274 } 25275 } 25276 25277 var ceil = Math.ceil; 25278 var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher, 25279 ReactCurrentOwner$2 = ReactSharedInternals.ReactCurrentOwner, 25280 ReactCurrentBatchConfig$3 = ReactSharedInternals.ReactCurrentBatchConfig, 25281 ReactCurrentActQueue$1 = ReactSharedInternals.ReactCurrentActQueue; 25282 var NoContext = 25283 /* */ 25284 0; 25285 var BatchedContext = 25286 /* */ 25287 1; 25288 var RenderContext = 25289 /* */ 25290 2; 25291 var CommitContext = 25292 /* */ 25293 4; 25294 var RootInProgress = 0; 25295 var RootFatalErrored = 1; 25296 var RootErrored = 2; 25297 var RootSuspended = 3; 25298 var RootSuspendedWithDelay = 4; 25299 var RootCompleted = 5; 25300 var RootDidNotComplete = 6; // Describes where we are in the React execution stack 25301 25302 var executionContext = NoContext; // The root we're working on 25303 25304 var workInProgressRoot = null; // The fiber we're working on 25305 25306 var workInProgress = null; // The lanes we're rendering 25307 25308 var workInProgressRootRenderLanes = NoLanes; // Stack that allows components to change the render lanes for its subtree 25309 // This is a superset of the lanes we started working on at the root. The only 25310 // case where it's different from `workInProgressRootRenderLanes` is when we 25311 // enter a subtree that is hidden and needs to be unhidden: Suspense and 25312 // Offscreen component. 25313 // 25314 // Most things in the work loop should deal with workInProgressRootRenderLanes. 25315 // Most things in begin/complete phases should deal with subtreeRenderLanes. 25316 25317 var subtreeRenderLanes = NoLanes; 25318 var subtreeRenderLanesCursor = createCursor(NoLanes); // Whether to root completed, errored, suspended, etc. 25319 25320 var workInProgressRootExitStatus = RootInProgress; // A fatal error, if one is thrown 25321 25322 var workInProgressRootFatalError = null; // "Included" lanes refer to lanes that were worked on during this render. It's 25323 // slightly different than `renderLanes` because `renderLanes` can change as you 25324 // enter and exit an Offscreen tree. This value is the combination of all render 25325 // lanes for the entire render phase. 25326 25327 var workInProgressRootIncludedLanes = NoLanes; // The work left over by components that were visited during this render. Only 25328 // includes unprocessed updates, not work in bailed out children. 25329 25330 var workInProgressRootSkippedLanes = NoLanes; // Lanes that were updated (in an interleaved event) during this render. 25331 25332 var workInProgressRootInterleavedUpdatedLanes = NoLanes; // Lanes that were updated during the render phase (*not* an interleaved event). 25333 25334 var workInProgressRootPingedLanes = NoLanes; // Errors that are thrown during the render phase. 25335 25336 var workInProgressRootConcurrentErrors = null; // These are errors that we recovered from without surfacing them to the UI. 25337 // We will log them once the tree commits. 25338 25339 var workInProgressRootRecoverableErrors = null; // The most recent time we committed a fallback. This lets us ensure a train 25340 // model where we don't commit new loading states in too quick succession. 25341 25342 var globalMostRecentFallbackTime = 0; 25343 var FALLBACK_THROTTLE_MS = 500; // The absolute time for when we should start giving up on rendering 25344 // more and prefer CPU suspense heuristics instead. 25345 25346 var workInProgressRootRenderTargetTime = Infinity; // How long a render is supposed to take before we start following CPU 25347 // suspense heuristics and opt out of rendering more content. 25348 25349 var RENDER_TIMEOUT_MS = 500; 25350 var workInProgressTransitions = null; 25351 25352 function resetRenderTimer() { 25353 workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS; 25354 } 25355 25356 function getRenderTargetTime() { 25357 return workInProgressRootRenderTargetTime; 25358 } 25359 var hasUncaughtError = false; 25360 var firstUncaughtError = null; 25361 var legacyErrorBoundariesThatAlreadyFailed = null; // Only used when enableProfilerNestedUpdateScheduledHook is true; 25362 var rootDoesHavePassiveEffects = false; 25363 var rootWithPendingPassiveEffects = null; 25364 var pendingPassiveEffectsLanes = NoLanes; 25365 var pendingPassiveProfilerEffects = []; 25366 var pendingPassiveTransitions = null; // Use these to prevent an infinite loop of nested updates 25367 25368 var NESTED_UPDATE_LIMIT = 50; 25369 var nestedUpdateCount = 0; 25370 var rootWithNestedUpdates = null; 25371 var isFlushingPassiveEffects = false; 25372 var didScheduleUpdateDuringPassiveEffects = false; 25373 var NESTED_PASSIVE_UPDATE_LIMIT = 50; 25374 var nestedPassiveUpdateCount = 0; 25375 var rootWithPassiveNestedUpdates = null; // If two updates are scheduled within the same event, we should treat their 25376 // event times as simultaneous, even if the actual clock time has advanced 25377 // between the first and second call. 25378 25379 var currentEventTime = NoTimestamp; 25380 var currentEventTransitionLane = NoLanes; 25381 var isRunningInsertionEffect = false; 25382 function getWorkInProgressRoot() { 25383 return workInProgressRoot; 25384 } 25385 function requestEventTime() { 25386 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 25387 // We're inside React, so it's fine to read the actual time. 25388 return now(); 25389 } // We're not inside React, so we may be in the middle of a browser event. 25390 25391 25392 if (currentEventTime !== NoTimestamp) { 25393 // Use the same start time for all updates until we enter React again. 25394 return currentEventTime; 25395 } // This is the first update since React yielded. Compute a new start time. 25396 25397 25398 currentEventTime = now(); 25399 return currentEventTime; 25400 } 25401 function requestUpdateLane(fiber) { 25402 // Special cases 25403 var mode = fiber.mode; 25404 25405 if ((mode & ConcurrentMode) === NoMode) { 25406 return SyncLane; 25407 } else if ( (executionContext & RenderContext) !== NoContext && workInProgressRootRenderLanes !== NoLanes) { 25408 // This is a render phase update. These are not officially supported. The 25409 // old behavior is to give this the same "thread" (lanes) as 25410 // whatever is currently rendering. So if you call `setState` on a component 25411 // that happens later in the same render, it will flush. Ideally, we want to 25412 // remove the special case and treat them as if they came from an 25413 // interleaved event. Regardless, this pattern is not officially supported. 25414 // This behavior is only a fallback. The flag only exists until we can roll 25415 // out the setState warning, since existing code might accidentally rely on 25416 // the current behavior. 25417 return pickArbitraryLane(workInProgressRootRenderLanes); 25418 } 25419 25420 var isTransition = requestCurrentTransition() !== NoTransition; 25421 25422 if (isTransition) { 25423 if ( ReactCurrentBatchConfig$3.transition !== null) { 25424 var transition = ReactCurrentBatchConfig$3.transition; 25425 25426 if (!transition._updatedFibers) { 25427 transition._updatedFibers = new Set(); 25428 } 25429 25430 transition._updatedFibers.add(fiber); 25431 } // The algorithm for assigning an update to a lane should be stable for all 25432 // updates at the same priority within the same event. To do this, the 25433 // inputs to the algorithm must be the same. 25434 // 25435 // The trick we use is to cache the first of each of these inputs within an 25436 // event. Then reset the cached values once we can be sure the event is 25437 // over. Our heuristic for that is whenever we enter a concurrent work loop. 25438 25439 25440 if (currentEventTransitionLane === NoLane) { 25441 // All transitions within the same event are assigned the same lane. 25442 currentEventTransitionLane = claimNextTransitionLane(); 25443 } 25444 25445 return currentEventTransitionLane; 25446 } // Updates originating inside certain React methods, like flushSync, have 25447 // their priority set by tracking it with a context variable. 25448 // 25449 // The opaque type returned by the host config is internally a lane, so we can 25450 // use that directly. 25451 // TODO: Move this type conversion to the event priority module. 25452 25453 25454 var updateLane = getCurrentUpdatePriority(); 25455 25456 if (updateLane !== NoLane) { 25457 return updateLane; 25458 } // This update originated outside React. Ask the host environment for an 25459 // appropriate priority, based on the type of event. 25460 // 25461 // The opaque type returned by the host config is internally a lane, so we can 25462 // use that directly. 25463 // TODO: Move this type conversion to the event priority module. 25464 25465 25466 var eventLane = getCurrentEventPriority(); 25467 return eventLane; 25468 } 25469 25470 function requestRetryLane(fiber) { 25471 // This is a fork of `requestUpdateLane` designed specifically for Suspense 25472 // "retries" — a special update that attempts to flip a Suspense boundary 25473 // from its placeholder state to its primary/resolved state. 25474 // Special cases 25475 var mode = fiber.mode; 25476 25477 if ((mode & ConcurrentMode) === NoMode) { 25478 return SyncLane; 25479 } 25480 25481 return claimNextRetryLane(); 25482 } 25483 25484 function scheduleUpdateOnFiber(root, fiber, lane, eventTime) { 25485 checkForNestedUpdates(); 25486 25487 { 25488 if (isRunningInsertionEffect) { 25489 error('useInsertionEffect must not schedule updates.'); 25490 } 25491 } 25492 25493 { 25494 if (isFlushingPassiveEffects) { 25495 didScheduleUpdateDuringPassiveEffects = true; 25496 } 25497 } // Mark that the root has a pending update. 25498 25499 25500 markRootUpdated(root, lane, eventTime); 25501 25502 if ((executionContext & RenderContext) !== NoLanes && root === workInProgressRoot) { 25503 // This update was dispatched during the render phase. This is a mistake 25504 // if the update originates from user space (with the exception of local 25505 // hook updates, which are handled differently and don't reach this 25506 // function), but there are some internal React features that use this as 25507 // an implementation detail, like selective hydration. 25508 warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase 25509 } else { 25510 // This is a normal update, scheduled from outside the render phase. For 25511 // example, during an input event. 25512 { 25513 if (isDevToolsPresent) { 25514 addFiberToLanesMap(root, fiber, lane); 25515 } 25516 } 25517 25518 warnIfUpdatesNotWrappedWithActDEV(fiber); 25519 25520 if (root === workInProgressRoot) { 25521 // Received an update to a tree that's in the middle of rendering. Mark 25522 // that there was an interleaved update work on this root. Unless the 25523 // `deferRenderPhaseUpdateToNextBatch` flag is off and this is a render 25524 // phase update. In that case, we don't treat render phase updates as if 25525 // they were interleaved, for backwards compat reasons. 25526 if ( (executionContext & RenderContext) === NoContext) { 25527 workInProgressRootInterleavedUpdatedLanes = mergeLanes(workInProgressRootInterleavedUpdatedLanes, lane); 25528 } 25529 25530 if (workInProgressRootExitStatus === RootSuspendedWithDelay) { 25531 // The root already suspended with a delay, which means this render 25532 // definitely won't finish. Since we have a new update, let's mark it as 25533 // suspended now, right before marking the incoming update. This has the 25534 // effect of interrupting the current render and switching to the update. 25535 // TODO: Make sure this doesn't override pings that happen while we've 25536 // already started rendering. 25537 markRootSuspended$1(root, workInProgressRootRenderLanes); 25538 } 25539 } 25540 25541 ensureRootIsScheduled(root, eventTime); 25542 25543 if (lane === SyncLane && executionContext === NoContext && (fiber.mode & ConcurrentMode) === NoMode && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. 25544 !( ReactCurrentActQueue$1.isBatchingLegacy)) { 25545 // Flush the synchronous work now, unless we're already working or inside 25546 // a batch. This is intentionally inside scheduleUpdateOnFiber instead of 25547 // scheduleCallbackForFiber to preserve the ability to schedule a callback 25548 // without immediately flushing it. We only do this for user-initiated 25549 // updates, to preserve historical behavior of legacy mode. 25550 resetRenderTimer(); 25551 flushSyncCallbacksOnlyInLegacyMode(); 25552 } 25553 } 25554 } 25555 function scheduleInitialHydrationOnRoot(root, lane, eventTime) { 25556 // This is a special fork of scheduleUpdateOnFiber that is only used to 25557 // schedule the initial hydration of a root that has just been created. Most 25558 // of the stuff in scheduleUpdateOnFiber can be skipped. 25559 // 25560 // The main reason for this separate path, though, is to distinguish the 25561 // initial children from subsequent updates. In fully client-rendered roots 25562 // (createRoot instead of hydrateRoot), all top-level renders are modeled as 25563 // updates, but hydration roots are special because the initial render must 25564 // match what was rendered on the server. 25565 var current = root.current; 25566 current.lanes = lane; 25567 markRootUpdated(root, lane, eventTime); 25568 ensureRootIsScheduled(root, eventTime); 25569 } 25570 function isUnsafeClassRenderPhaseUpdate(fiber) { 25571 // Check if this is a render phase update. Only called by class components, 25572 // which special (deprecated) behavior for UNSAFE_componentWillReceive props. 25573 return (// TODO: Remove outdated deferRenderPhaseUpdateToNextBatch experiment. We 25574 // decided not to enable it. 25575 (executionContext & RenderContext) !== NoContext 25576 ); 25577 } // Use this function to schedule a task for a root. There's only one task per 25578 // root; if a task was already scheduled, we'll check to make sure the priority 25579 // of the existing task is the same as the priority of the next level that the 25580 // root has work on. This function is called on every update, and right before 25581 // exiting a task. 25582 25583 function ensureRootIsScheduled(root, currentTime) { 25584 var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as 25585 // expired so we know to work on those next. 25586 25587 markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. 25588 25589 var nextLanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes); 25590 25591 if (nextLanes === NoLanes) { 25592 // Special case: There's nothing to work on. 25593 if (existingCallbackNode !== null) { 25594 cancelCallback$1(existingCallbackNode); 25595 } 25596 25597 root.callbackNode = null; 25598 root.callbackPriority = NoLane; 25599 return; 25600 } // We use the highest priority lane to represent the priority of the callback. 25601 25602 25603 var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. 25604 25605 var existingCallbackPriority = root.callbackPriority; 25606 25607 if (existingCallbackPriority === newCallbackPriority && // Special case related to `act`. If the currently scheduled task is a 25608 // Scheduler task, rather than an `act` task, cancel it and re-scheduled 25609 // on the `act` queue. 25610 !( ReactCurrentActQueue$1.current !== null && existingCallbackNode !== fakeActCallbackNode)) { 25611 { 25612 // If we're going to re-use an existing task, it needs to exist. 25613 // Assume that discrete update microtasks are non-cancellable and null. 25614 // TODO: Temporary until we confirm this warning is not fired. 25615 if (existingCallbackNode == null && existingCallbackPriority !== SyncLane) { 25616 error('Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.'); 25617 } 25618 } // The priority hasn't changed. We can reuse the existing task. Exit. 25619 25620 25621 return; 25622 } 25623 25624 if (existingCallbackNode != null) { 25625 // Cancel the existing callback. We'll schedule a new one below. 25626 cancelCallback$1(existingCallbackNode); 25627 } // Schedule a new callback. 25628 25629 25630 var newCallbackNode; 25631 25632 if (newCallbackPriority === SyncLane) { 25633 // Special case: Sync React callbacks are scheduled on a special 25634 // internal queue 25635 if (root.tag === LegacyRoot) { 25636 if ( ReactCurrentActQueue$1.isBatchingLegacy !== null) { 25637 ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; 25638 } 25639 25640 scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); 25641 } else { 25642 scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); 25643 } 25644 25645 { 25646 // Flush the queue in a microtask. 25647 if ( ReactCurrentActQueue$1.current !== null) { 25648 // Inside `act`, use our internal `act` queue so that these get flushed 25649 // at the end of the current scope even when using the sync version 25650 // of `act`. 25651 ReactCurrentActQueue$1.current.push(flushSyncCallbacks); 25652 } else { 25653 scheduleMicrotask(function () { 25654 // In Safari, appending an iframe forces microtasks to run. 25655 // https://github.com/facebook/react/issues/22459 25656 // We don't support running callbacks in the middle of render 25657 // or commit so we need to check against that. 25658 if ((executionContext & (RenderContext | CommitContext)) === NoContext) { 25659 // Note that this would still prematurely flush the callbacks 25660 // if this happens outside render or commit phase (e.g. in an event). 25661 flushSyncCallbacks(); 25662 } 25663 }); 25664 } 25665 } 25666 25667 newCallbackNode = null; 25668 } else { 25669 var schedulerPriorityLevel; 25670 25671 switch (lanesToEventPriority(nextLanes)) { 25672 case DiscreteEventPriority: 25673 schedulerPriorityLevel = ImmediatePriority; 25674 break; 25675 25676 case ContinuousEventPriority: 25677 schedulerPriorityLevel = UserBlockingPriority; 25678 break; 25679 25680 case DefaultEventPriority: 25681 schedulerPriorityLevel = NormalPriority; 25682 break; 25683 25684 case IdleEventPriority: 25685 schedulerPriorityLevel = IdlePriority; 25686 break; 25687 25688 default: 25689 schedulerPriorityLevel = NormalPriority; 25690 break; 25691 } 25692 25693 newCallbackNode = scheduleCallback$1(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root)); 25694 } 25695 25696 root.callbackPriority = newCallbackPriority; 25697 root.callbackNode = newCallbackNode; 25698 } // This is the entry point for every concurrent task, i.e. anything that 25699 // goes through Scheduler. 25700 25701 25702 function performConcurrentWorkOnRoot(root, didTimeout) { 25703 { 25704 resetNestedUpdateFlag(); 25705 } // Since we know we're in a React event, we can clear the current 25706 // event time. The next update will compute a new event time. 25707 25708 25709 currentEventTime = NoTimestamp; 25710 currentEventTransitionLane = NoLanes; 25711 25712 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 25713 throw new Error('Should not already be working.'); 25714 } // Flush any pending passive effects before deciding which lanes to work on, 25715 // in case they schedule additional work. 25716 25717 25718 var originalCallbackNode = root.callbackNode; 25719 var didFlushPassiveEffects = flushPassiveEffects(); 25720 25721 if (didFlushPassiveEffects) { 25722 // Something in the passive effect phase may have canceled the current task. 25723 // Check if the task node for this root was changed. 25724 if (root.callbackNode !== originalCallbackNode) { 25725 // The current task was canceled. Exit. We don't need to call 25726 // `ensureRootIsScheduled` because the check above implies either that 25727 // there's a new task, or that there's no remaining work on this root. 25728 return null; 25729 } 25730 } // Determine the next lanes to work on, using the fields stored 25731 // on the root. 25732 25733 25734 var lanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes); 25735 25736 if (lanes === NoLanes) { 25737 // Defensive coding. This is never expected to happen. 25738 return null; 25739 } // We disable time-slicing in some cases: if the work has been CPU-bound 25740 // for too long ("expired" work, to prevent starvation), or we're in 25741 // sync-updates-by-default mode. 25742 // TODO: We only check `didTimeout` defensively, to account for a Scheduler 25743 // bug we're still investigating. Once the bug in Scheduler is fixed, 25744 // we can remove this, since we track expiration ourselves. 25745 25746 25747 var shouldTimeSlice = !includesBlockingLane(root, lanes) && !includesExpiredLane(root, lanes) && ( !didTimeout); 25748 var exitStatus = shouldTimeSlice ? renderRootConcurrent(root, lanes) : renderRootSync(root, lanes); 25749 25750 if (exitStatus !== RootInProgress) { 25751 if (exitStatus === RootErrored) { 25752 // If something threw an error, try rendering one more time. We'll 25753 // render synchronously to block concurrent data mutations, and we'll 25754 // includes all pending updates are included. If it still fails after 25755 // the second attempt, we'll give up and commit the resulting tree. 25756 var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); 25757 25758 if (errorRetryLanes !== NoLanes) { 25759 lanes = errorRetryLanes; 25760 exitStatus = recoverFromConcurrentError(root, errorRetryLanes); 25761 } 25762 } 25763 25764 if (exitStatus === RootFatalErrored) { 25765 var fatalError = workInProgressRootFatalError; 25766 prepareFreshStack(root, NoLanes); 25767 markRootSuspended$1(root, lanes); 25768 ensureRootIsScheduled(root, now()); 25769 throw fatalError; 25770 } 25771 25772 if (exitStatus === RootDidNotComplete) { 25773 // The render unwound without completing the tree. This happens in special 25774 // cases where need to exit the current render without producing a 25775 // consistent tree or committing. 25776 // 25777 // This should only happen during a concurrent render, not a discrete or 25778 // synchronous update. We should have already checked for this when we 25779 // unwound the stack. 25780 markRootSuspended$1(root, lanes); 25781 } else { 25782 // The render completed. 25783 // Check if this render may have yielded to a concurrent event, and if so, 25784 // confirm that any newly rendered stores are consistent. 25785 // TODO: It's possible that even a concurrent render may never have yielded 25786 // to the main thread, if it was fast enough, or if it expired. We could 25787 // skip the consistency check in that case, too. 25788 var renderWasConcurrent = !includesBlockingLane(root, lanes); 25789 var finishedWork = root.current.alternate; 25790 25791 if (renderWasConcurrent && !isRenderConsistentWithExternalStores(finishedWork)) { 25792 // A store was mutated in an interleaved event. Render again, 25793 // synchronously, to block further mutations. 25794 exitStatus = renderRootSync(root, lanes); // We need to check again if something threw 25795 25796 if (exitStatus === RootErrored) { 25797 var _errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); 25798 25799 if (_errorRetryLanes !== NoLanes) { 25800 lanes = _errorRetryLanes; 25801 exitStatus = recoverFromConcurrentError(root, _errorRetryLanes); // We assume the tree is now consistent because we didn't yield to any 25802 // concurrent events. 25803 } 25804 } 25805 25806 if (exitStatus === RootFatalErrored) { 25807 var _fatalError = workInProgressRootFatalError; 25808 prepareFreshStack(root, NoLanes); 25809 markRootSuspended$1(root, lanes); 25810 ensureRootIsScheduled(root, now()); 25811 throw _fatalError; 25812 } 25813 } // We now have a consistent tree. The next step is either to commit it, 25814 // or, if something suspended, wait to commit it after a timeout. 25815 25816 25817 root.finishedWork = finishedWork; 25818 root.finishedLanes = lanes; 25819 finishConcurrentRender(root, exitStatus, lanes); 25820 } 25821 } 25822 25823 ensureRootIsScheduled(root, now()); 25824 25825 if (root.callbackNode === originalCallbackNode) { 25826 // The task node scheduled for this root is the same one that's 25827 // currently executed. Need to return a continuation. 25828 return performConcurrentWorkOnRoot.bind(null, root); 25829 } 25830 25831 return null; 25832 } 25833 25834 function recoverFromConcurrentError(root, errorRetryLanes) { 25835 // If an error occurred during hydration, discard server response and fall 25836 // back to client side render. 25837 // Before rendering again, save the errors from the previous attempt. 25838 var errorsFromFirstAttempt = workInProgressRootConcurrentErrors; 25839 25840 if (isRootDehydrated(root)) { 25841 // The shell failed to hydrate. Set a flag to force a client rendering 25842 // during the next attempt. To do this, we call prepareFreshStack now 25843 // to create the root work-in-progress fiber. This is a bit weird in terms 25844 // of factoring, because it relies on renderRootSync not calling 25845 // prepareFreshStack again in the call below, which happens because the 25846 // root and lanes haven't changed. 25847 // 25848 // TODO: I think what we should do is set ForceClientRender inside 25849 // throwException, like we do for nested Suspense boundaries. The reason 25850 // it's here instead is so we can switch to the synchronous work loop, too. 25851 // Something to consider for a future refactor. 25852 var rootWorkInProgress = prepareFreshStack(root, errorRetryLanes); 25853 rootWorkInProgress.flags |= ForceClientRender; 25854 25855 { 25856 errorHydratingContainer(root.containerInfo); 25857 } 25858 } 25859 25860 var exitStatus = renderRootSync(root, errorRetryLanes); 25861 25862 if (exitStatus !== RootErrored) { 25863 // Successfully finished rendering on retry 25864 // The errors from the failed first attempt have been recovered. Add 25865 // them to the collection of recoverable errors. We'll log them in the 25866 // commit phase. 25867 var errorsFromSecondAttempt = workInProgressRootRecoverableErrors; 25868 workInProgressRootRecoverableErrors = errorsFromFirstAttempt; // The errors from the second attempt should be queued after the errors 25869 // from the first attempt, to preserve the causal sequence. 25870 25871 if (errorsFromSecondAttempt !== null) { 25872 queueRecoverableErrors(errorsFromSecondAttempt); 25873 } 25874 } 25875 25876 return exitStatus; 25877 } 25878 25879 function queueRecoverableErrors(errors) { 25880 if (workInProgressRootRecoverableErrors === null) { 25881 workInProgressRootRecoverableErrors = errors; 25882 } else { 25883 workInProgressRootRecoverableErrors.push.apply(workInProgressRootRecoverableErrors, errors); 25884 } 25885 } 25886 25887 function finishConcurrentRender(root, exitStatus, lanes) { 25888 switch (exitStatus) { 25889 case RootInProgress: 25890 case RootFatalErrored: 25891 { 25892 throw new Error('Root did not complete. This is a bug in React.'); 25893 } 25894 // Flow knows about invariant, so it complains if I add a break 25895 // statement, but eslint doesn't know about invariant, so it complains 25896 // if I do. eslint-disable-next-line no-fallthrough 25897 25898 case RootErrored: 25899 { 25900 // We should have already attempted to retry this tree. If we reached 25901 // this point, it errored again. Commit it. 25902 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); 25903 break; 25904 } 25905 25906 case RootSuspended: 25907 { 25908 markRootSuspended$1(root, lanes); // We have an acceptable loading state. We need to figure out if we 25909 // should immediately commit it or wait a bit. 25910 25911 if (includesOnlyRetries(lanes) && // do not delay if we're inside an act() scope 25912 !shouldForceFlushFallbacksInDEV()) { 25913 // This render only included retries, no updates. Throttle committing 25914 // retries so that we don't show too many loading states too quickly. 25915 var msUntilTimeout = globalMostRecentFallbackTime + FALLBACK_THROTTLE_MS - now(); // Don't bother with a very short suspense time. 25916 25917 if (msUntilTimeout > 10) { 25918 var nextLanes = getNextLanes(root, NoLanes); 25919 25920 if (nextLanes !== NoLanes) { 25921 // There's additional work on this root. 25922 break; 25923 } 25924 25925 var suspendedLanes = root.suspendedLanes; 25926 25927 if (!isSubsetOfLanes(suspendedLanes, lanes)) { 25928 // We should prefer to render the fallback of at the last 25929 // suspended level. Ping the last suspended level to try 25930 // rendering it again. 25931 // FIXME: What if the suspended lanes are Idle? Should not restart. 25932 var eventTime = requestEventTime(); 25933 markRootPinged(root, suspendedLanes); 25934 break; 25935 } // The render is suspended, it hasn't timed out, and there's no 25936 // lower priority work to do. Instead of committing the fallback 25937 // immediately, wait for more data to arrive. 25938 25939 25940 root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root, workInProgressRootRecoverableErrors, workInProgressTransitions), msUntilTimeout); 25941 break; 25942 } 25943 } // The work expired. Commit immediately. 25944 25945 25946 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); 25947 break; 25948 } 25949 25950 case RootSuspendedWithDelay: 25951 { 25952 markRootSuspended$1(root, lanes); 25953 25954 if (includesOnlyTransitions(lanes)) { 25955 // This is a transition, so we should exit without committing a 25956 // placeholder and without scheduling a timeout. Delay indefinitely 25957 // until we receive more data. 25958 break; 25959 } 25960 25961 if (!shouldForceFlushFallbacksInDEV()) { 25962 // This is not a transition, but we did trigger an avoided state. 25963 // Schedule a placeholder to display after a short delay, using the Just 25964 // Noticeable Difference. 25965 // TODO: Is the JND optimization worth the added complexity? If this is 25966 // the only reason we track the event time, then probably not. 25967 // Consider removing. 25968 var mostRecentEventTime = getMostRecentEventTime(root, lanes); 25969 var eventTimeMs = mostRecentEventTime; 25970 var timeElapsedMs = now() - eventTimeMs; 25971 25972 var _msUntilTimeout = jnd(timeElapsedMs) - timeElapsedMs; // Don't bother with a very short suspense time. 25973 25974 25975 if (_msUntilTimeout > 10) { 25976 // Instead of committing the fallback immediately, wait for more data 25977 // to arrive. 25978 root.timeoutHandle = scheduleTimeout(commitRoot.bind(null, root, workInProgressRootRecoverableErrors, workInProgressTransitions), _msUntilTimeout); 25979 break; 25980 } 25981 } // Commit the placeholder. 25982 25983 25984 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); 25985 break; 25986 } 25987 25988 case RootCompleted: 25989 { 25990 // The work completed. Ready to commit. 25991 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); 25992 break; 25993 } 25994 25995 default: 25996 { 25997 throw new Error('Unknown root exit status.'); 25998 } 25999 } 26000 } 26001 26002 function isRenderConsistentWithExternalStores(finishedWork) { 26003 // Search the rendered tree for external store reads, and check whether the 26004 // stores were mutated in a concurrent event. Intentionally using an iterative 26005 // loop instead of recursion so we can exit early. 26006 var node = finishedWork; 26007 26008 while (true) { 26009 if (node.flags & StoreConsistency) { 26010 var updateQueue = node.updateQueue; 26011 26012 if (updateQueue !== null) { 26013 var checks = updateQueue.stores; 26014 26015 if (checks !== null) { 26016 for (var i = 0; i < checks.length; i++) { 26017 var check = checks[i]; 26018 var getSnapshot = check.getSnapshot; 26019 var renderedValue = check.value; 26020 26021 try { 26022 if (!objectIs(getSnapshot(), renderedValue)) { 26023 // Found an inconsistent store. 26024 return false; 26025 } 26026 } catch (error) { 26027 // If `getSnapshot` throws, return `false`. This will schedule 26028 // a re-render, and the error will be rethrown during render. 26029 return false; 26030 } 26031 } 26032 } 26033 } 26034 } 26035 26036 var child = node.child; 26037 26038 if (node.subtreeFlags & StoreConsistency && child !== null) { 26039 child.return = node; 26040 node = child; 26041 continue; 26042 } 26043 26044 if (node === finishedWork) { 26045 return true; 26046 } 26047 26048 while (node.sibling === null) { 26049 if (node.return === null || node.return === finishedWork) { 26050 return true; 26051 } 26052 26053 node = node.return; 26054 } 26055 26056 node.sibling.return = node.return; 26057 node = node.sibling; 26058 } // Flow doesn't know this is unreachable, but eslint does 26059 // eslint-disable-next-line no-unreachable 26060 26061 26062 return true; 26063 } 26064 26065 function markRootSuspended$1(root, suspendedLanes) { 26066 // When suspending, we should always exclude lanes that were pinged or (more 26067 // rarely, since we try to avoid it) updated during the render phase. 26068 // TODO: Lol maybe there's a better way to factor this besides this 26069 // obnoxiously named function :) 26070 suspendedLanes = removeLanes(suspendedLanes, workInProgressRootPingedLanes); 26071 suspendedLanes = removeLanes(suspendedLanes, workInProgressRootInterleavedUpdatedLanes); 26072 markRootSuspended(root, suspendedLanes); 26073 } // This is the entry point for synchronous tasks that don't go 26074 // through Scheduler 26075 26076 26077 function performSyncWorkOnRoot(root) { 26078 { 26079 syncNestedUpdateFlag(); 26080 } 26081 26082 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 26083 throw new Error('Should not already be working.'); 26084 } 26085 26086 flushPassiveEffects(); 26087 var lanes = getNextLanes(root, NoLanes); 26088 26089 if (!includesSomeLane(lanes, SyncLane)) { 26090 // There's no remaining sync work left. 26091 ensureRootIsScheduled(root, now()); 26092 return null; 26093 } 26094 26095 var exitStatus = renderRootSync(root, lanes); 26096 26097 if (root.tag !== LegacyRoot && exitStatus === RootErrored) { 26098 // If something threw an error, try rendering one more time. We'll render 26099 // synchronously to block concurrent data mutations, and we'll includes 26100 // all pending updates are included. If it still fails after the second 26101 // attempt, we'll give up and commit the resulting tree. 26102 var errorRetryLanes = getLanesToRetrySynchronouslyOnError(root); 26103 26104 if (errorRetryLanes !== NoLanes) { 26105 lanes = errorRetryLanes; 26106 exitStatus = recoverFromConcurrentError(root, errorRetryLanes); 26107 } 26108 } 26109 26110 if (exitStatus === RootFatalErrored) { 26111 var fatalError = workInProgressRootFatalError; 26112 prepareFreshStack(root, NoLanes); 26113 markRootSuspended$1(root, lanes); 26114 ensureRootIsScheduled(root, now()); 26115 throw fatalError; 26116 } 26117 26118 if (exitStatus === RootDidNotComplete) { 26119 throw new Error('Root did not complete. This is a bug in React.'); 26120 } // We now have a consistent tree. Because this is a sync render, we 26121 // will commit it even if something suspended. 26122 26123 26124 var finishedWork = root.current.alternate; 26125 root.finishedWork = finishedWork; 26126 root.finishedLanes = lanes; 26127 commitRoot(root, workInProgressRootRecoverableErrors, workInProgressTransitions); // Before exiting, make sure there's a callback scheduled for the next 26128 // pending level. 26129 26130 ensureRootIsScheduled(root, now()); 26131 return null; 26132 } 26133 26134 function flushRoot(root, lanes) { 26135 if (lanes !== NoLanes) { 26136 markRootEntangled(root, mergeLanes(lanes, SyncLane)); 26137 ensureRootIsScheduled(root, now()); 26138 26139 if ((executionContext & (RenderContext | CommitContext)) === NoContext) { 26140 resetRenderTimer(); 26141 flushSyncCallbacks(); 26142 } 26143 } 26144 } 26145 function batchedUpdates$1(fn, a) { 26146 var prevExecutionContext = executionContext; 26147 executionContext |= BatchedContext; 26148 26149 try { 26150 return fn(a); 26151 } finally { 26152 executionContext = prevExecutionContext; // If there were legacy sync updates, flush them at the end of the outer 26153 // most batchedUpdates-like method. 26154 26155 if (executionContext === NoContext && // Treat `act` as if it's inside `batchedUpdates`, even in legacy mode. 26156 !( ReactCurrentActQueue$1.isBatchingLegacy)) { 26157 resetRenderTimer(); 26158 flushSyncCallbacksOnlyInLegacyMode(); 26159 } 26160 } 26161 } 26162 function discreteUpdates(fn, a, b, c, d) { 26163 var previousPriority = getCurrentUpdatePriority(); 26164 var prevTransition = ReactCurrentBatchConfig$3.transition; 26165 26166 try { 26167 ReactCurrentBatchConfig$3.transition = null; 26168 setCurrentUpdatePriority(DiscreteEventPriority); 26169 return fn(a, b, c, d); 26170 } finally { 26171 setCurrentUpdatePriority(previousPriority); 26172 ReactCurrentBatchConfig$3.transition = prevTransition; 26173 26174 if (executionContext === NoContext) { 26175 resetRenderTimer(); 26176 } 26177 } 26178 } // Overload the definition to the two valid signatures. 26179 // Warning, this opts-out of checking the function body. 26180 26181 // eslint-disable-next-line no-redeclare 26182 function flushSync(fn) { 26183 // In legacy mode, we flush pending passive effects at the beginning of the 26184 // next event, not at the end of the previous one. 26185 if (rootWithPendingPassiveEffects !== null && rootWithPendingPassiveEffects.tag === LegacyRoot && (executionContext & (RenderContext | CommitContext)) === NoContext) { 26186 flushPassiveEffects(); 26187 } 26188 26189 var prevExecutionContext = executionContext; 26190 executionContext |= BatchedContext; 26191 var prevTransition = ReactCurrentBatchConfig$3.transition; 26192 var previousPriority = getCurrentUpdatePriority(); 26193 26194 try { 26195 ReactCurrentBatchConfig$3.transition = null; 26196 setCurrentUpdatePriority(DiscreteEventPriority); 26197 26198 if (fn) { 26199 return fn(); 26200 } else { 26201 return undefined; 26202 } 26203 } finally { 26204 setCurrentUpdatePriority(previousPriority); 26205 ReactCurrentBatchConfig$3.transition = prevTransition; 26206 executionContext = prevExecutionContext; // Flush the immediate callbacks that were scheduled during this batch. 26207 // Note that this will happen even if batchedUpdates is higher up 26208 // the stack. 26209 26210 if ((executionContext & (RenderContext | CommitContext)) === NoContext) { 26211 flushSyncCallbacks(); 26212 } 26213 } 26214 } 26215 function isAlreadyRendering() { 26216 // Used by the renderer to print a warning if certain APIs are called from 26217 // the wrong context. 26218 return (executionContext & (RenderContext | CommitContext)) !== NoContext; 26219 } 26220 function pushRenderLanes(fiber, lanes) { 26221 push(subtreeRenderLanesCursor, subtreeRenderLanes, fiber); 26222 subtreeRenderLanes = mergeLanes(subtreeRenderLanes, lanes); 26223 workInProgressRootIncludedLanes = mergeLanes(workInProgressRootIncludedLanes, lanes); 26224 } 26225 function popRenderLanes(fiber) { 26226 subtreeRenderLanes = subtreeRenderLanesCursor.current; 26227 pop(subtreeRenderLanesCursor, fiber); 26228 } 26229 26230 function prepareFreshStack(root, lanes) { 26231 root.finishedWork = null; 26232 root.finishedLanes = NoLanes; 26233 var timeoutHandle = root.timeoutHandle; 26234 26235 if (timeoutHandle !== noTimeout) { 26236 // The root previous suspended and scheduled a timeout to commit a fallback 26237 // state. Now that we have additional work, cancel the timeout. 26238 root.timeoutHandle = noTimeout; // $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above 26239 26240 cancelTimeout(timeoutHandle); 26241 } 26242 26243 if (workInProgress !== null) { 26244 var interruptedWork = workInProgress.return; 26245 26246 while (interruptedWork !== null) { 26247 var current = interruptedWork.alternate; 26248 unwindInterruptedWork(current, interruptedWork); 26249 interruptedWork = interruptedWork.return; 26250 } 26251 } 26252 26253 workInProgressRoot = root; 26254 var rootWorkInProgress = createWorkInProgress(root.current, null); 26255 workInProgress = rootWorkInProgress; 26256 workInProgressRootRenderLanes = subtreeRenderLanes = workInProgressRootIncludedLanes = lanes; 26257 workInProgressRootExitStatus = RootInProgress; 26258 workInProgressRootFatalError = null; 26259 workInProgressRootSkippedLanes = NoLanes; 26260 workInProgressRootInterleavedUpdatedLanes = NoLanes; 26261 workInProgressRootPingedLanes = NoLanes; 26262 workInProgressRootConcurrentErrors = null; 26263 workInProgressRootRecoverableErrors = null; 26264 finishQueueingConcurrentUpdates(); 26265 26266 { 26267 ReactStrictModeWarnings.discardPendingWarnings(); 26268 } 26269 26270 return rootWorkInProgress; 26271 } 26272 26273 function handleError(root, thrownValue) { 26274 do { 26275 var erroredWork = workInProgress; 26276 26277 try { 26278 // Reset module-level state that was set during the render phase. 26279 resetContextDependencies(); 26280 resetHooksAfterThrow(); 26281 resetCurrentFiber(); // TODO: I found and added this missing line while investigating a 26282 // separate issue. Write a regression test using string refs. 26283 26284 ReactCurrentOwner$2.current = null; 26285 26286 if (erroredWork === null || erroredWork.return === null) { 26287 // Expected to be working on a non-root fiber. This is a fatal error 26288 // because there's no ancestor that can handle it; the root is 26289 // supposed to capture all errors that weren't caught by an error 26290 // boundary. 26291 workInProgressRootExitStatus = RootFatalErrored; 26292 workInProgressRootFatalError = thrownValue; // Set `workInProgress` to null. This represents advancing to the next 26293 // sibling, or the parent if there are no siblings. But since the root 26294 // has no siblings nor a parent, we set it to null. Usually this is 26295 // handled by `completeUnitOfWork` or `unwindWork`, but since we're 26296 // intentionally not calling those, we need set it here. 26297 // TODO: Consider calling `unwindWork` to pop the contexts. 26298 26299 workInProgress = null; 26300 return; 26301 } 26302 26303 if (enableProfilerTimer && erroredWork.mode & ProfileMode) { 26304 // Record the time spent rendering before an error was thrown. This 26305 // avoids inaccurate Profiler durations in the case of a 26306 // suspended render. 26307 stopProfilerTimerIfRunningAndRecordDelta(erroredWork, true); 26308 } 26309 26310 if (enableSchedulingProfiler) { 26311 markComponentRenderStopped(); 26312 26313 if (thrownValue !== null && typeof thrownValue === 'object' && typeof thrownValue.then === 'function') { 26314 var wakeable = thrownValue; 26315 markComponentSuspended(erroredWork, wakeable, workInProgressRootRenderLanes); 26316 } else { 26317 markComponentErrored(erroredWork, thrownValue, workInProgressRootRenderLanes); 26318 } 26319 } 26320 26321 throwException(root, erroredWork.return, erroredWork, thrownValue, workInProgressRootRenderLanes); 26322 completeUnitOfWork(erroredWork); 26323 } catch (yetAnotherThrownValue) { 26324 // Something in the return path also threw. 26325 thrownValue = yetAnotherThrownValue; 26326 26327 if (workInProgress === erroredWork && erroredWork !== null) { 26328 // If this boundary has already errored, then we had trouble processing 26329 // the error. Bubble it to the next boundary. 26330 erroredWork = erroredWork.return; 26331 workInProgress = erroredWork; 26332 } else { 26333 erroredWork = workInProgress; 26334 } 26335 26336 continue; 26337 } // Return to the normal work loop. 26338 26339 26340 return; 26341 } while (true); 26342 } 26343 26344 function pushDispatcher() { 26345 var prevDispatcher = ReactCurrentDispatcher$2.current; 26346 ReactCurrentDispatcher$2.current = ContextOnlyDispatcher; 26347 26348 if (prevDispatcher === null) { 26349 // The React isomorphic package does not include a default dispatcher. 26350 // Instead the first renderer will lazily attach one, in order to give 26351 // nicer error messages. 26352 return ContextOnlyDispatcher; 26353 } else { 26354 return prevDispatcher; 26355 } 26356 } 26357 26358 function popDispatcher(prevDispatcher) { 26359 ReactCurrentDispatcher$2.current = prevDispatcher; 26360 } 26361 26362 function markCommitTimeOfFallback() { 26363 globalMostRecentFallbackTime = now(); 26364 } 26365 function markSkippedUpdateLanes(lane) { 26366 workInProgressRootSkippedLanes = mergeLanes(lane, workInProgressRootSkippedLanes); 26367 } 26368 function renderDidSuspend() { 26369 if (workInProgressRootExitStatus === RootInProgress) { 26370 workInProgressRootExitStatus = RootSuspended; 26371 } 26372 } 26373 function renderDidSuspendDelayIfPossible() { 26374 if (workInProgressRootExitStatus === RootInProgress || workInProgressRootExitStatus === RootSuspended || workInProgressRootExitStatus === RootErrored) { 26375 workInProgressRootExitStatus = RootSuspendedWithDelay; 26376 } // Check if there are updates that we skipped tree that might have unblocked 26377 // this render. 26378 26379 26380 if (workInProgressRoot !== null && (includesNonIdleWork(workInProgressRootSkippedLanes) || includesNonIdleWork(workInProgressRootInterleavedUpdatedLanes))) { 26381 // Mark the current render as suspended so that we switch to working on 26382 // the updates that were skipped. Usually we only suspend at the end of 26383 // the render phase. 26384 // TODO: We should probably always mark the root as suspended immediately 26385 // (inside this function), since by suspending at the end of the render 26386 // phase introduces a potential mistake where we suspend lanes that were 26387 // pinged or updated while we were rendering. 26388 markRootSuspended$1(workInProgressRoot, workInProgressRootRenderLanes); 26389 } 26390 } 26391 function renderDidError(error) { 26392 if (workInProgressRootExitStatus !== RootSuspendedWithDelay) { 26393 workInProgressRootExitStatus = RootErrored; 26394 } 26395 26396 if (workInProgressRootConcurrentErrors === null) { 26397 workInProgressRootConcurrentErrors = [error]; 26398 } else { 26399 workInProgressRootConcurrentErrors.push(error); 26400 } 26401 } // Called during render to determine if anything has suspended. 26402 // Returns false if we're not sure. 26403 26404 function renderHasNotSuspendedYet() { 26405 // If something errored or completed, we can't really be sure, 26406 // so those are false. 26407 return workInProgressRootExitStatus === RootInProgress; 26408 } 26409 26410 function renderRootSync(root, lanes) { 26411 var prevExecutionContext = executionContext; 26412 executionContext |= RenderContext; 26413 var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack 26414 // and prepare a fresh one. Otherwise we'll continue where we left off. 26415 26416 if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { 26417 { 26418 if (isDevToolsPresent) { 26419 var memoizedUpdaters = root.memoizedUpdaters; 26420 26421 if (memoizedUpdaters.size > 0) { 26422 restorePendingUpdaters(root, workInProgressRootRenderLanes); 26423 memoizedUpdaters.clear(); 26424 } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. 26425 // If we bailout on this work, we'll move them back (like above). 26426 // It's important to move them now in case the work spawns more work at the same priority with different updaters. 26427 // That way we can keep the current update and future updates separate. 26428 26429 26430 movePendingFibersToMemoized(root, lanes); 26431 } 26432 } 26433 26434 workInProgressTransitions = getTransitionsForLanes(); 26435 prepareFreshStack(root, lanes); 26436 } 26437 26438 { 26439 markRenderStarted(lanes); 26440 } 26441 26442 do { 26443 try { 26444 workLoopSync(); 26445 break; 26446 } catch (thrownValue) { 26447 handleError(root, thrownValue); 26448 } 26449 } while (true); 26450 26451 resetContextDependencies(); 26452 executionContext = prevExecutionContext; 26453 popDispatcher(prevDispatcher); 26454 26455 if (workInProgress !== null) { 26456 // This is a sync render, so we should have finished the whole tree. 26457 throw new Error('Cannot commit an incomplete root. This error is likely caused by a ' + 'bug in React. Please file an issue.'); 26458 } 26459 26460 { 26461 markRenderStopped(); 26462 } // Set this to null to indicate there's no in-progress render. 26463 26464 26465 workInProgressRoot = null; 26466 workInProgressRootRenderLanes = NoLanes; 26467 return workInProgressRootExitStatus; 26468 } // The work loop is an extremely hot path. Tell Closure not to inline it. 26469 26470 /** @noinline */ 26471 26472 26473 function workLoopSync() { 26474 // Already timed out, so perform work without checking if we need to yield. 26475 while (workInProgress !== null) { 26476 performUnitOfWork(workInProgress); 26477 } 26478 } 26479 26480 function renderRootConcurrent(root, lanes) { 26481 var prevExecutionContext = executionContext; 26482 executionContext |= RenderContext; 26483 var prevDispatcher = pushDispatcher(); // If the root or lanes have changed, throw out the existing stack 26484 // and prepare a fresh one. Otherwise we'll continue where we left off. 26485 26486 if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) { 26487 { 26488 if (isDevToolsPresent) { 26489 var memoizedUpdaters = root.memoizedUpdaters; 26490 26491 if (memoizedUpdaters.size > 0) { 26492 restorePendingUpdaters(root, workInProgressRootRenderLanes); 26493 memoizedUpdaters.clear(); 26494 } // At this point, move Fibers that scheduled the upcoming work from the Map to the Set. 26495 // If we bailout on this work, we'll move them back (like above). 26496 // It's important to move them now in case the work spawns more work at the same priority with different updaters. 26497 // That way we can keep the current update and future updates separate. 26498 26499 26500 movePendingFibersToMemoized(root, lanes); 26501 } 26502 } 26503 26504 workInProgressTransitions = getTransitionsForLanes(); 26505 resetRenderTimer(); 26506 prepareFreshStack(root, lanes); 26507 } 26508 26509 { 26510 markRenderStarted(lanes); 26511 } 26512 26513 do { 26514 try { 26515 workLoopConcurrent(); 26516 break; 26517 } catch (thrownValue) { 26518 handleError(root, thrownValue); 26519 } 26520 } while (true); 26521 26522 resetContextDependencies(); 26523 popDispatcher(prevDispatcher); 26524 executionContext = prevExecutionContext; 26525 26526 26527 if (workInProgress !== null) { 26528 // Still work remaining. 26529 { 26530 markRenderYielded(); 26531 } 26532 26533 return RootInProgress; 26534 } else { 26535 // Completed the tree. 26536 { 26537 markRenderStopped(); 26538 } // Set this to null to indicate there's no in-progress render. 26539 26540 26541 workInProgressRoot = null; 26542 workInProgressRootRenderLanes = NoLanes; // Return the final exit status. 26543 26544 return workInProgressRootExitStatus; 26545 } 26546 } 26547 /** @noinline */ 26548 26549 26550 function workLoopConcurrent() { 26551 // Perform work until Scheduler asks us to yield 26552 while (workInProgress !== null && !shouldYield()) { 26553 performUnitOfWork(workInProgress); 26554 } 26555 } 26556 26557 function performUnitOfWork(unitOfWork) { 26558 // The current, flushed, state of this fiber is the alternate. Ideally 26559 // nothing should rely on this, but relying on it here means that we don't 26560 // need an additional field on the work in progress. 26561 var current = unitOfWork.alternate; 26562 setCurrentFiber(unitOfWork); 26563 var next; 26564 26565 if ( (unitOfWork.mode & ProfileMode) !== NoMode) { 26566 startProfilerTimer(unitOfWork); 26567 next = beginWork$1(current, unitOfWork, subtreeRenderLanes); 26568 stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true); 26569 } else { 26570 next = beginWork$1(current, unitOfWork, subtreeRenderLanes); 26571 } 26572 26573 resetCurrentFiber(); 26574 unitOfWork.memoizedProps = unitOfWork.pendingProps; 26575 26576 if (next === null) { 26577 // If this doesn't spawn new work, complete the current work. 26578 completeUnitOfWork(unitOfWork); 26579 } else { 26580 workInProgress = next; 26581 } 26582 26583 ReactCurrentOwner$2.current = null; 26584 } 26585 26586 function completeUnitOfWork(unitOfWork) { 26587 // Attempt to complete the current unit of work, then move to the next 26588 // sibling. If there are no more siblings, return to the parent fiber. 26589 var completedWork = unitOfWork; 26590 26591 do { 26592 // The current, flushed, state of this fiber is the alternate. Ideally 26593 // nothing should rely on this, but relying on it here means that we don't 26594 // need an additional field on the work in progress. 26595 var current = completedWork.alternate; 26596 var returnFiber = completedWork.return; // Check if the work completed or if something threw. 26597 26598 if ((completedWork.flags & Incomplete) === NoFlags) { 26599 setCurrentFiber(completedWork); 26600 var next = void 0; 26601 26602 if ( (completedWork.mode & ProfileMode) === NoMode) { 26603 next = completeWork(current, completedWork, subtreeRenderLanes); 26604 } else { 26605 startProfilerTimer(completedWork); 26606 next = completeWork(current, completedWork, subtreeRenderLanes); // Update render duration assuming we didn't error. 26607 26608 stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); 26609 } 26610 26611 resetCurrentFiber(); 26612 26613 if (next !== null) { 26614 // Completing this fiber spawned new work. Work on that next. 26615 workInProgress = next; 26616 return; 26617 } 26618 } else { 26619 // This fiber did not complete because something threw. Pop values off 26620 // the stack without entering the complete phase. If this is a boundary, 26621 // capture values if possible. 26622 var _next = unwindWork(current, completedWork); // Because this fiber did not complete, don't reset its lanes. 26623 26624 26625 if (_next !== null) { 26626 // If completing this work spawned new work, do that next. We'll come 26627 // back here again. 26628 // Since we're restarting, remove anything that is not a host effect 26629 // from the effect tag. 26630 _next.flags &= HostEffectMask; 26631 workInProgress = _next; 26632 return; 26633 } 26634 26635 if ( (completedWork.mode & ProfileMode) !== NoMode) { 26636 // Record the render duration for the fiber that errored. 26637 stopProfilerTimerIfRunningAndRecordDelta(completedWork, false); // Include the time spent working on failed children before continuing. 26638 26639 var actualDuration = completedWork.actualDuration; 26640 var child = completedWork.child; 26641 26642 while (child !== null) { 26643 actualDuration += child.actualDuration; 26644 child = child.sibling; 26645 } 26646 26647 completedWork.actualDuration = actualDuration; 26648 } 26649 26650 if (returnFiber !== null) { 26651 // Mark the parent fiber as incomplete and clear its subtree flags. 26652 returnFiber.flags |= Incomplete; 26653 returnFiber.subtreeFlags = NoFlags; 26654 returnFiber.deletions = null; 26655 } else { 26656 // We've unwound all the way to the root. 26657 workInProgressRootExitStatus = RootDidNotComplete; 26658 workInProgress = null; 26659 return; 26660 } 26661 } 26662 26663 var siblingFiber = completedWork.sibling; 26664 26665 if (siblingFiber !== null) { 26666 // If there is more work to do in this returnFiber, do that next. 26667 workInProgress = siblingFiber; 26668 return; 26669 } // Otherwise, return to the parent 26670 26671 26672 completedWork = returnFiber; // Update the next thing we're working on in case something throws. 26673 26674 workInProgress = completedWork; 26675 } while (completedWork !== null); // We've reached the root. 26676 26677 26678 if (workInProgressRootExitStatus === RootInProgress) { 26679 workInProgressRootExitStatus = RootCompleted; 26680 } 26681 } 26682 26683 function commitRoot(root, recoverableErrors, transitions) { 26684 // TODO: This no longer makes any sense. We already wrap the mutation and 26685 // layout phases. Should be able to remove. 26686 var previousUpdateLanePriority = getCurrentUpdatePriority(); 26687 var prevTransition = ReactCurrentBatchConfig$3.transition; 26688 26689 try { 26690 ReactCurrentBatchConfig$3.transition = null; 26691 setCurrentUpdatePriority(DiscreteEventPriority); 26692 commitRootImpl(root, recoverableErrors, transitions, previousUpdateLanePriority); 26693 } finally { 26694 ReactCurrentBatchConfig$3.transition = prevTransition; 26695 setCurrentUpdatePriority(previousUpdateLanePriority); 26696 } 26697 26698 return null; 26699 } 26700 26701 function commitRootImpl(root, recoverableErrors, transitions, renderPriorityLevel) { 26702 do { 26703 // `flushPassiveEffects` will call `flushSyncUpdateQueue` at the end, which 26704 // means `flushPassiveEffects` will sometimes result in additional 26705 // passive effects. So we need to keep flushing in a loop until there are 26706 // no more pending effects. 26707 // TODO: Might be better if `flushPassiveEffects` did not automatically 26708 // flush synchronous work at the end, to avoid factoring hazards like this. 26709 flushPassiveEffects(); 26710 } while (rootWithPendingPassiveEffects !== null); 26711 26712 flushRenderPhaseStrictModeWarningsInDEV(); 26713 26714 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 26715 throw new Error('Should not already be working.'); 26716 } 26717 26718 var finishedWork = root.finishedWork; 26719 var lanes = root.finishedLanes; 26720 26721 { 26722 markCommitStarted(lanes); 26723 } 26724 26725 if (finishedWork === null) { 26726 26727 { 26728 markCommitStopped(); 26729 } 26730 26731 return null; 26732 } else { 26733 { 26734 if (lanes === NoLanes) { 26735 error('root.finishedLanes should not be empty during a commit. This is a ' + 'bug in React.'); 26736 } 26737 } 26738 } 26739 26740 root.finishedWork = null; 26741 root.finishedLanes = NoLanes; 26742 26743 if (finishedWork === root.current) { 26744 throw new Error('Cannot commit the same tree as before. This error is likely caused by ' + 'a bug in React. Please file an issue.'); 26745 } // commitRoot never returns a continuation; it always finishes synchronously. 26746 // So we can clear these now to allow a new callback to be scheduled. 26747 26748 26749 root.callbackNode = null; 26750 root.callbackPriority = NoLane; // Update the first and last pending times on this root. The new first 26751 // pending time is whatever is left on the root fiber. 26752 26753 var remainingLanes = mergeLanes(finishedWork.lanes, finishedWork.childLanes); 26754 markRootFinished(root, remainingLanes); 26755 26756 if (root === workInProgressRoot) { 26757 // We can reset these now that they are finished. 26758 workInProgressRoot = null; 26759 workInProgress = null; 26760 workInProgressRootRenderLanes = NoLanes; 26761 } // If there are pending passive effects, schedule a callback to process them. 26762 // Do this as early as possible, so it is queued before anything else that 26763 // might get scheduled in the commit phase. (See #16714.) 26764 // TODO: Delete all other places that schedule the passive effect callback 26765 // They're redundant. 26766 26767 26768 if ((finishedWork.subtreeFlags & PassiveMask) !== NoFlags || (finishedWork.flags & PassiveMask) !== NoFlags) { 26769 if (!rootDoesHavePassiveEffects) { 26770 rootDoesHavePassiveEffects = true; 26771 // to store it in pendingPassiveTransitions until they get processed 26772 // We need to pass this through as an argument to commitRoot 26773 // because workInProgressTransitions might have changed between 26774 // the previous render and commit if we throttle the commit 26775 // with setTimeout 26776 26777 pendingPassiveTransitions = transitions; 26778 scheduleCallback$1(NormalPriority, function () { 26779 flushPassiveEffects(); // This render triggered passive effects: release the root cache pool 26780 // *after* passive effects fire to avoid freeing a cache pool that may 26781 // be referenced by a node in the tree (HostRoot, Cache boundary etc) 26782 26783 return null; 26784 }); 26785 } 26786 } // Check if there are any effects in the whole tree. 26787 // TODO: This is left over from the effect list implementation, where we had 26788 // to check for the existence of `firstEffect` to satisfy Flow. I think the 26789 // only other reason this optimization exists is because it affects profiling. 26790 // Reconsider whether this is necessary. 26791 26792 26793 var subtreeHasEffects = (finishedWork.subtreeFlags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags; 26794 var rootHasEffect = (finishedWork.flags & (BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !== NoFlags; 26795 26796 if (subtreeHasEffects || rootHasEffect) { 26797 var prevTransition = ReactCurrentBatchConfig$3.transition; 26798 ReactCurrentBatchConfig$3.transition = null; 26799 var previousPriority = getCurrentUpdatePriority(); 26800 setCurrentUpdatePriority(DiscreteEventPriority); 26801 var prevExecutionContext = executionContext; 26802 executionContext |= CommitContext; // Reset this to null before calling lifecycles 26803 26804 ReactCurrentOwner$2.current = null; // The commit phase is broken into several sub-phases. We do a separate pass 26805 // of the effect list for each phase: all mutation effects come before all 26806 // layout effects, and so on. 26807 // The first phase a "before mutation" phase. We use this phase to read the 26808 // state of the host tree right before we mutate it. This is where 26809 // getSnapshotBeforeUpdate is called. 26810 26811 var shouldFireAfterActiveInstanceBlur = commitBeforeMutationEffects(root, finishedWork); 26812 26813 { 26814 // Mark the current commit time to be shared by all Profilers in this 26815 // batch. This enables them to be grouped later. 26816 recordCommitTime(); 26817 } 26818 26819 26820 commitMutationEffects(root, finishedWork, lanes); 26821 26822 resetAfterCommit(root.containerInfo); // The work-in-progress tree is now the current tree. This must come after 26823 // the mutation phase, so that the previous tree is still current during 26824 // componentWillUnmount, but before the layout phase, so that the finished 26825 // work is current during componentDidMount/Update. 26826 26827 root.current = finishedWork; // The next phase is the layout phase, where we call effects that read 26828 26829 { 26830 markLayoutEffectsStarted(lanes); 26831 } 26832 26833 commitLayoutEffects(finishedWork, root, lanes); 26834 26835 { 26836 markLayoutEffectsStopped(); 26837 } 26838 // opportunity to paint. 26839 26840 26841 requestPaint(); 26842 executionContext = prevExecutionContext; // Reset the priority to the previous non-sync value. 26843 26844 setCurrentUpdatePriority(previousPriority); 26845 ReactCurrentBatchConfig$3.transition = prevTransition; 26846 } else { 26847 // No effects. 26848 root.current = finishedWork; // Measure these anyway so the flamegraph explicitly shows that there were 26849 // no effects. 26850 // TODO: Maybe there's a better way to report this. 26851 26852 { 26853 recordCommitTime(); 26854 } 26855 } 26856 26857 var rootDidHavePassiveEffects = rootDoesHavePassiveEffects; 26858 26859 if (rootDoesHavePassiveEffects) { 26860 // This commit has passive effects. Stash a reference to them. But don't 26861 // schedule a callback until after flushing layout work. 26862 rootDoesHavePassiveEffects = false; 26863 rootWithPendingPassiveEffects = root; 26864 pendingPassiveEffectsLanes = lanes; 26865 } else { 26866 26867 { 26868 nestedPassiveUpdateCount = 0; 26869 rootWithPassiveNestedUpdates = null; 26870 } 26871 } // Read this again, since an effect might have updated it 26872 26873 26874 remainingLanes = root.pendingLanes; // Check if there's remaining work on this root 26875 // TODO: This is part of the `componentDidCatch` implementation. Its purpose 26876 // is to detect whether something might have called setState inside 26877 // `componentDidCatch`. The mechanism is known to be flawed because `setState` 26878 // inside `componentDidCatch` is itself flawed — that's why we recommend 26879 // `getDerivedStateFromError` instead. However, it could be improved by 26880 // checking if remainingLanes includes Sync work, instead of whether there's 26881 // any work remaining at all (which would also include stuff like Suspense 26882 // retries or transitions). It's been like this for a while, though, so fixing 26883 // it probably isn't that urgent. 26884 26885 if (remainingLanes === NoLanes) { 26886 // If there's no remaining work, we can clear the set of already failed 26887 // error boundaries. 26888 legacyErrorBoundariesThatAlreadyFailed = null; 26889 } 26890 26891 { 26892 if (!rootDidHavePassiveEffects) { 26893 commitDoubleInvokeEffectsInDEV(root.current, false); 26894 } 26895 } 26896 26897 onCommitRoot(finishedWork.stateNode, renderPriorityLevel); 26898 26899 { 26900 if (isDevToolsPresent) { 26901 root.memoizedUpdaters.clear(); 26902 } 26903 } 26904 26905 { 26906 onCommitRoot$1(); 26907 } // Always call this before exiting `commitRoot`, to ensure that any 26908 // additional work on this root is scheduled. 26909 26910 26911 ensureRootIsScheduled(root, now()); 26912 26913 if (recoverableErrors !== null) { 26914 // There were errors during this render, but recovered from them without 26915 // needing to surface it to the UI. We log them here. 26916 var onRecoverableError = root.onRecoverableError; 26917 26918 for (var i = 0; i < recoverableErrors.length; i++) { 26919 var recoverableError = recoverableErrors[i]; 26920 var componentStack = recoverableError.stack; 26921 var digest = recoverableError.digest; 26922 onRecoverableError(recoverableError.value, { 26923 componentStack: componentStack, 26924 digest: digest 26925 }); 26926 } 26927 } 26928 26929 if (hasUncaughtError) { 26930 hasUncaughtError = false; 26931 var error$1 = firstUncaughtError; 26932 firstUncaughtError = null; 26933 throw error$1; 26934 } // If the passive effects are the result of a discrete render, flush them 26935 // synchronously at the end of the current task so that the result is 26936 // immediately observable. Otherwise, we assume that they are not 26937 // order-dependent and do not need to be observed by external systems, so we 26938 // can wait until after paint. 26939 // TODO: We can optimize this by not scheduling the callback earlier. Since we 26940 // currently schedule the callback in multiple places, will wait until those 26941 // are consolidated. 26942 26943 26944 if (includesSomeLane(pendingPassiveEffectsLanes, SyncLane) && root.tag !== LegacyRoot) { 26945 flushPassiveEffects(); 26946 } // Read this again, since a passive effect might have updated it 26947 26948 26949 remainingLanes = root.pendingLanes; 26950 26951 if (includesSomeLane(remainingLanes, SyncLane)) { 26952 { 26953 markNestedUpdateScheduled(); 26954 } // Count the number of times the root synchronously re-renders without 26955 // finishing. If there are too many, it indicates an infinite update loop. 26956 26957 26958 if (root === rootWithNestedUpdates) { 26959 nestedUpdateCount++; 26960 } else { 26961 nestedUpdateCount = 0; 26962 rootWithNestedUpdates = root; 26963 } 26964 } else { 26965 nestedUpdateCount = 0; 26966 } // If layout work was scheduled, flush it now. 26967 26968 26969 flushSyncCallbacks(); 26970 26971 { 26972 markCommitStopped(); 26973 } 26974 26975 return null; 26976 } 26977 26978 function flushPassiveEffects() { 26979 // Returns whether passive effects were flushed. 26980 // TODO: Combine this check with the one in flushPassiveEFfectsImpl. We should 26981 // probably just combine the two functions. I believe they were only separate 26982 // in the first place because we used to wrap it with 26983 // `Scheduler.runWithPriority`, which accepts a function. But now we track the 26984 // priority within React itself, so we can mutate the variable directly. 26985 if (rootWithPendingPassiveEffects !== null) { 26986 var renderPriority = lanesToEventPriority(pendingPassiveEffectsLanes); 26987 var priority = lowerEventPriority(DefaultEventPriority, renderPriority); 26988 var prevTransition = ReactCurrentBatchConfig$3.transition; 26989 var previousPriority = getCurrentUpdatePriority(); 26990 26991 try { 26992 ReactCurrentBatchConfig$3.transition = null; 26993 setCurrentUpdatePriority(priority); 26994 return flushPassiveEffectsImpl(); 26995 } finally { 26996 setCurrentUpdatePriority(previousPriority); 26997 ReactCurrentBatchConfig$3.transition = prevTransition; // Once passive effects have run for the tree - giving components a 26998 } 26999 } 27000 27001 return false; 27002 } 27003 function enqueuePendingPassiveProfilerEffect(fiber) { 27004 { 27005 pendingPassiveProfilerEffects.push(fiber); 27006 27007 if (!rootDoesHavePassiveEffects) { 27008 rootDoesHavePassiveEffects = true; 27009 scheduleCallback$1(NormalPriority, function () { 27010 flushPassiveEffects(); 27011 return null; 27012 }); 27013 } 27014 } 27015 } 27016 27017 function flushPassiveEffectsImpl() { 27018 if (rootWithPendingPassiveEffects === null) { 27019 return false; 27020 } // Cache and clear the transitions flag 27021 27022 27023 var transitions = pendingPassiveTransitions; 27024 pendingPassiveTransitions = null; 27025 var root = rootWithPendingPassiveEffects; 27026 var lanes = pendingPassiveEffectsLanes; 27027 rootWithPendingPassiveEffects = null; // TODO: This is sometimes out of sync with rootWithPendingPassiveEffects. 27028 // Figure out why and fix it. It's not causing any known issues (probably 27029 // because it's only used for profiling), but it's a refactor hazard. 27030 27031 pendingPassiveEffectsLanes = NoLanes; 27032 27033 if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { 27034 throw new Error('Cannot flush passive effects while already rendering.'); 27035 } 27036 27037 { 27038 isFlushingPassiveEffects = true; 27039 didScheduleUpdateDuringPassiveEffects = false; 27040 } 27041 27042 { 27043 markPassiveEffectsStarted(lanes); 27044 } 27045 27046 var prevExecutionContext = executionContext; 27047 executionContext |= CommitContext; 27048 commitPassiveUnmountEffects(root.current); 27049 commitPassiveMountEffects(root, root.current, lanes, transitions); // TODO: Move to commitPassiveMountEffects 27050 27051 { 27052 var profilerEffects = pendingPassiveProfilerEffects; 27053 pendingPassiveProfilerEffects = []; 27054 27055 for (var i = 0; i < profilerEffects.length; i++) { 27056 var _fiber = profilerEffects[i]; 27057 commitPassiveEffectDurations(root, _fiber); 27058 } 27059 } 27060 27061 { 27062 markPassiveEffectsStopped(); 27063 } 27064 27065 { 27066 commitDoubleInvokeEffectsInDEV(root.current, true); 27067 } 27068 27069 executionContext = prevExecutionContext; 27070 flushSyncCallbacks(); 27071 27072 { 27073 // If additional passive effects were scheduled, increment a counter. If this 27074 // exceeds the limit, we'll fire a warning. 27075 if (didScheduleUpdateDuringPassiveEffects) { 27076 if (root === rootWithPassiveNestedUpdates) { 27077 nestedPassiveUpdateCount++; 27078 } else { 27079 nestedPassiveUpdateCount = 0; 27080 rootWithPassiveNestedUpdates = root; 27081 } 27082 } else { 27083 nestedPassiveUpdateCount = 0; 27084 } 27085 27086 isFlushingPassiveEffects = false; 27087 didScheduleUpdateDuringPassiveEffects = false; 27088 } // TODO: Move to commitPassiveMountEffects 27089 27090 27091 onPostCommitRoot(root); 27092 27093 { 27094 var stateNode = root.current.stateNode; 27095 stateNode.effectDuration = 0; 27096 stateNode.passiveEffectDuration = 0; 27097 } 27098 27099 return true; 27100 } 27101 27102 function isAlreadyFailedLegacyErrorBoundary(instance) { 27103 return legacyErrorBoundariesThatAlreadyFailed !== null && legacyErrorBoundariesThatAlreadyFailed.has(instance); 27104 } 27105 function markLegacyErrorBoundaryAsFailed(instance) { 27106 if (legacyErrorBoundariesThatAlreadyFailed === null) { 27107 legacyErrorBoundariesThatAlreadyFailed = new Set([instance]); 27108 } else { 27109 legacyErrorBoundariesThatAlreadyFailed.add(instance); 27110 } 27111 } 27112 27113 function prepareToThrowUncaughtError(error) { 27114 if (!hasUncaughtError) { 27115 hasUncaughtError = true; 27116 firstUncaughtError = error; 27117 } 27118 } 27119 27120 var onUncaughtError = prepareToThrowUncaughtError; 27121 27122 function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { 27123 var errorInfo = createCapturedValueAtFiber(error, sourceFiber); 27124 var update = createRootErrorUpdate(rootFiber, errorInfo, SyncLane); 27125 var root = enqueueUpdate(rootFiber, update, SyncLane); 27126 var eventTime = requestEventTime(); 27127 27128 if (root !== null) { 27129 markRootUpdated(root, SyncLane, eventTime); 27130 ensureRootIsScheduled(root, eventTime); 27131 } 27132 } 27133 27134 function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error$1) { 27135 { 27136 reportUncaughtErrorInDEV(error$1); 27137 setIsRunningInsertionEffect(false); 27138 } 27139 27140 if (sourceFiber.tag === HostRoot) { 27141 // Error was thrown at the root. There is no parent, so the root 27142 // itself should capture it. 27143 captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error$1); 27144 return; 27145 } 27146 27147 var fiber = null; 27148 27149 { 27150 fiber = nearestMountedAncestor; 27151 } 27152 27153 while (fiber !== null) { 27154 if (fiber.tag === HostRoot) { 27155 captureCommitPhaseErrorOnRoot(fiber, sourceFiber, error$1); 27156 return; 27157 } else if (fiber.tag === ClassComponent) { 27158 var ctor = fiber.type; 27159 var instance = fiber.stateNode; 27160 27161 if (typeof ctor.getDerivedStateFromError === 'function' || typeof instance.componentDidCatch === 'function' && !isAlreadyFailedLegacyErrorBoundary(instance)) { 27162 var errorInfo = createCapturedValueAtFiber(error$1, sourceFiber); 27163 var update = createClassErrorUpdate(fiber, errorInfo, SyncLane); 27164 var root = enqueueUpdate(fiber, update, SyncLane); 27165 var eventTime = requestEventTime(); 27166 27167 if (root !== null) { 27168 markRootUpdated(root, SyncLane, eventTime); 27169 ensureRootIsScheduled(root, eventTime); 27170 } 27171 27172 return; 27173 } 27174 } 27175 27176 fiber = fiber.return; 27177 } 27178 27179 { 27180 // TODO: Until we re-land skipUnmountedBoundaries (see #20147), this warning 27181 // will fire for errors that are thrown by destroy functions inside deleted 27182 // trees. What it should instead do is propagate the error to the parent of 27183 // the deleted tree. In the meantime, do not add this warning to the 27184 // allowlist; this is only for our internal use. 27185 error('Internal React error: Attempted to capture a commit phase error ' + 'inside a detached tree. This indicates a bug in React. Likely ' + 'causes include deleting the same fiber more than once, committing an ' + 'already-finished tree, or an inconsistent return pointer.\n\n' + 'Error message:\n\n%s', error$1); 27186 } 27187 } 27188 function pingSuspendedRoot(root, wakeable, pingedLanes) { 27189 var pingCache = root.pingCache; 27190 27191 if (pingCache !== null) { 27192 // The wakeable resolved, so we no longer need to memoize, because it will 27193 // never be thrown again. 27194 pingCache.delete(wakeable); 27195 } 27196 27197 var eventTime = requestEventTime(); 27198 markRootPinged(root, pingedLanes); 27199 warnIfSuspenseResolutionNotWrappedWithActDEV(root); 27200 27201 if (workInProgressRoot === root && isSubsetOfLanes(workInProgressRootRenderLanes, pingedLanes)) { 27202 // Received a ping at the same priority level at which we're currently 27203 // rendering. We might want to restart this render. This should mirror 27204 // the logic of whether or not a root suspends once it completes. 27205 // TODO: If we're rendering sync either due to Sync, Batched or expired, 27206 // we should probably never restart. 27207 // If we're suspended with delay, or if it's a retry, we'll always suspend 27208 // so we can always restart. 27209 if (workInProgressRootExitStatus === RootSuspendedWithDelay || workInProgressRootExitStatus === RootSuspended && includesOnlyRetries(workInProgressRootRenderLanes) && now() - globalMostRecentFallbackTime < FALLBACK_THROTTLE_MS) { 27210 // Restart from the root. 27211 prepareFreshStack(root, NoLanes); 27212 } else { 27213 // Even though we can't restart right now, we might get an 27214 // opportunity later. So we mark this render as having a ping. 27215 workInProgressRootPingedLanes = mergeLanes(workInProgressRootPingedLanes, pingedLanes); 27216 } 27217 } 27218 27219 ensureRootIsScheduled(root, eventTime); 27220 } 27221 27222 function retryTimedOutBoundary(boundaryFiber, retryLane) { 27223 // The boundary fiber (a Suspense component or SuspenseList component) 27224 // previously was rendered in its fallback state. One of the promises that 27225 // suspended it has resolved, which means at least part of the tree was 27226 // likely unblocked. Try rendering again, at a new lanes. 27227 if (retryLane === NoLane) { 27228 // TODO: Assign this to `suspenseState.retryLane`? to avoid 27229 // unnecessary entanglement? 27230 retryLane = requestRetryLane(boundaryFiber); 27231 } // TODO: Special case idle priority? 27232 27233 27234 var eventTime = requestEventTime(); 27235 var root = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); 27236 27237 if (root !== null) { 27238 markRootUpdated(root, retryLane, eventTime); 27239 ensureRootIsScheduled(root, eventTime); 27240 } 27241 } 27242 27243 function retryDehydratedSuspenseBoundary(boundaryFiber) { 27244 var suspenseState = boundaryFiber.memoizedState; 27245 var retryLane = NoLane; 27246 27247 if (suspenseState !== null) { 27248 retryLane = suspenseState.retryLane; 27249 } 27250 27251 retryTimedOutBoundary(boundaryFiber, retryLane); 27252 } 27253 function resolveRetryWakeable(boundaryFiber, wakeable) { 27254 var retryLane = NoLane; // Default 27255 27256 var retryCache; 27257 27258 switch (boundaryFiber.tag) { 27259 case SuspenseComponent: 27260 retryCache = boundaryFiber.stateNode; 27261 var suspenseState = boundaryFiber.memoizedState; 27262 27263 if (suspenseState !== null) { 27264 retryLane = suspenseState.retryLane; 27265 } 27266 27267 break; 27268 27269 case SuspenseListComponent: 27270 retryCache = boundaryFiber.stateNode; 27271 break; 27272 27273 default: 27274 throw new Error('Pinged unknown suspense boundary type. ' + 'This is probably a bug in React.'); 27275 } 27276 27277 if (retryCache !== null) { 27278 // The wakeable resolved, so we no longer need to memoize, because it will 27279 // never be thrown again. 27280 retryCache.delete(wakeable); 27281 } 27282 27283 retryTimedOutBoundary(boundaryFiber, retryLane); 27284 } // Computes the next Just Noticeable Difference (JND) boundary. 27285 // The theory is that a person can't tell the difference between small differences in time. 27286 // Therefore, if we wait a bit longer than necessary that won't translate to a noticeable 27287 // difference in the experience. However, waiting for longer might mean that we can avoid 27288 // showing an intermediate loading state. The longer we have already waited, the harder it 27289 // is to tell small differences in time. Therefore, the longer we've already waited, 27290 // the longer we can wait additionally. At some point we have to give up though. 27291 // We pick a train model where the next boundary commits at a consistent schedule. 27292 // These particular numbers are vague estimates. We expect to adjust them based on research. 27293 27294 function jnd(timeElapsed) { 27295 return timeElapsed < 120 ? 120 : timeElapsed < 480 ? 480 : timeElapsed < 1080 ? 1080 : timeElapsed < 1920 ? 1920 : timeElapsed < 3000 ? 3000 : timeElapsed < 4320 ? 4320 : ceil(timeElapsed / 1960) * 1960; 27296 } 27297 27298 function checkForNestedUpdates() { 27299 if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { 27300 nestedUpdateCount = 0; 27301 rootWithNestedUpdates = null; 27302 throw new Error('Maximum update depth exceeded. This can happen when a component ' + 'repeatedly calls setState inside componentWillUpdate or ' + 'componentDidUpdate. React limits the number of nested updates to ' + 'prevent infinite loops.'); 27303 } 27304 27305 { 27306 if (nestedPassiveUpdateCount > NESTED_PASSIVE_UPDATE_LIMIT) { 27307 nestedPassiveUpdateCount = 0; 27308 rootWithPassiveNestedUpdates = null; 27309 27310 error('Maximum update depth exceeded. This can happen when a component ' + "calls setState inside useEffect, but useEffect either doesn't " + 'have a dependency array, or one of the dependencies changes on ' + 'every render.'); 27311 } 27312 } 27313 } 27314 27315 function flushRenderPhaseStrictModeWarningsInDEV() { 27316 { 27317 ReactStrictModeWarnings.flushLegacyContextWarning(); 27318 27319 { 27320 ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings(); 27321 } 27322 } 27323 } 27324 27325 function commitDoubleInvokeEffectsInDEV(fiber, hasPassiveEffects) { 27326 { 27327 // TODO (StrictEffects) Should we set a marker on the root if it contains strict effects 27328 // so we don't traverse unnecessarily? similar to subtreeFlags but just at the root level. 27329 // Maybe not a big deal since this is DEV only behavior. 27330 setCurrentFiber(fiber); 27331 invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectUnmountInDEV); 27332 27333 if (hasPassiveEffects) { 27334 invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectUnmountInDEV); 27335 } 27336 27337 invokeEffectsInDev(fiber, MountLayoutDev, invokeLayoutEffectMountInDEV); 27338 27339 if (hasPassiveEffects) { 27340 invokeEffectsInDev(fiber, MountPassiveDev, invokePassiveEffectMountInDEV); 27341 } 27342 27343 resetCurrentFiber(); 27344 } 27345 } 27346 27347 function invokeEffectsInDev(firstChild, fiberFlags, invokeEffectFn) { 27348 { 27349 // We don't need to re-check StrictEffectsMode here. 27350 // This function is only called if that check has already passed. 27351 var current = firstChild; 27352 var subtreeRoot = null; 27353 27354 while (current !== null) { 27355 var primarySubtreeFlag = current.subtreeFlags & fiberFlags; 27356 27357 if (current !== subtreeRoot && current.child !== null && primarySubtreeFlag !== NoFlags) { 27358 current = current.child; 27359 } else { 27360 if ((current.flags & fiberFlags) !== NoFlags) { 27361 invokeEffectFn(current); 27362 } 27363 27364 if (current.sibling !== null) { 27365 current = current.sibling; 27366 } else { 27367 current = subtreeRoot = current.return; 27368 } 27369 } 27370 } 27371 } 27372 } 27373 27374 var didWarnStateUpdateForNotYetMountedComponent = null; 27375 function warnAboutUpdateOnNotYetMountedFiberInDEV(fiber) { 27376 { 27377 if ((executionContext & RenderContext) !== NoContext) { 27378 // We let the other warning about render phase updates deal with this one. 27379 return; 27380 } 27381 27382 if (!(fiber.mode & ConcurrentMode)) { 27383 return; 27384 } 27385 27386 var tag = fiber.tag; 27387 27388 if (tag !== IndeterminateComponent && tag !== HostRoot && tag !== ClassComponent && tag !== FunctionComponent && tag !== ForwardRef && tag !== MemoComponent && tag !== SimpleMemoComponent) { 27389 // Only warn for user-defined components, not internal ones like Suspense. 27390 return; 27391 } // We show the whole stack but dedupe on the top component's name because 27392 // the problematic code almost always lies inside that component. 27393 27394 27395 var componentName = getComponentNameFromFiber(fiber) || 'ReactComponent'; 27396 27397 if (didWarnStateUpdateForNotYetMountedComponent !== null) { 27398 if (didWarnStateUpdateForNotYetMountedComponent.has(componentName)) { 27399 return; 27400 } 27401 27402 didWarnStateUpdateForNotYetMountedComponent.add(componentName); 27403 } else { 27404 didWarnStateUpdateForNotYetMountedComponent = new Set([componentName]); 27405 } 27406 27407 var previousFiber = current; 27408 27409 try { 27410 setCurrentFiber(fiber); 27411 27412 error("Can't perform a React state update on a component that hasn't mounted yet. " + 'This indicates that you have a side-effect in your render function that ' + 'asynchronously later calls tries to update the component. Move this work to ' + 'useEffect instead.'); 27413 } finally { 27414 if (previousFiber) { 27415 setCurrentFiber(fiber); 27416 } else { 27417 resetCurrentFiber(); 27418 } 27419 } 27420 } 27421 } 27422 var beginWork$1; 27423 27424 { 27425 var dummyFiber = null; 27426 27427 beginWork$1 = function (current, unitOfWork, lanes) { 27428 // If a component throws an error, we replay it again in a synchronously 27429 // dispatched event, so that the debugger will treat it as an uncaught 27430 // error See ReactErrorUtils for more information. 27431 // Before entering the begin phase, copy the work-in-progress onto a dummy 27432 // fiber. If beginWork throws, we'll use this to reset the state. 27433 var originalWorkInProgressCopy = assignFiberPropertiesInDEV(dummyFiber, unitOfWork); 27434 27435 try { 27436 return beginWork(current, unitOfWork, lanes); 27437 } catch (originalError) { 27438 if (didSuspendOrErrorWhileHydratingDEV() || originalError !== null && typeof originalError === 'object' && typeof originalError.then === 'function') { 27439 // Don't replay promises. 27440 // Don't replay errors if we are hydrating and have already suspended or handled an error 27441 throw originalError; 27442 } // Keep this code in sync with handleError; any changes here must have 27443 // corresponding changes there. 27444 27445 27446 resetContextDependencies(); 27447 resetHooksAfterThrow(); // Don't reset current debug fiber, since we're about to work on the 27448 // same fiber again. 27449 // Unwind the failed stack frame 27450 27451 unwindInterruptedWork(current, unitOfWork); // Restore the original properties of the fiber. 27452 27453 assignFiberPropertiesInDEV(unitOfWork, originalWorkInProgressCopy); 27454 27455 if ( unitOfWork.mode & ProfileMode) { 27456 // Reset the profiler timer. 27457 startProfilerTimer(unitOfWork); 27458 } // Run beginWork again. 27459 27460 27461 invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes); 27462 27463 if (hasCaughtError()) { 27464 var replayError = clearCaughtError(); 27465 27466 if (typeof replayError === 'object' && replayError !== null && replayError._suppressLogging && typeof originalError === 'object' && originalError !== null && !originalError._suppressLogging) { 27467 // If suppressed, let the flag carry over to the original error which is the one we'll rethrow. 27468 originalError._suppressLogging = true; 27469 } 27470 } // We always throw the original error in case the second render pass is not idempotent. 27471 // This can happen if a memoized function or CommonJS module doesn't throw after first invocation. 27472 27473 27474 throw originalError; 27475 } 27476 }; 27477 } 27478 27479 var didWarnAboutUpdateInRender = false; 27480 var didWarnAboutUpdateInRenderForAnotherComponent; 27481 27482 { 27483 didWarnAboutUpdateInRenderForAnotherComponent = new Set(); 27484 } 27485 27486 function warnAboutRenderPhaseUpdatesInDEV(fiber) { 27487 { 27488 if (isRendering && !getIsUpdatingOpaqueValueInRenderPhaseInDEV()) { 27489 switch (fiber.tag) { 27490 case FunctionComponent: 27491 case ForwardRef: 27492 case SimpleMemoComponent: 27493 { 27494 var renderingComponentName = workInProgress && getComponentNameFromFiber(workInProgress) || 'Unknown'; // Dedupe by the rendering component because it's the one that needs to be fixed. 27495 27496 var dedupeKey = renderingComponentName; 27497 27498 if (!didWarnAboutUpdateInRenderForAnotherComponent.has(dedupeKey)) { 27499 didWarnAboutUpdateInRenderForAnotherComponent.add(dedupeKey); 27500 var setStateComponentName = getComponentNameFromFiber(fiber) || 'Unknown'; 27501 27502 error('Cannot update a component (`%s`) while rendering a ' + 'different component (`%s`). To locate the bad setState() call inside `%s`, ' + 'follow the stack trace as described in https://reactjs.org/link/setstate-in-render', setStateComponentName, renderingComponentName, renderingComponentName); 27503 } 27504 27505 break; 27506 } 27507 27508 case ClassComponent: 27509 { 27510 if (!didWarnAboutUpdateInRender) { 27511 error('Cannot update during an existing state transition (such as ' + 'within `render`). Render methods should be a pure ' + 'function of props and state.'); 27512 27513 didWarnAboutUpdateInRender = true; 27514 } 27515 27516 break; 27517 } 27518 } 27519 } 27520 } 27521 } 27522 27523 function restorePendingUpdaters(root, lanes) { 27524 { 27525 if (isDevToolsPresent) { 27526 var memoizedUpdaters = root.memoizedUpdaters; 27527 memoizedUpdaters.forEach(function (schedulingFiber) { 27528 addFiberToLanesMap(root, schedulingFiber, lanes); 27529 }); // This function intentionally does not clear memoized updaters. 27530 // Those may still be relevant to the current commit 27531 // and a future one (e.g. Suspense). 27532 } 27533 } 27534 } 27535 var fakeActCallbackNode = {}; 27536 27537 function scheduleCallback$1(priorityLevel, callback) { 27538 { 27539 // If we're currently inside an `act` scope, bypass Scheduler and push to 27540 // the `act` queue instead. 27541 var actQueue = ReactCurrentActQueue$1.current; 27542 27543 if (actQueue !== null) { 27544 actQueue.push(callback); 27545 return fakeActCallbackNode; 27546 } else { 27547 return scheduleCallback(priorityLevel, callback); 27548 } 27549 } 27550 } 27551 27552 function cancelCallback$1(callbackNode) { 27553 if ( callbackNode === fakeActCallbackNode) { 27554 return; 27555 } // In production, always call Scheduler. This function will be stripped out. 27556 27557 27558 return cancelCallback(callbackNode); 27559 } 27560 27561 function shouldForceFlushFallbacksInDEV() { 27562 // Never force flush in production. This function should get stripped out. 27563 return ReactCurrentActQueue$1.current !== null; 27564 } 27565 27566 function warnIfUpdatesNotWrappedWithActDEV(fiber) { 27567 { 27568 if (fiber.mode & ConcurrentMode) { 27569 if (!isConcurrentActEnvironment()) { 27570 // Not in an act environment. No need to warn. 27571 return; 27572 } 27573 } else { 27574 // Legacy mode has additional cases where we suppress a warning. 27575 if (!isLegacyActEnvironment()) { 27576 // Not in an act environment. No need to warn. 27577 return; 27578 } 27579 27580 if (executionContext !== NoContext) { 27581 // Legacy mode doesn't warn if the update is batched, i.e. 27582 // batchedUpdates or flushSync. 27583 return; 27584 } 27585 27586 if (fiber.tag !== FunctionComponent && fiber.tag !== ForwardRef && fiber.tag !== SimpleMemoComponent) { 27587 // For backwards compatibility with pre-hooks code, legacy mode only 27588 // warns for updates that originate from a hook. 27589 return; 27590 } 27591 } 27592 27593 if (ReactCurrentActQueue$1.current === null) { 27594 var previousFiber = current; 27595 27596 try { 27597 setCurrentFiber(fiber); 27598 27599 error('An update to %s inside a test was not wrapped in act(...).\n\n' + 'When testing, code that causes React state updates should be ' + 'wrapped into act(...):\n\n' + 'act(() => {\n' + ' /* fire events that update state */\n' + '});\n' + '/* assert on the output */\n\n' + "This ensures that you're testing the behavior the user would see " + 'in the browser.' + ' Learn more at https://reactjs.org/link/wrap-tests-with-act', getComponentNameFromFiber(fiber)); 27600 } finally { 27601 if (previousFiber) { 27602 setCurrentFiber(fiber); 27603 } else { 27604 resetCurrentFiber(); 27605 } 27606 } 27607 } 27608 } 27609 } 27610 27611 function warnIfSuspenseResolutionNotWrappedWithActDEV(root) { 27612 { 27613 if (root.tag !== LegacyRoot && isConcurrentActEnvironment() && ReactCurrentActQueue$1.current === null) { 27614 error('A suspended resource finished loading inside a test, but the event ' + 'was not wrapped in act(...).\n\n' + 'When testing, code that resolves suspended data should be wrapped ' + 'into act(...):\n\n' + 'act(() => {\n' + ' /* finish loading suspended data */\n' + '});\n' + '/* assert on the output */\n\n' + "This ensures that you're testing the behavior the user would see " + 'in the browser.' + ' Learn more at https://reactjs.org/link/wrap-tests-with-act'); 27615 } 27616 } 27617 } 27618 27619 function setIsRunningInsertionEffect(isRunning) { 27620 { 27621 isRunningInsertionEffect = isRunning; 27622 } 27623 } 27624 27625 /* eslint-disable react-internal/prod-error-codes */ 27626 var resolveFamily = null; // $FlowFixMe Flow gets confused by a WeakSet feature check below. 27627 27628 var failedBoundaries = null; 27629 var setRefreshHandler = function (handler) { 27630 { 27631 resolveFamily = handler; 27632 } 27633 }; 27634 function resolveFunctionForHotReloading(type) { 27635 { 27636 if (resolveFamily === null) { 27637 // Hot reloading is disabled. 27638 return type; 27639 } 27640 27641 var family = resolveFamily(type); 27642 27643 if (family === undefined) { 27644 return type; 27645 } // Use the latest known implementation. 27646 27647 27648 return family.current; 27649 } 27650 } 27651 function resolveClassForHotReloading(type) { 27652 // No implementation differences. 27653 return resolveFunctionForHotReloading(type); 27654 } 27655 function resolveForwardRefForHotReloading(type) { 27656 { 27657 if (resolveFamily === null) { 27658 // Hot reloading is disabled. 27659 return type; 27660 } 27661 27662 var family = resolveFamily(type); 27663 27664 if (family === undefined) { 27665 // Check if we're dealing with a real forwardRef. Don't want to crash early. 27666 if (type !== null && type !== undefined && typeof type.render === 'function') { 27667 // ForwardRef is special because its resolved .type is an object, 27668 // but it's possible that we only have its inner render function in the map. 27669 // If that inner render function is different, we'll build a new forwardRef type. 27670 var currentRender = resolveFunctionForHotReloading(type.render); 27671 27672 if (type.render !== currentRender) { 27673 var syntheticType = { 27674 $$typeof: REACT_FORWARD_REF_TYPE, 27675 render: currentRender 27676 }; 27677 27678 if (type.displayName !== undefined) { 27679 syntheticType.displayName = type.displayName; 27680 } 27681 27682 return syntheticType; 27683 } 27684 } 27685 27686 return type; 27687 } // Use the latest known implementation. 27688 27689 27690 return family.current; 27691 } 27692 } 27693 function isCompatibleFamilyForHotReloading(fiber, element) { 27694 { 27695 if (resolveFamily === null) { 27696 // Hot reloading is disabled. 27697 return false; 27698 } 27699 27700 var prevType = fiber.elementType; 27701 var nextType = element.type; // If we got here, we know types aren't === equal. 27702 27703 var needsCompareFamilies = false; 27704 var $$typeofNextType = typeof nextType === 'object' && nextType !== null ? nextType.$$typeof : null; 27705 27706 switch (fiber.tag) { 27707 case ClassComponent: 27708 { 27709 if (typeof nextType === 'function') { 27710 needsCompareFamilies = true; 27711 } 27712 27713 break; 27714 } 27715 27716 case FunctionComponent: 27717 { 27718 if (typeof nextType === 'function') { 27719 needsCompareFamilies = true; 27720 } else if ($$typeofNextType === REACT_LAZY_TYPE) { 27721 // We don't know the inner type yet. 27722 // We're going to assume that the lazy inner type is stable, 27723 // and so it is sufficient to avoid reconciling it away. 27724 // We're not going to unwrap or actually use the new lazy type. 27725 needsCompareFamilies = true; 27726 } 27727 27728 break; 27729 } 27730 27731 case ForwardRef: 27732 { 27733 if ($$typeofNextType === REACT_FORWARD_REF_TYPE) { 27734 needsCompareFamilies = true; 27735 } else if ($$typeofNextType === REACT_LAZY_TYPE) { 27736 needsCompareFamilies = true; 27737 } 27738 27739 break; 27740 } 27741 27742 case MemoComponent: 27743 case SimpleMemoComponent: 27744 { 27745 if ($$typeofNextType === REACT_MEMO_TYPE) { 27746 // TODO: if it was but can no longer be simple, 27747 // we shouldn't set this. 27748 needsCompareFamilies = true; 27749 } else if ($$typeofNextType === REACT_LAZY_TYPE) { 27750 needsCompareFamilies = true; 27751 } 27752 27753 break; 27754 } 27755 27756 default: 27757 return false; 27758 } // Check if both types have a family and it's the same one. 27759 27760 27761 if (needsCompareFamilies) { 27762 // Note: memo() and forwardRef() we'll compare outer rather than inner type. 27763 // This means both of them need to be registered to preserve state. 27764 // If we unwrapped and compared the inner types for wrappers instead, 27765 // then we would risk falsely saying two separate memo(Foo) 27766 // calls are equivalent because they wrap the same Foo function. 27767 var prevFamily = resolveFamily(prevType); 27768 27769 if (prevFamily !== undefined && prevFamily === resolveFamily(nextType)) { 27770 return true; 27771 } 27772 } 27773 27774 return false; 27775 } 27776 } 27777 function markFailedErrorBoundaryForHotReloading(fiber) { 27778 { 27779 if (resolveFamily === null) { 27780 // Hot reloading is disabled. 27781 return; 27782 } 27783 27784 if (typeof WeakSet !== 'function') { 27785 return; 27786 } 27787 27788 if (failedBoundaries === null) { 27789 failedBoundaries = new WeakSet(); 27790 } 27791 27792 failedBoundaries.add(fiber); 27793 } 27794 } 27795 var scheduleRefresh = function (root, update) { 27796 { 27797 if (resolveFamily === null) { 27798 // Hot reloading is disabled. 27799 return; 27800 } 27801 27802 var staleFamilies = update.staleFamilies, 27803 updatedFamilies = update.updatedFamilies; 27804 flushPassiveEffects(); 27805 flushSync(function () { 27806 scheduleFibersWithFamiliesRecursively(root.current, updatedFamilies, staleFamilies); 27807 }); 27808 } 27809 }; 27810 var scheduleRoot = function (root, element) { 27811 { 27812 if (root.context !== emptyContextObject) { 27813 // Super edge case: root has a legacy _renderSubtree context 27814 // but we don't know the parentComponent so we can't pass it. 27815 // Just ignore. We'll delete this with _renderSubtree code path later. 27816 return; 27817 } 27818 27819 flushPassiveEffects(); 27820 flushSync(function () { 27821 updateContainer(element, root, null, null); 27822 }); 27823 } 27824 }; 27825 27826 function scheduleFibersWithFamiliesRecursively(fiber, updatedFamilies, staleFamilies) { 27827 { 27828 var alternate = fiber.alternate, 27829 child = fiber.child, 27830 sibling = fiber.sibling, 27831 tag = fiber.tag, 27832 type = fiber.type; 27833 var candidateType = null; 27834 27835 switch (tag) { 27836 case FunctionComponent: 27837 case SimpleMemoComponent: 27838 case ClassComponent: 27839 candidateType = type; 27840 break; 27841 27842 case ForwardRef: 27843 candidateType = type.render; 27844 break; 27845 } 27846 27847 if (resolveFamily === null) { 27848 throw new Error('Expected resolveFamily to be set during hot reload.'); 27849 } 27850 27851 var needsRender = false; 27852 var needsRemount = false; 27853 27854 if (candidateType !== null) { 27855 var family = resolveFamily(candidateType); 27856 27857 if (family !== undefined) { 27858 if (staleFamilies.has(family)) { 27859 needsRemount = true; 27860 } else if (updatedFamilies.has(family)) { 27861 if (tag === ClassComponent) { 27862 needsRemount = true; 27863 } else { 27864 needsRender = true; 27865 } 27866 } 27867 } 27868 } 27869 27870 if (failedBoundaries !== null) { 27871 if (failedBoundaries.has(fiber) || alternate !== null && failedBoundaries.has(alternate)) { 27872 needsRemount = true; 27873 } 27874 } 27875 27876 if (needsRemount) { 27877 fiber._debugNeedsRemount = true; 27878 } 27879 27880 if (needsRemount || needsRender) { 27881 var _root = enqueueConcurrentRenderForLane(fiber, SyncLane); 27882 27883 if (_root !== null) { 27884 scheduleUpdateOnFiber(_root, fiber, SyncLane, NoTimestamp); 27885 } 27886 } 27887 27888 if (child !== null && !needsRemount) { 27889 scheduleFibersWithFamiliesRecursively(child, updatedFamilies, staleFamilies); 27890 } 27891 27892 if (sibling !== null) { 27893 scheduleFibersWithFamiliesRecursively(sibling, updatedFamilies, staleFamilies); 27894 } 27895 } 27896 } 27897 27898 var findHostInstancesForRefresh = function (root, families) { 27899 { 27900 var hostInstances = new Set(); 27901 var types = new Set(families.map(function (family) { 27902 return family.current; 27903 })); 27904 findHostInstancesForMatchingFibersRecursively(root.current, types, hostInstances); 27905 return hostInstances; 27906 } 27907 }; 27908 27909 function findHostInstancesForMatchingFibersRecursively(fiber, types, hostInstances) { 27910 { 27911 var child = fiber.child, 27912 sibling = fiber.sibling, 27913 tag = fiber.tag, 27914 type = fiber.type; 27915 var candidateType = null; 27916 27917 switch (tag) { 27918 case FunctionComponent: 27919 case SimpleMemoComponent: 27920 case ClassComponent: 27921 candidateType = type; 27922 break; 27923 27924 case ForwardRef: 27925 candidateType = type.render; 27926 break; 27927 } 27928 27929 var didMatch = false; 27930 27931 if (candidateType !== null) { 27932 if (types.has(candidateType)) { 27933 didMatch = true; 27934 } 27935 } 27936 27937 if (didMatch) { 27938 // We have a match. This only drills down to the closest host components. 27939 // There's no need to search deeper because for the purpose of giving 27940 // visual feedback, "flashing" outermost parent rectangles is sufficient. 27941 findHostInstancesForFiberShallowly(fiber, hostInstances); 27942 } else { 27943 // If there's no match, maybe there will be one further down in the child tree. 27944 if (child !== null) { 27945 findHostInstancesForMatchingFibersRecursively(child, types, hostInstances); 27946 } 27947 } 27948 27949 if (sibling !== null) { 27950 findHostInstancesForMatchingFibersRecursively(sibling, types, hostInstances); 27951 } 27952 } 27953 } 27954 27955 function findHostInstancesForFiberShallowly(fiber, hostInstances) { 27956 { 27957 var foundHostInstances = findChildHostInstancesForFiberShallowly(fiber, hostInstances); 27958 27959 if (foundHostInstances) { 27960 return; 27961 } // If we didn't find any host children, fallback to closest host parent. 27962 27963 27964 var node = fiber; 27965 27966 while (true) { 27967 switch (node.tag) { 27968 case HostComponent: 27969 hostInstances.add(node.stateNode); 27970 return; 27971 27972 case HostPortal: 27973 hostInstances.add(node.stateNode.containerInfo); 27974 return; 27975 27976 case HostRoot: 27977 hostInstances.add(node.stateNode.containerInfo); 27978 return; 27979 } 27980 27981 if (node.return === null) { 27982 throw new Error('Expected to reach root first.'); 27983 } 27984 27985 node = node.return; 27986 } 27987 } 27988 } 27989 27990 function findChildHostInstancesForFiberShallowly(fiber, hostInstances) { 27991 { 27992 var node = fiber; 27993 var foundHostInstances = false; 27994 27995 while (true) { 27996 if (node.tag === HostComponent) { 27997 // We got a match. 27998 foundHostInstances = true; 27999 hostInstances.add(node.stateNode); // There may still be more, so keep searching. 28000 } else if (node.child !== null) { 28001 node.child.return = node; 28002 node = node.child; 28003 continue; 28004 } 28005 28006 if (node === fiber) { 28007 return foundHostInstances; 28008 } 28009 28010 while (node.sibling === null) { 28011 if (node.return === null || node.return === fiber) { 28012 return foundHostInstances; 28013 } 28014 28015 node = node.return; 28016 } 28017 28018 node.sibling.return = node.return; 28019 node = node.sibling; 28020 } 28021 } 28022 28023 return false; 28024 } 28025 28026 var hasBadMapPolyfill; 28027 28028 { 28029 hasBadMapPolyfill = false; 28030 28031 try { 28032 var nonExtensibleObject = Object.preventExtensions({}); 28033 /* eslint-disable no-new */ 28034 28035 new Map([[nonExtensibleObject, null]]); 28036 new Set([nonExtensibleObject]); 28037 /* eslint-enable no-new */ 28038 } catch (e) { 28039 // TODO: Consider warning about bad polyfills 28040 hasBadMapPolyfill = true; 28041 } 28042 } 28043 28044 function FiberNode(tag, pendingProps, key, mode) { 28045 // Instance 28046 this.tag = tag; 28047 this.key = key; 28048 this.elementType = null; 28049 this.type = null; 28050 this.stateNode = null; // Fiber 28051 28052 this.return = null; 28053 this.child = null; 28054 this.sibling = null; 28055 this.index = 0; 28056 this.ref = null; 28057 this.pendingProps = pendingProps; 28058 this.memoizedProps = null; 28059 this.updateQueue = null; 28060 this.memoizedState = null; 28061 this.dependencies = null; 28062 this.mode = mode; // Effects 28063 28064 this.flags = NoFlags; 28065 this.subtreeFlags = NoFlags; 28066 this.deletions = null; 28067 this.lanes = NoLanes; 28068 this.childLanes = NoLanes; 28069 this.alternate = null; 28070 28071 { 28072 // Note: The following is done to avoid a v8 performance cliff. 28073 // 28074 // Initializing the fields below to smis and later updating them with 28075 // double values will cause Fibers to end up having separate shapes. 28076 // This behavior/bug has something to do with Object.preventExtension(). 28077 // Fortunately this only impacts DEV builds. 28078 // Unfortunately it makes React unusably slow for some applications. 28079 // To work around this, initialize the fields below with doubles. 28080 // 28081 // Learn more about this here: 28082 // https://github.com/facebook/react/issues/14365 28083 // https://bugs.chromium.org/p/v8/issues/detail?id=8538 28084 this.actualDuration = Number.NaN; 28085 this.actualStartTime = Number.NaN; 28086 this.selfBaseDuration = Number.NaN; 28087 this.treeBaseDuration = Number.NaN; // It's okay to replace the initial doubles with smis after initialization. 28088 // This won't trigger the performance cliff mentioned above, 28089 // and it simplifies other profiler code (including DevTools). 28090 28091 this.actualDuration = 0; 28092 this.actualStartTime = -1; 28093 this.selfBaseDuration = 0; 28094 this.treeBaseDuration = 0; 28095 } 28096 28097 { 28098 // This isn't directly used but is handy for debugging internals: 28099 this._debugSource = null; 28100 this._debugOwner = null; 28101 this._debugNeedsRemount = false; 28102 this._debugHookTypes = null; 28103 28104 if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') { 28105 Object.preventExtensions(this); 28106 } 28107 } 28108 } // This is a constructor function, rather than a POJO constructor, still 28109 // please ensure we do the following: 28110 // 1) Nobody should add any instance methods on this. Instance methods can be 28111 // more difficult to predict when they get optimized and they are almost 28112 // never inlined properly in static compilers. 28113 // 2) Nobody should rely on `instanceof Fiber` for type testing. We should 28114 // always know when it is a fiber. 28115 // 3) We might want to experiment with using numeric keys since they are easier 28116 // to optimize in a non-JIT environment. 28117 // 4) We can easily go from a constructor to a createFiber object literal if that 28118 // is faster. 28119 // 5) It should be easy to port this to a C struct and keep a C implementation 28120 // compatible. 28121 28122 28123 var createFiber = function (tag, pendingProps, key, mode) { 28124 // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors 28125 return new FiberNode(tag, pendingProps, key, mode); 28126 }; 28127 28128 function shouldConstruct$1(Component) { 28129 var prototype = Component.prototype; 28130 return !!(prototype && prototype.isReactComponent); 28131 } 28132 28133 function isSimpleFunctionComponent(type) { 28134 return typeof type === 'function' && !shouldConstruct$1(type) && type.defaultProps === undefined; 28135 } 28136 function resolveLazyComponentTag(Component) { 28137 if (typeof Component === 'function') { 28138 return shouldConstruct$1(Component) ? ClassComponent : FunctionComponent; 28139 } else if (Component !== undefined && Component !== null) { 28140 var $$typeof = Component.$$typeof; 28141 28142 if ($$typeof === REACT_FORWARD_REF_TYPE) { 28143 return ForwardRef; 28144 } 28145 28146 if ($$typeof === REACT_MEMO_TYPE) { 28147 return MemoComponent; 28148 } 28149 } 28150 28151 return IndeterminateComponent; 28152 } // This is used to create an alternate fiber to do work on. 28153 28154 function createWorkInProgress(current, pendingProps) { 28155 var workInProgress = current.alternate; 28156 28157 if (workInProgress === null) { 28158 // We use a double buffering pooling technique because we know that we'll 28159 // only ever need at most two versions of a tree. We pool the "other" unused 28160 // node that we're free to reuse. This is lazily created to avoid allocating 28161 // extra objects for things that are never updated. It also allow us to 28162 // reclaim the extra memory if needed. 28163 workInProgress = createFiber(current.tag, pendingProps, current.key, current.mode); 28164 workInProgress.elementType = current.elementType; 28165 workInProgress.type = current.type; 28166 workInProgress.stateNode = current.stateNode; 28167 28168 { 28169 // DEV-only fields 28170 workInProgress._debugSource = current._debugSource; 28171 workInProgress._debugOwner = current._debugOwner; 28172 workInProgress._debugHookTypes = current._debugHookTypes; 28173 } 28174 28175 workInProgress.alternate = current; 28176 current.alternate = workInProgress; 28177 } else { 28178 workInProgress.pendingProps = pendingProps; // Needed because Blocks store data on type. 28179 28180 workInProgress.type = current.type; // We already have an alternate. 28181 // Reset the effect tag. 28182 28183 workInProgress.flags = NoFlags; // The effects are no longer valid. 28184 28185 workInProgress.subtreeFlags = NoFlags; 28186 workInProgress.deletions = null; 28187 28188 { 28189 // We intentionally reset, rather than copy, actualDuration & actualStartTime. 28190 // This prevents time from endlessly accumulating in new commits. 28191 // This has the downside of resetting values for different priority renders, 28192 // But works for yielding (the common case) and should support resuming. 28193 workInProgress.actualDuration = 0; 28194 workInProgress.actualStartTime = -1; 28195 } 28196 } // Reset all effects except static ones. 28197 // Static effects are not specific to a render. 28198 28199 28200 workInProgress.flags = current.flags & StaticMask; 28201 workInProgress.childLanes = current.childLanes; 28202 workInProgress.lanes = current.lanes; 28203 workInProgress.child = current.child; 28204 workInProgress.memoizedProps = current.memoizedProps; 28205 workInProgress.memoizedState = current.memoizedState; 28206 workInProgress.updateQueue = current.updateQueue; // Clone the dependencies object. This is mutated during the render phase, so 28207 // it cannot be shared with the current fiber. 28208 28209 var currentDependencies = current.dependencies; 28210 workInProgress.dependencies = currentDependencies === null ? null : { 28211 lanes: currentDependencies.lanes, 28212 firstContext: currentDependencies.firstContext 28213 }; // These will be overridden during the parent's reconciliation 28214 28215 workInProgress.sibling = current.sibling; 28216 workInProgress.index = current.index; 28217 workInProgress.ref = current.ref; 28218 28219 { 28220 workInProgress.selfBaseDuration = current.selfBaseDuration; 28221 workInProgress.treeBaseDuration = current.treeBaseDuration; 28222 } 28223 28224 { 28225 workInProgress._debugNeedsRemount = current._debugNeedsRemount; 28226 28227 switch (workInProgress.tag) { 28228 case IndeterminateComponent: 28229 case FunctionComponent: 28230 case SimpleMemoComponent: 28231 workInProgress.type = resolveFunctionForHotReloading(current.type); 28232 break; 28233 28234 case ClassComponent: 28235 workInProgress.type = resolveClassForHotReloading(current.type); 28236 break; 28237 28238 case ForwardRef: 28239 workInProgress.type = resolveForwardRefForHotReloading(current.type); 28240 break; 28241 } 28242 } 28243 28244 return workInProgress; 28245 } // Used to reuse a Fiber for a second pass. 28246 28247 function resetWorkInProgress(workInProgress, renderLanes) { 28248 // This resets the Fiber to what createFiber or createWorkInProgress would 28249 // have set the values to before during the first pass. Ideally this wouldn't 28250 // be necessary but unfortunately many code paths reads from the workInProgress 28251 // when they should be reading from current and writing to workInProgress. 28252 // We assume pendingProps, index, key, ref, return are still untouched to 28253 // avoid doing another reconciliation. 28254 // Reset the effect flags but keep any Placement tags, since that's something 28255 // that child fiber is setting, not the reconciliation. 28256 workInProgress.flags &= StaticMask | Placement; // The effects are no longer valid. 28257 28258 var current = workInProgress.alternate; 28259 28260 if (current === null) { 28261 // Reset to createFiber's initial values. 28262 workInProgress.childLanes = NoLanes; 28263 workInProgress.lanes = renderLanes; 28264 workInProgress.child = null; 28265 workInProgress.subtreeFlags = NoFlags; 28266 workInProgress.memoizedProps = null; 28267 workInProgress.memoizedState = null; 28268 workInProgress.updateQueue = null; 28269 workInProgress.dependencies = null; 28270 workInProgress.stateNode = null; 28271 28272 { 28273 // Note: We don't reset the actualTime counts. It's useful to accumulate 28274 // actual time across multiple render passes. 28275 workInProgress.selfBaseDuration = 0; 28276 workInProgress.treeBaseDuration = 0; 28277 } 28278 } else { 28279 // Reset to the cloned values that createWorkInProgress would've. 28280 workInProgress.childLanes = current.childLanes; 28281 workInProgress.lanes = current.lanes; 28282 workInProgress.child = current.child; 28283 workInProgress.subtreeFlags = NoFlags; 28284 workInProgress.deletions = null; 28285 workInProgress.memoizedProps = current.memoizedProps; 28286 workInProgress.memoizedState = current.memoizedState; 28287 workInProgress.updateQueue = current.updateQueue; // Needed because Blocks store data on type. 28288 28289 workInProgress.type = current.type; // Clone the dependencies object. This is mutated during the render phase, so 28290 // it cannot be shared with the current fiber. 28291 28292 var currentDependencies = current.dependencies; 28293 workInProgress.dependencies = currentDependencies === null ? null : { 28294 lanes: currentDependencies.lanes, 28295 firstContext: currentDependencies.firstContext 28296 }; 28297 28298 { 28299 // Note: We don't reset the actualTime counts. It's useful to accumulate 28300 // actual time across multiple render passes. 28301 workInProgress.selfBaseDuration = current.selfBaseDuration; 28302 workInProgress.treeBaseDuration = current.treeBaseDuration; 28303 } 28304 } 28305 28306 return workInProgress; 28307 } 28308 function createHostRootFiber(tag, isStrictMode, concurrentUpdatesByDefaultOverride) { 28309 var mode; 28310 28311 if (tag === ConcurrentRoot) { 28312 mode = ConcurrentMode; 28313 28314 if (isStrictMode === true) { 28315 mode |= StrictLegacyMode; 28316 28317 { 28318 mode |= StrictEffectsMode; 28319 } 28320 } 28321 } else { 28322 mode = NoMode; 28323 } 28324 28325 if ( isDevToolsPresent) { 28326 // Always collect profile timings when DevTools are present. 28327 // This enables DevTools to start capturing timing at any point– 28328 // Without some nodes in the tree having empty base times. 28329 mode |= ProfileMode; 28330 } 28331 28332 return createFiber(HostRoot, null, null, mode); 28333 } 28334 function createFiberFromTypeAndProps(type, // React$ElementType 28335 key, pendingProps, owner, mode, lanes) { 28336 var fiberTag = IndeterminateComponent; // The resolved type is set if we know what the final type will be. I.e. it's not lazy. 28337 28338 var resolvedType = type; 28339 28340 if (typeof type === 'function') { 28341 if (shouldConstruct$1(type)) { 28342 fiberTag = ClassComponent; 28343 28344 { 28345 resolvedType = resolveClassForHotReloading(resolvedType); 28346 } 28347 } else { 28348 { 28349 resolvedType = resolveFunctionForHotReloading(resolvedType); 28350 } 28351 } 28352 } else if (typeof type === 'string') { 28353 fiberTag = HostComponent; 28354 } else { 28355 getTag: switch (type) { 28356 case REACT_FRAGMENT_TYPE: 28357 return createFiberFromFragment(pendingProps.children, mode, lanes, key); 28358 28359 case REACT_STRICT_MODE_TYPE: 28360 fiberTag = Mode; 28361 mode |= StrictLegacyMode; 28362 28363 if ( (mode & ConcurrentMode) !== NoMode) { 28364 // Strict effects should never run on legacy roots 28365 mode |= StrictEffectsMode; 28366 } 28367 28368 break; 28369 28370 case REACT_PROFILER_TYPE: 28371 return createFiberFromProfiler(pendingProps, mode, lanes, key); 28372 28373 case REACT_SUSPENSE_TYPE: 28374 return createFiberFromSuspense(pendingProps, mode, lanes, key); 28375 28376 case REACT_SUSPENSE_LIST_TYPE: 28377 return createFiberFromSuspenseList(pendingProps, mode, lanes, key); 28378 28379 case REACT_OFFSCREEN_TYPE: 28380 return createFiberFromOffscreen(pendingProps, mode, lanes, key); 28381 28382 case REACT_LEGACY_HIDDEN_TYPE: 28383 28384 // eslint-disable-next-line no-fallthrough 28385 28386 case REACT_SCOPE_TYPE: 28387 28388 // eslint-disable-next-line no-fallthrough 28389 28390 case REACT_CACHE_TYPE: 28391 28392 // eslint-disable-next-line no-fallthrough 28393 28394 case REACT_TRACING_MARKER_TYPE: 28395 28396 // eslint-disable-next-line no-fallthrough 28397 28398 case REACT_DEBUG_TRACING_MODE_TYPE: 28399 28400 // eslint-disable-next-line no-fallthrough 28401 28402 default: 28403 { 28404 if (typeof type === 'object' && type !== null) { 28405 switch (type.$$typeof) { 28406 case REACT_PROVIDER_TYPE: 28407 fiberTag = ContextProvider; 28408 break getTag; 28409 28410 case REACT_CONTEXT_TYPE: 28411 // This is a consumer 28412 fiberTag = ContextConsumer; 28413 break getTag; 28414 28415 case REACT_FORWARD_REF_TYPE: 28416 fiberTag = ForwardRef; 28417 28418 { 28419 resolvedType = resolveForwardRefForHotReloading(resolvedType); 28420 } 28421 28422 break getTag; 28423 28424 case REACT_MEMO_TYPE: 28425 fiberTag = MemoComponent; 28426 break getTag; 28427 28428 case REACT_LAZY_TYPE: 28429 fiberTag = LazyComponent; 28430 resolvedType = null; 28431 break getTag; 28432 } 28433 } 28434 28435 var info = ''; 28436 28437 { 28438 if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) { 28439 info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and " + 'named imports.'; 28440 } 28441 28442 var ownerName = owner ? getComponentNameFromFiber(owner) : null; 28443 28444 if (ownerName) { 28445 info += '\n\nCheck the render method of `' + ownerName + '`.'; 28446 } 28447 } 28448 28449 throw new Error('Element type is invalid: expected a string (for built-in ' + 'components) or a class/function (for composite components) ' + ("but got: " + (type == null ? type : typeof type) + "." + info)); 28450 } 28451 } 28452 } 28453 28454 var fiber = createFiber(fiberTag, pendingProps, key, mode); 28455 fiber.elementType = type; 28456 fiber.type = resolvedType; 28457 fiber.lanes = lanes; 28458 28459 { 28460 fiber._debugOwner = owner; 28461 } 28462 28463 return fiber; 28464 } 28465 function createFiberFromElement(element, mode, lanes) { 28466 var owner = null; 28467 28468 { 28469 owner = element._owner; 28470 } 28471 28472 var type = element.type; 28473 var key = element.key; 28474 var pendingProps = element.props; 28475 var fiber = createFiberFromTypeAndProps(type, key, pendingProps, owner, mode, lanes); 28476 28477 { 28478 fiber._debugSource = element._source; 28479 fiber._debugOwner = element._owner; 28480 } 28481 28482 return fiber; 28483 } 28484 function createFiberFromFragment(elements, mode, lanes, key) { 28485 var fiber = createFiber(Fragment, elements, key, mode); 28486 fiber.lanes = lanes; 28487 return fiber; 28488 } 28489 28490 function createFiberFromProfiler(pendingProps, mode, lanes, key) { 28491 { 28492 if (typeof pendingProps.id !== 'string') { 28493 error('Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.', typeof pendingProps.id); 28494 } 28495 } 28496 28497 var fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode); 28498 fiber.elementType = REACT_PROFILER_TYPE; 28499 fiber.lanes = lanes; 28500 28501 { 28502 fiber.stateNode = { 28503 effectDuration: 0, 28504 passiveEffectDuration: 0 28505 }; 28506 } 28507 28508 return fiber; 28509 } 28510 28511 function createFiberFromSuspense(pendingProps, mode, lanes, key) { 28512 var fiber = createFiber(SuspenseComponent, pendingProps, key, mode); 28513 fiber.elementType = REACT_SUSPENSE_TYPE; 28514 fiber.lanes = lanes; 28515 return fiber; 28516 } 28517 function createFiberFromSuspenseList(pendingProps, mode, lanes, key) { 28518 var fiber = createFiber(SuspenseListComponent, pendingProps, key, mode); 28519 fiber.elementType = REACT_SUSPENSE_LIST_TYPE; 28520 fiber.lanes = lanes; 28521 return fiber; 28522 } 28523 function createFiberFromOffscreen(pendingProps, mode, lanes, key) { 28524 var fiber = createFiber(OffscreenComponent, pendingProps, key, mode); 28525 fiber.elementType = REACT_OFFSCREEN_TYPE; 28526 fiber.lanes = lanes; 28527 var primaryChildInstance = { 28528 isHidden: false 28529 }; 28530 fiber.stateNode = primaryChildInstance; 28531 return fiber; 28532 } 28533 function createFiberFromText(content, mode, lanes) { 28534 var fiber = createFiber(HostText, content, null, mode); 28535 fiber.lanes = lanes; 28536 return fiber; 28537 } 28538 function createFiberFromHostInstanceForDeletion() { 28539 var fiber = createFiber(HostComponent, null, null, NoMode); 28540 fiber.elementType = 'DELETED'; 28541 return fiber; 28542 } 28543 function createFiberFromDehydratedFragment(dehydratedNode) { 28544 var fiber = createFiber(DehydratedFragment, null, null, NoMode); 28545 fiber.stateNode = dehydratedNode; 28546 return fiber; 28547 } 28548 function createFiberFromPortal(portal, mode, lanes) { 28549 var pendingProps = portal.children !== null ? portal.children : []; 28550 var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); 28551 fiber.lanes = lanes; 28552 fiber.stateNode = { 28553 containerInfo: portal.containerInfo, 28554 pendingChildren: null, 28555 // Used by persistent updates 28556 implementation: portal.implementation 28557 }; 28558 return fiber; 28559 } // Used for stashing WIP properties to replay failed work in DEV. 28560 28561 function assignFiberPropertiesInDEV(target, source) { 28562 if (target === null) { 28563 // This Fiber's initial properties will always be overwritten. 28564 // We only use a Fiber to ensure the same hidden class so DEV isn't slow. 28565 target = createFiber(IndeterminateComponent, null, null, NoMode); 28566 } // This is intentionally written as a list of all properties. 28567 // We tried to use Object.assign() instead but this is called in 28568 // the hottest path, and Object.assign() was too slow: 28569 // https://github.com/facebook/react/issues/12502 28570 // This code is DEV-only so size is not a concern. 28571 28572 28573 target.tag = source.tag; 28574 target.key = source.key; 28575 target.elementType = source.elementType; 28576 target.type = source.type; 28577 target.stateNode = source.stateNode; 28578 target.return = source.return; 28579 target.child = source.child; 28580 target.sibling = source.sibling; 28581 target.index = source.index; 28582 target.ref = source.ref; 28583 target.pendingProps = source.pendingProps; 28584 target.memoizedProps = source.memoizedProps; 28585 target.updateQueue = source.updateQueue; 28586 target.memoizedState = source.memoizedState; 28587 target.dependencies = source.dependencies; 28588 target.mode = source.mode; 28589 target.flags = source.flags; 28590 target.subtreeFlags = source.subtreeFlags; 28591 target.deletions = source.deletions; 28592 target.lanes = source.lanes; 28593 target.childLanes = source.childLanes; 28594 target.alternate = source.alternate; 28595 28596 { 28597 target.actualDuration = source.actualDuration; 28598 target.actualStartTime = source.actualStartTime; 28599 target.selfBaseDuration = source.selfBaseDuration; 28600 target.treeBaseDuration = source.treeBaseDuration; 28601 } 28602 28603 target._debugSource = source._debugSource; 28604 target._debugOwner = source._debugOwner; 28605 target._debugNeedsRemount = source._debugNeedsRemount; 28606 target._debugHookTypes = source._debugHookTypes; 28607 return target; 28608 } 28609 28610 function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError) { 28611 this.tag = tag; 28612 this.containerInfo = containerInfo; 28613 this.pendingChildren = null; 28614 this.current = null; 28615 this.pingCache = null; 28616 this.finishedWork = null; 28617 this.timeoutHandle = noTimeout; 28618 this.context = null; 28619 this.pendingContext = null; 28620 this.callbackNode = null; 28621 this.callbackPriority = NoLane; 28622 this.eventTimes = createLaneMap(NoLanes); 28623 this.expirationTimes = createLaneMap(NoTimestamp); 28624 this.pendingLanes = NoLanes; 28625 this.suspendedLanes = NoLanes; 28626 this.pingedLanes = NoLanes; 28627 this.expiredLanes = NoLanes; 28628 this.mutableReadLanes = NoLanes; 28629 this.finishedLanes = NoLanes; 28630 this.entangledLanes = NoLanes; 28631 this.entanglements = createLaneMap(NoLanes); 28632 this.identifierPrefix = identifierPrefix; 28633 this.onRecoverableError = onRecoverableError; 28634 28635 { 28636 this.mutableSourceEagerHydrationData = null; 28637 } 28638 28639 { 28640 this.effectDuration = 0; 28641 this.passiveEffectDuration = 0; 28642 } 28643 28644 { 28645 this.memoizedUpdaters = new Set(); 28646 var pendingUpdatersLaneMap = this.pendingUpdatersLaneMap = []; 28647 28648 for (var _i = 0; _i < TotalLanes; _i++) { 28649 pendingUpdatersLaneMap.push(new Set()); 28650 } 28651 } 28652 28653 { 28654 switch (tag) { 28655 case ConcurrentRoot: 28656 this._debugRootType = hydrate ? 'hydrateRoot()' : 'createRoot()'; 28657 break; 28658 28659 case LegacyRoot: 28660 this._debugRootType = hydrate ? 'hydrate()' : 'render()'; 28661 break; 28662 } 28663 } 28664 } 28665 28666 function createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, // TODO: We have several of these arguments that are conceptually part of the 28667 // host config, but because they are passed in at runtime, we have to thread 28668 // them through the root constructor. Perhaps we should put them all into a 28669 // single type, like a DynamicHostConfig that is defined by the renderer. 28670 identifierPrefix, onRecoverableError, transitionCallbacks) { 28671 var root = new FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onRecoverableError); 28672 // stateNode is any. 28673 28674 28675 var uninitializedFiber = createHostRootFiber(tag, isStrictMode); 28676 root.current = uninitializedFiber; 28677 uninitializedFiber.stateNode = root; 28678 28679 { 28680 var _initialState = { 28681 element: initialChildren, 28682 isDehydrated: hydrate, 28683 cache: null, 28684 // not enabled yet 28685 transitions: null, 28686 pendingSuspenseBoundaries: null 28687 }; 28688 uninitializedFiber.memoizedState = _initialState; 28689 } 28690 28691 initializeUpdateQueue(uninitializedFiber); 28692 return root; 28693 } 28694 28695 var ReactVersion = '18.2.0'; 28696 28697 function createPortal(children, containerInfo, // TODO: figure out the API for cross-renderer implementation. 28698 implementation) { 28699 var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; 28700 28701 { 28702 checkKeyStringCoercion(key); 28703 } 28704 28705 return { 28706 // This tag allow us to uniquely identify this as a React Portal 28707 $$typeof: REACT_PORTAL_TYPE, 28708 key: key == null ? null : '' + key, 28709 children: children, 28710 containerInfo: containerInfo, 28711 implementation: implementation 28712 }; 28713 } 28714 28715 var didWarnAboutNestedUpdates; 28716 var didWarnAboutFindNodeInStrictMode; 28717 28718 { 28719 didWarnAboutNestedUpdates = false; 28720 didWarnAboutFindNodeInStrictMode = {}; 28721 } 28722 28723 function getContextForSubtree(parentComponent) { 28724 if (!parentComponent) { 28725 return emptyContextObject; 28726 } 28727 28728 var fiber = get(parentComponent); 28729 var parentContext = findCurrentUnmaskedContext(fiber); 28730 28731 if (fiber.tag === ClassComponent) { 28732 var Component = fiber.type; 28733 28734 if (isContextProvider(Component)) { 28735 return processChildContext(fiber, Component, parentContext); 28736 } 28737 } 28738 28739 return parentContext; 28740 } 28741 28742 function findHostInstanceWithWarning(component, methodName) { 28743 { 28744 var fiber = get(component); 28745 28746 if (fiber === undefined) { 28747 if (typeof component.render === 'function') { 28748 throw new Error('Unable to find node on an unmounted component.'); 28749 } else { 28750 var keys = Object.keys(component).join(','); 28751 throw new Error("Argument appears to not be a ReactComponent. Keys: " + keys); 28752 } 28753 } 28754 28755 var hostFiber = findCurrentHostFiber(fiber); 28756 28757 if (hostFiber === null) { 28758 return null; 28759 } 28760 28761 if (hostFiber.mode & StrictLegacyMode) { 28762 var componentName = getComponentNameFromFiber(fiber) || 'Component'; 28763 28764 if (!didWarnAboutFindNodeInStrictMode[componentName]) { 28765 didWarnAboutFindNodeInStrictMode[componentName] = true; 28766 var previousFiber = current; 28767 28768 try { 28769 setCurrentFiber(hostFiber); 28770 28771 if (fiber.mode & StrictLegacyMode) { 28772 error('%s is deprecated in StrictMode. ' + '%s was passed an instance of %s which is inside StrictMode. ' + 'Instead, add a ref directly to the element you want to reference. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-find-node', methodName, methodName, componentName); 28773 } else { 28774 error('%s is deprecated in StrictMode. ' + '%s was passed an instance of %s which renders StrictMode children. ' + 'Instead, add a ref directly to the element you want to reference. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-find-node', methodName, methodName, componentName); 28775 } 28776 } finally { 28777 // Ideally this should reset to previous but this shouldn't be called in 28778 // render and there's another warning for that anyway. 28779 if (previousFiber) { 28780 setCurrentFiber(previousFiber); 28781 } else { 28782 resetCurrentFiber(); 28783 } 28784 } 28785 } 28786 } 28787 28788 return hostFiber.stateNode; 28789 } 28790 } 28791 28792 function createContainer(containerInfo, tag, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError, transitionCallbacks) { 28793 var hydrate = false; 28794 var initialChildren = null; 28795 return createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); 28796 } 28797 function createHydrationContainer(initialChildren, // TODO: Remove `callback` when we delete legacy mode. 28798 callback, containerInfo, tag, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError, transitionCallbacks) { 28799 var hydrate = true; 28800 var root = createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); // TODO: Move this to FiberRoot constructor 28801 28802 root.context = getContextForSubtree(null); // Schedule the initial render. In a hydration root, this is different from 28803 // a regular update because the initial render must match was was rendered 28804 // on the server. 28805 // NOTE: This update intentionally doesn't have a payload. We're only using 28806 // the update to schedule work on the root fiber (and, for legacy roots, to 28807 // enqueue the callback if one is provided). 28808 28809 var current = root.current; 28810 var eventTime = requestEventTime(); 28811 var lane = requestUpdateLane(current); 28812 var update = createUpdate(eventTime, lane); 28813 update.callback = callback !== undefined && callback !== null ? callback : null; 28814 enqueueUpdate(current, update, lane); 28815 scheduleInitialHydrationOnRoot(root, lane, eventTime); 28816 return root; 28817 } 28818 function updateContainer(element, container, parentComponent, callback) { 28819 { 28820 onScheduleRoot(container, element); 28821 } 28822 28823 var current$1 = container.current; 28824 var eventTime = requestEventTime(); 28825 var lane = requestUpdateLane(current$1); 28826 28827 { 28828 markRenderScheduled(lane); 28829 } 28830 28831 var context = getContextForSubtree(parentComponent); 28832 28833 if (container.context === null) { 28834 container.context = context; 28835 } else { 28836 container.pendingContext = context; 28837 } 28838 28839 { 28840 if (isRendering && current !== null && !didWarnAboutNestedUpdates) { 28841 didWarnAboutNestedUpdates = true; 28842 28843 error('Render methods should be a pure function of props and state; ' + 'triggering nested component updates from render is not allowed. ' + 'If necessary, trigger nested updates in componentDidUpdate.\n\n' + 'Check the render method of %s.', getComponentNameFromFiber(current) || 'Unknown'); 28844 } 28845 } 28846 28847 var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property 28848 // being called "element". 28849 28850 update.payload = { 28851 element: element 28852 }; 28853 callback = callback === undefined ? null : callback; 28854 28855 if (callback !== null) { 28856 { 28857 if (typeof callback !== 'function') { 28858 error('render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback); 28859 } 28860 } 28861 28862 update.callback = callback; 28863 } 28864 28865 var root = enqueueUpdate(current$1, update, lane); 28866 28867 if (root !== null) { 28868 scheduleUpdateOnFiber(root, current$1, lane, eventTime); 28869 entangleTransitions(root, current$1, lane); 28870 } 28871 28872 return lane; 28873 } 28874 function getPublicRootInstance(container) { 28875 var containerFiber = container.current; 28876 28877 if (!containerFiber.child) { 28878 return null; 28879 } 28880 28881 switch (containerFiber.child.tag) { 28882 case HostComponent: 28883 return getPublicInstance(containerFiber.child.stateNode); 28884 28885 default: 28886 return containerFiber.child.stateNode; 28887 } 28888 } 28889 function attemptSynchronousHydration$1(fiber) { 28890 switch (fiber.tag) { 28891 case HostRoot: 28892 { 28893 var root = fiber.stateNode; 28894 28895 if (isRootDehydrated(root)) { 28896 // Flush the first scheduled "update". 28897 var lanes = getHighestPriorityPendingLanes(root); 28898 flushRoot(root, lanes); 28899 } 28900 28901 break; 28902 } 28903 28904 case SuspenseComponent: 28905 { 28906 flushSync(function () { 28907 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 28908 28909 if (root !== null) { 28910 var eventTime = requestEventTime(); 28911 scheduleUpdateOnFiber(root, fiber, SyncLane, eventTime); 28912 } 28913 }); // If we're still blocked after this, we need to increase 28914 // the priority of any promises resolving within this 28915 // boundary so that they next attempt also has higher pri. 28916 28917 var retryLane = SyncLane; 28918 markRetryLaneIfNotHydrated(fiber, retryLane); 28919 break; 28920 } 28921 } 28922 } 28923 28924 function markRetryLaneImpl(fiber, retryLane) { 28925 var suspenseState = fiber.memoizedState; 28926 28927 if (suspenseState !== null && suspenseState.dehydrated !== null) { 28928 suspenseState.retryLane = higherPriorityLane(suspenseState.retryLane, retryLane); 28929 } 28930 } // Increases the priority of thenables when they resolve within this boundary. 28931 28932 28933 function markRetryLaneIfNotHydrated(fiber, retryLane) { 28934 markRetryLaneImpl(fiber, retryLane); 28935 var alternate = fiber.alternate; 28936 28937 if (alternate) { 28938 markRetryLaneImpl(alternate, retryLane); 28939 } 28940 } 28941 function attemptContinuousHydration$1(fiber) { 28942 if (fiber.tag !== SuspenseComponent) { 28943 // We ignore HostRoots here because we can't increase 28944 // their priority and they should not suspend on I/O, 28945 // since you have to wrap anything that might suspend in 28946 // Suspense. 28947 return; 28948 } 28949 28950 var lane = SelectiveHydrationLane; 28951 var root = enqueueConcurrentRenderForLane(fiber, lane); 28952 28953 if (root !== null) { 28954 var eventTime = requestEventTime(); 28955 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 28956 } 28957 28958 markRetryLaneIfNotHydrated(fiber, lane); 28959 } 28960 function attemptHydrationAtCurrentPriority$1(fiber) { 28961 if (fiber.tag !== SuspenseComponent) { 28962 // We ignore HostRoots here because we can't increase 28963 // their priority other than synchronously flush it. 28964 return; 28965 } 28966 28967 var lane = requestUpdateLane(fiber); 28968 var root = enqueueConcurrentRenderForLane(fiber, lane); 28969 28970 if (root !== null) { 28971 var eventTime = requestEventTime(); 28972 scheduleUpdateOnFiber(root, fiber, lane, eventTime); 28973 } 28974 28975 markRetryLaneIfNotHydrated(fiber, lane); 28976 } 28977 function findHostInstanceWithNoPortals(fiber) { 28978 var hostFiber = findCurrentHostFiberWithNoPortals(fiber); 28979 28980 if (hostFiber === null) { 28981 return null; 28982 } 28983 28984 return hostFiber.stateNode; 28985 } 28986 28987 var shouldErrorImpl = function (fiber) { 28988 return null; 28989 }; 28990 28991 function shouldError(fiber) { 28992 return shouldErrorImpl(fiber); 28993 } 28994 28995 var shouldSuspendImpl = function (fiber) { 28996 return false; 28997 }; 28998 28999 function shouldSuspend(fiber) { 29000 return shouldSuspendImpl(fiber); 29001 } 29002 var overrideHookState = null; 29003 var overrideHookStateDeletePath = null; 29004 var overrideHookStateRenamePath = null; 29005 var overrideProps = null; 29006 var overridePropsDeletePath = null; 29007 var overridePropsRenamePath = null; 29008 var scheduleUpdate = null; 29009 var setErrorHandler = null; 29010 var setSuspenseHandler = null; 29011 29012 { 29013 var copyWithDeleteImpl = function (obj, path, index) { 29014 var key = path[index]; 29015 var updated = isArray(obj) ? obj.slice() : assign({}, obj); 29016 29017 if (index + 1 === path.length) { 29018 if (isArray(updated)) { 29019 updated.splice(key, 1); 29020 } else { 29021 delete updated[key]; 29022 } 29023 29024 return updated; 29025 } // $FlowFixMe number or string is fine here 29026 29027 29028 updated[key] = copyWithDeleteImpl(obj[key], path, index + 1); 29029 return updated; 29030 }; 29031 29032 var copyWithDelete = function (obj, path) { 29033 return copyWithDeleteImpl(obj, path, 0); 29034 }; 29035 29036 var copyWithRenameImpl = function (obj, oldPath, newPath, index) { 29037 var oldKey = oldPath[index]; 29038 var updated = isArray(obj) ? obj.slice() : assign({}, obj); 29039 29040 if (index + 1 === oldPath.length) { 29041 var newKey = newPath[index]; // $FlowFixMe number or string is fine here 29042 29043 updated[newKey] = updated[oldKey]; 29044 29045 if (isArray(updated)) { 29046 updated.splice(oldKey, 1); 29047 } else { 29048 delete updated[oldKey]; 29049 } 29050 } else { 29051 // $FlowFixMe number or string is fine here 29052 updated[oldKey] = copyWithRenameImpl( // $FlowFixMe number or string is fine here 29053 obj[oldKey], oldPath, newPath, index + 1); 29054 } 29055 29056 return updated; 29057 }; 29058 29059 var copyWithRename = function (obj, oldPath, newPath) { 29060 if (oldPath.length !== newPath.length) { 29061 warn('copyWithRename() expects paths of the same length'); 29062 29063 return; 29064 } else { 29065 for (var i = 0; i < newPath.length - 1; i++) { 29066 if (oldPath[i] !== newPath[i]) { 29067 warn('copyWithRename() expects paths to be the same except for the deepest key'); 29068 29069 return; 29070 } 29071 } 29072 } 29073 29074 return copyWithRenameImpl(obj, oldPath, newPath, 0); 29075 }; 29076 29077 var copyWithSetImpl = function (obj, path, index, value) { 29078 if (index >= path.length) { 29079 return value; 29080 } 29081 29082 var key = path[index]; 29083 var updated = isArray(obj) ? obj.slice() : assign({}, obj); // $FlowFixMe number or string is fine here 29084 29085 updated[key] = copyWithSetImpl(obj[key], path, index + 1, value); 29086 return updated; 29087 }; 29088 29089 var copyWithSet = function (obj, path, value) { 29090 return copyWithSetImpl(obj, path, 0, value); 29091 }; 29092 29093 var findHook = function (fiber, id) { 29094 // For now, the "id" of stateful hooks is just the stateful hook index. 29095 // This may change in the future with e.g. nested hooks. 29096 var currentHook = fiber.memoizedState; 29097 29098 while (currentHook !== null && id > 0) { 29099 currentHook = currentHook.next; 29100 id--; 29101 } 29102 29103 return currentHook; 29104 }; // Support DevTools editable values for useState and useReducer. 29105 29106 29107 overrideHookState = function (fiber, id, path, value) { 29108 var hook = findHook(fiber, id); 29109 29110 if (hook !== null) { 29111 var newState = copyWithSet(hook.memoizedState, path, value); 29112 hook.memoizedState = newState; 29113 hook.baseState = newState; // We aren't actually adding an update to the queue, 29114 // because there is no update we can add for useReducer hooks that won't trigger an error. 29115 // (There's no appropriate action type for DevTools overrides.) 29116 // As a result though, React will see the scheduled update as a noop and bailout. 29117 // Shallow cloning props works as a workaround for now to bypass the bailout check. 29118 29119 fiber.memoizedProps = assign({}, fiber.memoizedProps); 29120 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29121 29122 if (root !== null) { 29123 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29124 } 29125 } 29126 }; 29127 29128 overrideHookStateDeletePath = function (fiber, id, path) { 29129 var hook = findHook(fiber, id); 29130 29131 if (hook !== null) { 29132 var newState = copyWithDelete(hook.memoizedState, path); 29133 hook.memoizedState = newState; 29134 hook.baseState = newState; // We aren't actually adding an update to the queue, 29135 // because there is no update we can add for useReducer hooks that won't trigger an error. 29136 // (There's no appropriate action type for DevTools overrides.) 29137 // As a result though, React will see the scheduled update as a noop and bailout. 29138 // Shallow cloning props works as a workaround for now to bypass the bailout check. 29139 29140 fiber.memoizedProps = assign({}, fiber.memoizedProps); 29141 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29142 29143 if (root !== null) { 29144 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29145 } 29146 } 29147 }; 29148 29149 overrideHookStateRenamePath = function (fiber, id, oldPath, newPath) { 29150 var hook = findHook(fiber, id); 29151 29152 if (hook !== null) { 29153 var newState = copyWithRename(hook.memoizedState, oldPath, newPath); 29154 hook.memoizedState = newState; 29155 hook.baseState = newState; // We aren't actually adding an update to the queue, 29156 // because there is no update we can add for useReducer hooks that won't trigger an error. 29157 // (There's no appropriate action type for DevTools overrides.) 29158 // As a result though, React will see the scheduled update as a noop and bailout. 29159 // Shallow cloning props works as a workaround for now to bypass the bailout check. 29160 29161 fiber.memoizedProps = assign({}, fiber.memoizedProps); 29162 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29163 29164 if (root !== null) { 29165 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29166 } 29167 } 29168 }; // Support DevTools props for function components, forwardRef, memo, host components, etc. 29169 29170 29171 overrideProps = function (fiber, path, value) { 29172 fiber.pendingProps = copyWithSet(fiber.memoizedProps, path, value); 29173 29174 if (fiber.alternate) { 29175 fiber.alternate.pendingProps = fiber.pendingProps; 29176 } 29177 29178 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29179 29180 if (root !== null) { 29181 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29182 } 29183 }; 29184 29185 overridePropsDeletePath = function (fiber, path) { 29186 fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path); 29187 29188 if (fiber.alternate) { 29189 fiber.alternate.pendingProps = fiber.pendingProps; 29190 } 29191 29192 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29193 29194 if (root !== null) { 29195 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29196 } 29197 }; 29198 29199 overridePropsRenamePath = function (fiber, oldPath, newPath) { 29200 fiber.pendingProps = copyWithRename(fiber.memoizedProps, oldPath, newPath); 29201 29202 if (fiber.alternate) { 29203 fiber.alternate.pendingProps = fiber.pendingProps; 29204 } 29205 29206 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29207 29208 if (root !== null) { 29209 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29210 } 29211 }; 29212 29213 scheduleUpdate = function (fiber) { 29214 var root = enqueueConcurrentRenderForLane(fiber, SyncLane); 29215 29216 if (root !== null) { 29217 scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp); 29218 } 29219 }; 29220 29221 setErrorHandler = function (newShouldErrorImpl) { 29222 shouldErrorImpl = newShouldErrorImpl; 29223 }; 29224 29225 setSuspenseHandler = function (newShouldSuspendImpl) { 29226 shouldSuspendImpl = newShouldSuspendImpl; 29227 }; 29228 } 29229 29230 function findHostInstanceByFiber(fiber) { 29231 var hostFiber = findCurrentHostFiber(fiber); 29232 29233 if (hostFiber === null) { 29234 return null; 29235 } 29236 29237 return hostFiber.stateNode; 29238 } 29239 29240 function emptyFindFiberByHostInstance(instance) { 29241 return null; 29242 } 29243 29244 function getCurrentFiberForDevTools() { 29245 return current; 29246 } 29247 29248 function injectIntoDevTools(devToolsConfig) { 29249 var findFiberByHostInstance = devToolsConfig.findFiberByHostInstance; 29250 var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; 29251 return injectInternals({ 29252 bundleType: devToolsConfig.bundleType, 29253 version: devToolsConfig.version, 29254 rendererPackageName: devToolsConfig.rendererPackageName, 29255 rendererConfig: devToolsConfig.rendererConfig, 29256 overrideHookState: overrideHookState, 29257 overrideHookStateDeletePath: overrideHookStateDeletePath, 29258 overrideHookStateRenamePath: overrideHookStateRenamePath, 29259 overrideProps: overrideProps, 29260 overridePropsDeletePath: overridePropsDeletePath, 29261 overridePropsRenamePath: overridePropsRenamePath, 29262 setErrorHandler: setErrorHandler, 29263 setSuspenseHandler: setSuspenseHandler, 29264 scheduleUpdate: scheduleUpdate, 29265 currentDispatcherRef: ReactCurrentDispatcher, 29266 findHostInstanceByFiber: findHostInstanceByFiber, 29267 findFiberByHostInstance: findFiberByHostInstance || emptyFindFiberByHostInstance, 29268 // React Refresh 29269 findHostInstancesForRefresh: findHostInstancesForRefresh , 29270 scheduleRefresh: scheduleRefresh , 29271 scheduleRoot: scheduleRoot , 29272 setRefreshHandler: setRefreshHandler , 29273 // Enables DevTools to append owner stacks to error messages in DEV mode. 29274 getCurrentFiber: getCurrentFiberForDevTools , 29275 // Enables DevTools to detect reconciler version rather than renderer version 29276 // which may not match for third party renderers. 29277 reconcilerVersion: ReactVersion 29278 }); 29279 } 29280 29281 /* global reportError */ 29282 29283 var defaultOnRecoverableError = typeof reportError === 'function' ? // In modern browsers, reportError will dispatch an error event, 29284 // emulating an uncaught JavaScript error. 29285 reportError : function (error) { 29286 // In older browsers and test environments, fallback to console.error. 29287 // eslint-disable-next-line react-internal/no-production-logging 29288 console['error'](error); 29289 }; 29290 29291 function ReactDOMRoot(internalRoot) { 29292 this._internalRoot = internalRoot; 29293 } 29294 29295 ReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render = function (children) { 29296 var root = this._internalRoot; 29297 29298 if (root === null) { 29299 throw new Error('Cannot update an unmounted root.'); 29300 } 29301 29302 { 29303 if (typeof arguments[1] === 'function') { 29304 error('render(...): does not support the second callback argument. ' + 'To execute a side effect after rendering, declare it in a component body with useEffect().'); 29305 } else if (isValidContainer(arguments[1])) { 29306 error('You passed a container to the second argument of root.render(...). ' + "You don't need to pass it again since you already passed it to create the root."); 29307 } else if (typeof arguments[1] !== 'undefined') { 29308 error('You passed a second argument to root.render(...) but it only accepts ' + 'one argument.'); 29309 } 29310 29311 var container = root.containerInfo; 29312 29313 if (container.nodeType !== COMMENT_NODE) { 29314 var hostInstance = findHostInstanceWithNoPortals(root.current); 29315 29316 if (hostInstance) { 29317 if (hostInstance.parentNode !== container) { 29318 error('render(...): It looks like the React-rendered content of the ' + 'root container was removed without using React. This is not ' + 'supported and will cause errors. Instead, call ' + "root.unmount() to empty a root's container."); 29319 } 29320 } 29321 } 29322 } 29323 29324 updateContainer(children, root, null, null); 29325 }; 29326 29327 ReactDOMHydrationRoot.prototype.unmount = ReactDOMRoot.prototype.unmount = function () { 29328 { 29329 if (typeof arguments[0] === 'function') { 29330 error('unmount(...): does not support a callback argument. ' + 'To execute a side effect after rendering, declare it in a component body with useEffect().'); 29331 } 29332 } 29333 29334 var root = this._internalRoot; 29335 29336 if (root !== null) { 29337 this._internalRoot = null; 29338 var container = root.containerInfo; 29339 29340 { 29341 if (isAlreadyRendering()) { 29342 error('Attempted to synchronously unmount a root while React was already ' + 'rendering. React cannot finish unmounting the root until the ' + 'current render has completed, which may lead to a race condition.'); 29343 } 29344 } 29345 29346 flushSync(function () { 29347 updateContainer(null, root, null, null); 29348 }); 29349 unmarkContainerAsRoot(container); 29350 } 29351 }; 29352 29353 function createRoot(container, options) { 29354 if (!isValidContainer(container)) { 29355 throw new Error('createRoot(...): Target container is not a DOM element.'); 29356 } 29357 29358 warnIfReactDOMContainerInDEV(container); 29359 var isStrictMode = false; 29360 var concurrentUpdatesByDefaultOverride = false; 29361 var identifierPrefix = ''; 29362 var onRecoverableError = defaultOnRecoverableError; 29363 var transitionCallbacks = null; 29364 29365 if (options !== null && options !== undefined) { 29366 { 29367 if (options.hydrate) { 29368 warn('hydrate through createRoot is deprecated. Use ReactDOMClient.hydrateRoot(container, <App />) instead.'); 29369 } else { 29370 if (typeof options === 'object' && options !== null && options.$$typeof === REACT_ELEMENT_TYPE) { 29371 error('You passed a JSX element to createRoot. You probably meant to ' + 'call root.render instead. ' + 'Example usage:\n\n' + ' let root = createRoot(domContainer);\n' + ' root.render(<App />);'); 29372 } 29373 } 29374 } 29375 29376 if (options.unstable_strictMode === true) { 29377 isStrictMode = true; 29378 } 29379 29380 if (options.identifierPrefix !== undefined) { 29381 identifierPrefix = options.identifierPrefix; 29382 } 29383 29384 if (options.onRecoverableError !== undefined) { 29385 onRecoverableError = options.onRecoverableError; 29386 } 29387 29388 if (options.transitionCallbacks !== undefined) { 29389 transitionCallbacks = options.transitionCallbacks; 29390 } 29391 } 29392 29393 var root = createContainer(container, ConcurrentRoot, null, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); 29394 markContainerAsRoot(root.current, container); 29395 var rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container; 29396 listenToAllSupportedEvents(rootContainerElement); 29397 return new ReactDOMRoot(root); 29398 } 29399 29400 function ReactDOMHydrationRoot(internalRoot) { 29401 this._internalRoot = internalRoot; 29402 } 29403 29404 function scheduleHydration(target) { 29405 if (target) { 29406 queueExplicitHydrationTarget(target); 29407 } 29408 } 29409 29410 ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = scheduleHydration; 29411 function hydrateRoot(container, initialChildren, options) { 29412 if (!isValidContainer(container)) { 29413 throw new Error('hydrateRoot(...): Target container is not a DOM element.'); 29414 } 29415 29416 warnIfReactDOMContainerInDEV(container); 29417 29418 { 29419 if (initialChildren === undefined) { 29420 error('Must provide initial children as second argument to hydrateRoot. ' + 'Example usage: hydrateRoot(domContainer, <App />)'); 29421 } 29422 } // For now we reuse the whole bag of options since they contain 29423 // the hydration callbacks. 29424 29425 29426 var hydrationCallbacks = options != null ? options : null; // TODO: Delete this option 29427 29428 var mutableSources = options != null && options.hydratedSources || null; 29429 var isStrictMode = false; 29430 var concurrentUpdatesByDefaultOverride = false; 29431 var identifierPrefix = ''; 29432 var onRecoverableError = defaultOnRecoverableError; 29433 29434 if (options !== null && options !== undefined) { 29435 if (options.unstable_strictMode === true) { 29436 isStrictMode = true; 29437 } 29438 29439 if (options.identifierPrefix !== undefined) { 29440 identifierPrefix = options.identifierPrefix; 29441 } 29442 29443 if (options.onRecoverableError !== undefined) { 29444 onRecoverableError = options.onRecoverableError; 29445 } 29446 } 29447 29448 var root = createHydrationContainer(initialChildren, null, container, ConcurrentRoot, hydrationCallbacks, isStrictMode, concurrentUpdatesByDefaultOverride, identifierPrefix, onRecoverableError); 29449 markContainerAsRoot(root.current, container); // This can't be a comment node since hydration doesn't work on comment nodes anyway. 29450 29451 listenToAllSupportedEvents(container); 29452 29453 if (mutableSources) { 29454 for (var i = 0; i < mutableSources.length; i++) { 29455 var mutableSource = mutableSources[i]; 29456 registerMutableSourceForHydration(root, mutableSource); 29457 } 29458 } 29459 29460 return new ReactDOMHydrationRoot(root); 29461 } 29462 function isValidContainer(node) { 29463 return !!(node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || !disableCommentsAsDOMContainers )); 29464 } // TODO: Remove this function which also includes comment nodes. 29465 // We only use it in places that are currently more relaxed. 29466 29467 function isValidContainerLegacy(node) { 29468 return !!(node && (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE || node.nodeType === COMMENT_NODE && node.nodeValue === ' react-mount-point-unstable ')); 29469 } 29470 29471 function warnIfReactDOMContainerInDEV(container) { 29472 { 29473 if (container.nodeType === ELEMENT_NODE && container.tagName && container.tagName.toUpperCase() === 'BODY') { 29474 error('createRoot(): Creating roots directly with document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try using a container element created ' + 'for your app.'); 29475 } 29476 29477 if (isContainerMarkedAsRoot(container)) { 29478 if (container._reactRootContainer) { 29479 error('You are calling ReactDOMClient.createRoot() on a container that was previously ' + 'passed to ReactDOM.render(). This is not supported.'); 29480 } else { 29481 error('You are calling ReactDOMClient.createRoot() on a container that ' + 'has already been passed to createRoot() before. Instead, call ' + 'root.render() on the existing root instead if you want to update it.'); 29482 } 29483 } 29484 } 29485 } 29486 29487 var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; 29488 var topLevelUpdateWarnings; 29489 29490 { 29491 topLevelUpdateWarnings = function (container) { 29492 if (container._reactRootContainer && container.nodeType !== COMMENT_NODE) { 29493 var hostInstance = findHostInstanceWithNoPortals(container._reactRootContainer.current); 29494 29495 if (hostInstance) { 29496 if (hostInstance.parentNode !== container) { 29497 error('render(...): It looks like the React-rendered content of this ' + 'container was removed without using React. This is not ' + 'supported and will cause errors. Instead, call ' + 'ReactDOM.unmountComponentAtNode to empty a container.'); 29498 } 29499 } 29500 } 29501 29502 var isRootRenderedBySomeReact = !!container._reactRootContainer; 29503 var rootEl = getReactRootElementInContainer(container); 29504 var hasNonRootReactChild = !!(rootEl && getInstanceFromNode(rootEl)); 29505 29506 if (hasNonRootReactChild && !isRootRenderedBySomeReact) { 29507 error('render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.'); 29508 } 29509 29510 if (container.nodeType === ELEMENT_NODE && container.tagName && container.tagName.toUpperCase() === 'BODY') { 29511 error('render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.'); 29512 } 29513 }; 29514 } 29515 29516 function getReactRootElementInContainer(container) { 29517 if (!container) { 29518 return null; 29519 } 29520 29521 if (container.nodeType === DOCUMENT_NODE) { 29522 return container.documentElement; 29523 } else { 29524 return container.firstChild; 29525 } 29526 } 29527 29528 function noopOnRecoverableError() {// This isn't reachable because onRecoverableError isn't called in the 29529 // legacy API. 29530 } 29531 29532 function legacyCreateRootFromDOMContainer(container, initialChildren, parentComponent, callback, isHydrationContainer) { 29533 if (isHydrationContainer) { 29534 if (typeof callback === 'function') { 29535 var originalCallback = callback; 29536 29537 callback = function () { 29538 var instance = getPublicRootInstance(root); 29539 originalCallback.call(instance); 29540 }; 29541 } 29542 29543 var root = createHydrationContainer(initialChildren, callback, container, LegacyRoot, null, // hydrationCallbacks 29544 false, // isStrictMode 29545 false, // concurrentUpdatesByDefaultOverride, 29546 '', // identifierPrefix 29547 noopOnRecoverableError); 29548 container._reactRootContainer = root; 29549 markContainerAsRoot(root.current, container); 29550 var rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container; 29551 listenToAllSupportedEvents(rootContainerElement); 29552 flushSync(); 29553 return root; 29554 } else { 29555 // First clear any existing content. 29556 var rootSibling; 29557 29558 while (rootSibling = container.lastChild) { 29559 container.removeChild(rootSibling); 29560 } 29561 29562 if (typeof callback === 'function') { 29563 var _originalCallback = callback; 29564 29565 callback = function () { 29566 var instance = getPublicRootInstance(_root); 29567 29568 _originalCallback.call(instance); 29569 }; 29570 } 29571 29572 var _root = createContainer(container, LegacyRoot, null, // hydrationCallbacks 29573 false, // isStrictMode 29574 false, // concurrentUpdatesByDefaultOverride, 29575 '', // identifierPrefix 29576 noopOnRecoverableError); 29577 29578 container._reactRootContainer = _root; 29579 markContainerAsRoot(_root.current, container); 29580 29581 var _rootContainerElement = container.nodeType === COMMENT_NODE ? container.parentNode : container; 29582 29583 listenToAllSupportedEvents(_rootContainerElement); // Initial mount should not be batched. 29584 29585 flushSync(function () { 29586 updateContainer(initialChildren, _root, parentComponent, callback); 29587 }); 29588 return _root; 29589 } 29590 } 29591 29592 function warnOnInvalidCallback$1(callback, callerName) { 29593 { 29594 if (callback !== null && typeof callback !== 'function') { 29595 error('%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback); 29596 } 29597 } 29598 } 29599 29600 function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) { 29601 { 29602 topLevelUpdateWarnings(container); 29603 warnOnInvalidCallback$1(callback === undefined ? null : callback, 'render'); 29604 } 29605 29606 var maybeRoot = container._reactRootContainer; 29607 var root; 29608 29609 if (!maybeRoot) { 29610 // Initial mount 29611 root = legacyCreateRootFromDOMContainer(container, children, parentComponent, callback, forceHydrate); 29612 } else { 29613 root = maybeRoot; 29614 29615 if (typeof callback === 'function') { 29616 var originalCallback = callback; 29617 29618 callback = function () { 29619 var instance = getPublicRootInstance(root); 29620 originalCallback.call(instance); 29621 }; 29622 } // Update 29623 29624 29625 updateContainer(children, root, parentComponent, callback); 29626 } 29627 29628 return getPublicRootInstance(root); 29629 } 29630 29631 function findDOMNode(componentOrElement) { 29632 { 29633 var owner = ReactCurrentOwner$3.current; 29634 29635 if (owner !== null && owner.stateNode !== null) { 29636 var warnedAboutRefsInRender = owner.stateNode._warnedAboutRefsInRender; 29637 29638 if (!warnedAboutRefsInRender) { 29639 error('%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', getComponentNameFromType(owner.type) || 'A component'); 29640 } 29641 29642 owner.stateNode._warnedAboutRefsInRender = true; 29643 } 29644 } 29645 29646 if (componentOrElement == null) { 29647 return null; 29648 } 29649 29650 if (componentOrElement.nodeType === ELEMENT_NODE) { 29651 return componentOrElement; 29652 } 29653 29654 { 29655 return findHostInstanceWithWarning(componentOrElement, 'findDOMNode'); 29656 } 29657 } 29658 function hydrate(element, container, callback) { 29659 { 29660 error('ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot ' + 'instead. Until you switch to the new API, your app will behave as ' + "if it's running React 17. Learn " + 'more: https://reactjs.org/link/switch-to-createroot'); 29661 } 29662 29663 if (!isValidContainerLegacy(container)) { 29664 throw new Error('Target container is not a DOM element.'); 29665 } 29666 29667 { 29668 var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined; 29669 29670 if (isModernRoot) { 29671 error('You are calling ReactDOM.hydrate() on a container that was previously ' + 'passed to ReactDOMClient.createRoot(). This is not supported. ' + 'Did you mean to call hydrateRoot(container, element)?'); 29672 } 29673 } // TODO: throw or warn if we couldn't hydrate? 29674 29675 29676 return legacyRenderSubtreeIntoContainer(null, element, container, true, callback); 29677 } 29678 function render(element, container, callback) { 29679 { 29680 error('ReactDOM.render is no longer supported in React 18. Use createRoot ' + 'instead. Until you switch to the new API, your app will behave as ' + "if it's running React 17. Learn " + 'more: https://reactjs.org/link/switch-to-createroot'); 29681 } 29682 29683 if (!isValidContainerLegacy(container)) { 29684 throw new Error('Target container is not a DOM element.'); 29685 } 29686 29687 { 29688 var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined; 29689 29690 if (isModernRoot) { 29691 error('You are calling ReactDOM.render() on a container that was previously ' + 'passed to ReactDOMClient.createRoot(). This is not supported. ' + 'Did you mean to call root.render(element)?'); 29692 } 29693 } 29694 29695 return legacyRenderSubtreeIntoContainer(null, element, container, false, callback); 29696 } 29697 function unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) { 29698 { 29699 error('ReactDOM.unstable_renderSubtreeIntoContainer() is no longer supported ' + 'in React 18. Consider using a portal instead. Until you switch to ' + "the createRoot API, your app will behave as if it's running React " + '17. Learn more: https://reactjs.org/link/switch-to-createroot'); 29700 } 29701 29702 if (!isValidContainerLegacy(containerNode)) { 29703 throw new Error('Target container is not a DOM element.'); 29704 } 29705 29706 if (parentComponent == null || !has(parentComponent)) { 29707 throw new Error('parentComponent must be a valid React Component'); 29708 } 29709 29710 return legacyRenderSubtreeIntoContainer(parentComponent, element, containerNode, false, callback); 29711 } 29712 function unmountComponentAtNode(container) { 29713 if (!isValidContainerLegacy(container)) { 29714 throw new Error('unmountComponentAtNode(...): Target container is not a DOM element.'); 29715 } 29716 29717 { 29718 var isModernRoot = isContainerMarkedAsRoot(container) && container._reactRootContainer === undefined; 29719 29720 if (isModernRoot) { 29721 error('You are calling ReactDOM.unmountComponentAtNode() on a container that was previously ' + 'passed to ReactDOMClient.createRoot(). This is not supported. Did you mean to call root.unmount()?'); 29722 } 29723 } 29724 29725 if (container._reactRootContainer) { 29726 { 29727 var rootEl = getReactRootElementInContainer(container); 29728 var renderedByDifferentReact = rootEl && !getInstanceFromNode(rootEl); 29729 29730 if (renderedByDifferentReact) { 29731 error("unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by another copy of React.'); 29732 } 29733 } // Unmount should not be batched. 29734 29735 29736 flushSync(function () { 29737 legacyRenderSubtreeIntoContainer(null, null, container, false, function () { 29738 // $FlowFixMe This should probably use `delete container._reactRootContainer` 29739 container._reactRootContainer = null; 29740 unmarkContainerAsRoot(container); 29741 }); 29742 }); // If you call unmountComponentAtNode twice in quick succession, you'll 29743 // get `true` twice. That's probably fine? 29744 29745 return true; 29746 } else { 29747 { 29748 var _rootEl = getReactRootElementInContainer(container); 29749 29750 var hasNonRootReactChild = !!(_rootEl && getInstanceFromNode(_rootEl)); // Check if the container itself is a React root node. 29751 29752 var isContainerReactRoot = container.nodeType === ELEMENT_NODE && isValidContainerLegacy(container.parentNode) && !!container.parentNode._reactRootContainer; 29753 29754 if (hasNonRootReactChild) { 29755 error("unmountComponentAtNode(): The node you're attempting to unmount " + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.'); 29756 } 29757 } 29758 29759 return false; 29760 } 29761 } 29762 29763 setAttemptSynchronousHydration(attemptSynchronousHydration$1); 29764 setAttemptContinuousHydration(attemptContinuousHydration$1); 29765 setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority$1); 29766 setGetCurrentUpdatePriority(getCurrentUpdatePriority); 29767 setAttemptHydrationAtPriority(runWithPriority); 29768 29769 { 29770 if (typeof Map !== 'function' || // $FlowIssue Flow incorrectly thinks Map has no prototype 29771 Map.prototype == null || typeof Map.prototype.forEach !== 'function' || typeof Set !== 'function' || // $FlowIssue Flow incorrectly thinks Set has no prototype 29772 Set.prototype == null || typeof Set.prototype.clear !== 'function' || typeof Set.prototype.forEach !== 'function') { 29773 error('React depends on Map and Set built-in types. Make sure that you load a ' + 'polyfill in older browsers. https://reactjs.org/link/react-polyfills'); 29774 } 29775 } 29776 29777 setRestoreImplementation(restoreControlledState$3); 29778 setBatchingImplementation(batchedUpdates$1, discreteUpdates, flushSync); 29779 29780 function createPortal$1(children, container) { 29781 var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; 29782 29783 if (!isValidContainer(container)) { 29784 throw new Error('Target container is not a DOM element.'); 29785 } // TODO: pass ReactDOM portal implementation as third argument 29786 // $FlowFixMe The Flow type is opaque but there's no way to actually create it. 29787 29788 29789 return createPortal(children, container, null, key); 29790 } 29791 29792 function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) { 29793 return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback); 29794 } 29795 29796 var Internals = { 29797 usingClientEntryPoint: false, 29798 // Keep in sync with ReactTestUtils.js. 29799 // This is an array for better minification. 29800 Events: [getInstanceFromNode, getNodeFromInstance, getFiberCurrentPropsFromNode, enqueueStateRestore, restoreStateIfNeeded, batchedUpdates$1] 29801 }; 29802 29803 function createRoot$1(container, options) { 29804 { 29805 if (!Internals.usingClientEntryPoint && !true) { 29806 error('You are importing createRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".'); 29807 } 29808 } 29809 29810 return createRoot(container, options); 29811 } 29812 29813 function hydrateRoot$1(container, initialChildren, options) { 29814 { 29815 if (!Internals.usingClientEntryPoint && !true) { 29816 error('You are importing hydrateRoot from "react-dom" which is not supported. ' + 'You should instead import it from "react-dom/client".'); 29817 } 29818 } 29819 29820 return hydrateRoot(container, initialChildren, options); 29821 } // Overload the definition to the two valid signatures. 29822 // Warning, this opts-out of checking the function body. 29823 29824 29825 // eslint-disable-next-line no-redeclare 29826 function flushSync$1(fn) { 29827 { 29828 if (isAlreadyRendering()) { 29829 error('flushSync was called from inside a lifecycle method. React cannot ' + 'flush when React is already rendering. Consider moving this call to ' + 'a scheduler task or micro task.'); 29830 } 29831 } 29832 29833 return flushSync(fn); 29834 } 29835 var foundDevTools = injectIntoDevTools({ 29836 findFiberByHostInstance: getClosestInstanceFromNode, 29837 bundleType: 1 , 29838 version: ReactVersion, 29839 rendererPackageName: 'react-dom' 29840 }); 29841 29842 { 29843 if (!foundDevTools && canUseDOM && window.top === window.self) { 29844 // If we're in Chrome or Firefox, provide a download link if not installed. 29845 if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) { 29846 var protocol = window.location.protocol; // Don't warn in exotic cases like chrome-extension://. 29847 29848 if (/^(https?|file):$/.test(protocol)) { 29849 // eslint-disable-next-line react-internal/no-production-logging 29850 console.info('%cDownload the React DevTools ' + 'for a better development experience: ' + 'https://reactjs.org/link/react-devtools' + (protocol === 'file:' ? '\nYou might need to use a local HTTP server (instead of file://): ' + 'https://reactjs.org/link/react-devtools-faq' : ''), 'font-weight:bold'); 29851 } 29852 } 29853 } 29854 } 29855 29856 exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals; 29857 exports.createPortal = createPortal$1; 29858 exports.createRoot = createRoot$1; 29859 exports.findDOMNode = findDOMNode; 29860 exports.flushSync = flushSync$1; 29861 exports.hydrate = hydrate; 29862 exports.hydrateRoot = hydrateRoot$1; 29863 exports.render = render; 29864 exports.unmountComponentAtNode = unmountComponentAtNode; 29865 exports.unstable_batchedUpdates = batchedUpdates$1; 29866 exports.unstable_renderSubtreeIntoContainer = renderSubtreeIntoContainer; 29867 exports.version = ReactVersion; 29868 29869})));